苦逼的我又要往坑里填土了
看了新唐97x提供的iio-adc驱动之后,赶脚太脑壳疼,就自个弄了个简单的驱动,能读数了,有点进步,在这里先记录一下,(小白菜声明,借鉴网络以及官方驱动自个胡搞得,如有冒犯,请告知我大哥——晕哥)
废话少说上代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
//#include <mach/platform.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h> //copy_from_user声明
#include <linux/device.h> //设备文件的自动创建
#include <linux/clk.h>
#include <linux/kernel.h>
//#include <asm/mach/map.h>
#include "../../../arch/arm/mach-nuc970/include/mach/map.h"
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <asm/uaccess.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/cdev.h>
//寄存器地址映射
//#define adcba ioremap(NUC970_PA_ADC,(NUC970_SZ_ADC - 1))
#define CTL 0x00
#define CONF 0x04
#define IER 0x08
#define ISR 0x0C
#define DATA 0x28
//#define ADCCONF (volatile unsigned long *)0xB800A004
static struct clk *adc_clk;//定义adc时钟结构
//static int Device_Open = 0;
static int adc_init(void);
void adc_cleanup(void);
int init_module(void);
void cleanup_module(void);
struct adc_data_misc{
unsigned int data0;
unsigned int data1;
unsigned int data3;
};
struct adc_data{
unsigned int data;
int val;
};
struct adc_pag{
unsigned int buf[127];
};
//static unsigned long *adcbase;
static void adc_read(struct adc_data *adcdata){
unsigned long *adcbase;
adcbase = ioremap(NUC970_PA_ADC,(NUC970_SZ_ADC - 1));
writel(0x3<<6, adcbase + 0x01); //select AGND33 vs AVDD33
writel(1, adcbase + 0x00); //enable AD_EN, disable bandgap
writel(1, adcbase + 0x02);
writel((readl(adcbase + 0x01) | 1<<2), adcbase + 0x01); //enable NACEN
// enable channel
writel((readl(adcbase + 0x01) & ~(0x7 << 3)) | (adcdata->val << 3), adcbase + 0x01);
writel(readl(adcbase + 0x00) | 0x100, adcbase + 0x00);
writel(readl(adcbase + 0x03) | 0x001,adcbase + 0x03);
*(adcbase + 0x03) = 0x401;
//printk("adcbase + 0x03value=%lx\n",*(adcbase + 0x03));
//if(readl(adcbase + 0x03)&0x400){
adcdata->data = readl(adcbase + 0x0A);
//}
//else{
//printk("read error\n");
//}
iounmap(adcbase);
}
#define ADC_CHANNEL0 0x100000
#define ADC_CHANNEL1 0x100001
#define ADC_CHANNEL2 0x100002
#define ADC_CHANNEL3 0x100003
#define ADC_CHANNEL4 0x100004
#define ADC_CHANNEL5 0x100005
#define ADC_CHANNEL6 0x100006
#define ADC_CHANNEL7 0x100007
static long adc_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg){
struct adc_data adcdata;
struct adc_pag adcpag;
struct adc_data_misc adcdatamisc;
switch(cmd){
case ADC_CHANNEL0:
adcdata.val = 0;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
case ADC_CHANNEL1:
adcdata.val = 1;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
case ADC_CHANNEL2:
adcdata.val = 2;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
case ADC_CHANNEL3:
adcdata.val = 3;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
case ADC_CHANNEL4:
adcdata.val = 4;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
case ADC_CHANNEL5:
adcdata.val = 5;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
case ADC_CHANNEL6:
adcdata.val = 6;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
case ADC_CHANNEL7:
adcdata.val = 0;
adc_read(&adcdata);
copy_to_user((struct adc_data *)arg, &adcdata, sizeof(adcdata));
break;
default:
return -1;
}
//copy_from_user(&kindex,(int *)arg,sizeof(kindex));
return 0;
}
struct file_operations adc_ops =
{
.owner = THIS_MODULE,
.unlocked_ioctl = adc_ioctl
};
static struct cdev adc_cdev;
struct class *cls;
static dev_t dev;
static int adc_init(void){
alloc_chrdev_region(&dev, 0, 1, "xzm");
cdev_init(&adc_cdev, &adc_ops);
cdev_add(&adc_cdev, dev, 1);
cls = class_create(THIS_MODULE, "qiuqiu");
device_create(cls, NULL, dev, NULL, "myadc");
adc_clk = clk_get(NULL,"adc");
if(!adc_clk){
printk("failed to get adc clocl source \n");
return -ENOENT;
}
clk_enable(adc_clk);
printk(" initialized\n");
return 0;
}
void adc_cleanup(void){
if(adc_clk){
clk_disable(adc_clk);
clk_put(adc_clk);
adc_clk = NULL;
}
unregister_chrdev_region(dev, 1);
cdev_del(&adc_cdev);
device_destroy(cls, dev);
class_destroy(cls);
}
module_init(adc_init);
module_exit(adc_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("you");
调试程序同样上代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#define ADC_FUYONG 0x10000
#define ADC_CHANNEL0 0x100000
#define ADC_CHANNEL1 0x100001
#define ADC_CHANNEL2 0x100002
#define ADC_CHANNEL3 0x100003
#define ADC_CHANNEL4 0x100004
#define ADC_CHANNEL5 0x100005
#define ADC_CHANNEL6 0x100006
#define ADC_CHANNEL7 0x100007
struct adc_data {
unsigned int x;
};
struct adc_data_misc{
unsigned int data0;
unsigned int data1;
unsigned int data3;
};
struct adc_pag{
int buf[127];
};
int main(void)
{
int fd,i,j,cmd;
int buf[127];
struct adc_data info; //分配用户缓冲区
struct adc_data_misc miscinfo;
struct adc_pag adcpag;
info.x=1;
i = 1;
fd = open("/dev/myadc", O_RDWR);
if (fd < 0){
printf("file error\n");
return -1;
}
printf("info.x=%d\n",info.x);
printf("please input channel:\n");
// scanf("%d",&cmd);
cmd = 0;
switch(cmd){
case 0:
printf("start write\n");
for(j = 0;j < 20;j++){
ioctl(fd,ADC_CHANNEL0, &info);
//buf{i++} = info.x;
buf{ i }= info.x;
i = i + 1;
printf("%d ", info.x);
ioctl(fd,ADC_CHANNEL1, &info);
//buf{i++} = info.x;
buf {i } = info.x;
i = i + 1;
printf("%d ", info.x);
ioctl(fd, ADC_CHANNEL2, &info);
//buf{i++} = info.x;
buf{ i } = info.x;
i = i + 1;
printf("%d ", info.x);
printf("\n");
//usleep(50000);
}
break;
case 1:
while(1){
ioctl(fd,ADC_CHANNEL1, &info);
printf("%d\n", info.x);
//usleep(50000);
}
break;
case 2:
while(1){
ioctl(fd, ADC_CHANNEL2, &info);
printf("%d\n", info.x);
//usleep(50000);
}
break;
case 3:
while(1){
ioctl(fd, ADC_CHANNEL3, &info);
printf("%d\n", info.x);
//usleep(50000);
}
break;
case 4:
while(1){
ioctl(fd, ADC_CHANNEL4, &info);
printf("%d\n", info.x);
//usleep(50000);
}
break;
case 5:
while(1){
ioctl(fd, ADC_CHANNEL5, &info);
printf("%d\n", info.x);
//usleep(50000);
}
break;
case 6:
while(1){
ioctl(fd, ADC_CHANNEL6, &info);
printf("%d\n", info.x);
//usleep(50000);
}
break;
case 7:
for(i = 0;i < 15;i++){
ioctl(fd, ADC_CHANNEL7, &info);
printf("%d\n", info.x);
//usleep(50000);
}
break;
case 8:
while(1){
ioctl(fd,ADC_FUYONG,&miscinfo);
printf("ADC0=%d\n",miscinfo.data0);
printf("ADC1=%d\n",miscinfo.data1);
printf("ADC3=%d\n",miscinfo.data3);
}
default:
return -1;
}
printf("start read\n");
for(i = 1;i<64;i++){
printf("%d ",buf{i});
}
printf("\n");
close(fd);
return 0;
}
驱动代码写的比较简单,这里之所以要恬不知耻的上传,主要还是给老板(晕哥)打工没办法,大佬们,觉得辣眼睛的话,自觉忽略
驱动是有些问题的,还待完善,大佬们给下建议,用示波器抓的图会让老板上传
最近在97X上要做高频的数据采集,用的是qt,由于刚开始太清楚linux内核的任务调度机制,
也是本着偷懒的原则就在qt程序里直接用system执行shell命令,
结果用示波器测试发现,单单是gpio的一次拉高置低的时间就耗去了10ms,
龟龟,对于后面用到的ad那结果可想,这个懒还是偷不得的啊。
于是就用了mmap和fwrite测了一下,mmap操作一个io拉高拉低,是200纳秒,fwrite是400纳秒,
测试代码如下,虽然网上很多例子,但还是贴出来,以方便自己以后查阅,同时也是想linux小白进军的一步
mapp_gpio.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define GPIO_BASE (0xB8003000)
#define MAP_SIZE 0x32
static int dev_fd;
int main(void){
char dev_name[] = "/dev/mem";
dev_fd = open(dev_name,O_RDWR);
if(dev_fd < 0){
printf("open %s is error\n",dev_name);
return -1;
}
printf("1\n");
unsigned char *gpio_map_base = (unsigned char *)mmap(NULL,MAP_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,dev_fd,GPIO_BASE);
printf("2\n");
*(volatile unsigned int *)(gpio_map_base + 0x0100) |= (0x00000008);
while(1){
*(volatile unsigned int *)(gpio_map_base + 0x0104) |= (0x00000008);
*(volatile unsigned int *)(gpio_map_base + 0x0104) &= (~0x00000008);
}
printf("3\n");
if (dev_fd)
close(dev_fd);
munmap(gpio_map_base,MAP_SIZE);
return 0;
}
对于实时进程,Linux采用了两种调度策略,即FIFO(先来先服务调度)和RR(时间片轮转调度)。
因为实时进程具有一定程度的紧迫性,所以衡量一个 实时进程是否应该运行,Linux采用了一个比较固定的标准。
实时进程的counter只是用来表示该进程的剩余时间片,并不作为衡量它是否值得运行的标 准。
实时进程的counter只是用来表示该进程的剩余时间片,并不作为衡量它是否值得运行的标准,
这和普通进程是有区别的。上面已经看到,每个进程有两 个优先级(动态优先级和实时优先级),
实时优先级就是用来衡量实时进程是否值得运行的。(本段摘抄与百度)
fopen_gpio.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>FILE *fp;
char str[256];
int set_io_hight(void){
char buffer[10];
sprintf(str,"/sys/class/gpio/gpio%d/value",131);
strcpy(buffer,"1");
if ((fp = fopen(str, "rb+")) == NULL) {
printf("Cannot open value file.\n");
}
fwrite(buffer,sizeof(char),sizeof(buffer)-1,fp);
fclose(fp);
return 1;
}
int set_io_low(void){
char buffer[10];
sprintf(str,"/sys/class/gpio/gpio%d/value",131);
if ((fp = fopen(str, "rb+")) == NULL) {
printf("Cannot open value file.\n");
}
strcpy(buffer,"0");
fwrite(buffer,sizeof(char),sizeof(buffer)-1,fp);
fclose(fp);
return 1;
}int main(void)
{
int num=0x47;
if ((fp = fopen("/sys/class/gpio/export", "w")) == NULL) {
printf("Cannot open export file.\n");
exit(1);
}
num = 131;
fprintf(fp, "%d", num);
printf("num = %d\n",num);
fclose(fp);
// linux equivalent code "echo out > direction" to set the port as an input
sprintf(str,"/sys/class/gpio/gpio%d/direction",num);
if ((fp = fopen(str, "rb+")) == NULL) {
printf("Cannot open direction file.\n");
exit(1);
}
fprintf(fp, "out");
fclose(fp);
while(1){
set_io_hight();
set_io_low();
}
return 0;
}
以上程序是本菜鸟参照网上例程,以及新塘的数据手册编码而来
不是太清楚你想表达的意思,emmc分区应实在uboot阶段,至于/dev/下的设备文件是要在内核里注册的,你看看这个https://blog.csdn.net/u011975319/article/details/51803126
烧录方法详见NUC970 Linux BSP快速入门手册.pdf
如果觉得麻烦这里更有视频相送详见972DownloadBin.avi
第一步:
請將 BSP 目錄中的壓縮包複製到 Linux 開發機器上. 並使用以下的命令解壓縮 :
$ tar zxvf nuc970bsp.tar.gz
使用 sudo 來執行安裝腳本 (若是安裝的 Linux 沒有開放 root 權限, 例如 Ubuntu, 則可以
使用本方式來安裝 BSP)
# sudo ./install.sh
以下為整個安裝過程:
Extract arm_linux_4.3.tar.gz to /usr/local/
Wait for a while
Successfully installed tool chain
Install rootfs.tar.gz, applications.tar.gz and linux-3.10.x.tar.gz
Please enter absolute path for installing(eg:/home/<user name>) :
/home/someone/nuc970_bsp//此目录就是制定未来的nuc970的“打包目录”,在此目录下会生成nuc970bsp
Please wait for a while, it will take some time
NUC970 BSP installion complete
第二步:
接下来进入到内核目录
cd nuc970bsp/linux-3.10.x
执行新唐提供的缺省配置
make nuc972_defconfig
接下来就是内核配置
make ARCH=arm menuconfig
General setup --->
[ ] Initial RAM filesystem and RAM disk (initramfs/initrd) support
Boot options --->
(noinitrd root=/dev/mtdblock2 rootfstype=yaffs2 rootflags=inband-tags
console=ttyS0, 115200n8 rdinit=/sbin/init mem=64M) Default kernel command
string
Kernel command line type (Use bootloader arguments if available) ---
>
File systems --->
* Miscellaneous filesystems --->
* yaffs2 file system support
* Autoselect yaffs2 format
* Enable yaffs2 xattr support
Device Drivers --->
Generic Driver Options --->
* Nuvoton NUC970 FMI function selection
Select FMI device to support (Support MTD NAND Flash) --->
-*- Memory Technology Device (MTD) support --->
<> Command line partition table parsing//此项如果默认使用驱动里的配置参数也就是分为三个mtdblock,就不选
*Caching block device access to MTD devices
-*- NAND Device Support --->
-*- Nuvoton NUC970 MTD NAND --->
NUC970 NAND Flash pin selection (Port I) --->
配置完成保存退出
接下来编译内核
make uImage
第三步:属于准备工作
如果提示mkimage找不到,需要进入uboot目录下,按照uboot的编译方式编译一下,然后就会在uboot/tools/目录下出现mkimage
编译uboot的方法参见NUC970 Linux BSP快速入门手册.pdf
mkyaffs工具来源于nuc970/applications/yaffs2utils,进入此目录执行如下操作
make clean
make
制作uImage.bin
sudo mkimage -A arm -O linux -T kernel -C none -a 0x7fc0 -e 0x8000 -d arch/arm/boot/zImage 970image.bin
1. YAFFS2製作In-band tags Image命令如下:(yaffs2的tag儲存在DATA區塊中)
# mkyaffs2 --inband-tags -p 2048 rootfs rootfs_yaffs2.img
注释:
-A 指定CPU的体系结构
-O 指定操作系统类型
-T 指定影像类型
-C 指定影像的压缩方式,这里none表示不压缩
-a 指定映像在内存中的加载地址,映像下载到内存的时候,要按照用mkimage制作映像时,这个参数所制定的地址来下载
-e 指定映像运行的入口点地址,也就是相当于程序的运行地址
-d 指定映像的源文件
根文件系统制作成img格式的方法
./mkyaffs2 --inband-tags -p 2048 rootfs rootfs_yaffs2.img
注释:
inband-tags 相当于一个内部标签
-p 设置设备的页面大小
以上操作因为没有调试uboot所以这里使用的是官方提供的uboot.bin,后面用到的话将会做补充
接下来是qt5.4的的移植过程,这里分开文件写了
首先在linux内核配置 USB support --->
USB Gadget Support --->
USB Gadget Drivers (Android Composite Gadget) --->
这些配置选项小白菜,就不多解释后,大佬们在网上都见过很多,当然还是Android Composite Gadget这个也是内层全志家做好的,在安卓层就有丰富的mtp,我在这里也是默认用的这个,编译烧录,接下来就是在根文件系统里也就是抛掉安卓层,在linux用户层操作mass_storage和acm功能了
enter acm mode
echo 0 > /sys/class/android_usb/android0/enable
echo 1D6b > /sys/class/android_usb/android0/idVendor
echo 0106 > /sys/class/android_usb/android0/idProduct
echo 1 > /sys/class/android_usb/android0/f_acm/instances(听大佬解释这个参数是实例化一个acm设备,最初没加这项时,上位机识别设备,但是显示是未知设备)
echo acm > /sys/class/android_usb/android0/functions
echo 1 > /sys/class/android_usb/android0/enable
enter mass_storage mode
echo 0 > /sys/class/android_usb/android0/enable
echo 1f3a > /sys/class/android_usb/android0/idVendor
echo 1000 > /sys/class/android_usb/android0/idProduct
echo /dev/mmcblk0p9 > /sys/class/android_usb/android0/f_mass_storage/lun/file(将想要作为mass_storage的功能的分区写入文件)
echo mass_storage > /sys/class/android_usb/android0/functions
echo 1 > /sys/class/android_usb/android0/enable
此外mass_storage功能使用的时候,我的上位机会识别出来三个盘符,这个是因为在下位机的/sys/class/android_usb/android0/f_mass_storage/lun lun1 lun2三个有些想只在上位机识别出一个盘符的小伙伴可以更改驱动文件
/drivers/usb/gadget/android.c文件里的mass_storage_function_init函数里的for(i=0;i<config->fsg.nluns;i++),具体的更爱有很多种,小白菜想的很简单就是自己的枚举出来的盘符是三个,只想用一个就让循环少执行两次就好了,嘿嘿
当然还有想使用其他功能的小伙伴,这个可以去看安卓层的init.usb.rc文件里的内容,我就是在哪里找的
首先要确保/system/vendor/modules是否有以下文件,名字是否正确
bcmdhd.ko
bcm43438a0.hcd
fw_bcm43438a0.bin
fw_bcm43438a0_apsta.bin
fw_bcm43438a1.bin
fw_bcm43438a1_apsta.bin
nvram.txt
如果没有的话坑哥在我的一篇帖子里给我讲过介绍过,也有驱动文件,这里用的是ap6212
https://whycan.cn/t_604.html(嘿嘿,帖子用的还不是太好,先将就一下复制吧,晕哥看到的话给改一下吧,)
然后将驱动模块加载,insmod /system/vendor/modules/bcmdhd.ko
执行脚本connect_wx.sh(脚本内容我就不解释了,网上搜解释一大堆)
脚本内容如下
#!/bin/sh
ifconfig wlan0 up
wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf &
udhcpc -i wlan0
#ifconfig wlan0 192.168.1.210
配置/etc/wpa_supplicant.conf内容如下
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=0
ap_scan=1
network={
ssid="xxxxx"
scan_ssid=1
key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
pairwise=TKIP CCMP
group=CCMP TKIP WEP104 WEP40
psk="xxxxxx"
priority=5
}
保存退出,链接即可
出现的问题有时候执行链接脚本的时间比较长,ping的时候需要ping两次,这些问题要具体的查找一下,我感觉硬件的原因比较大
以太网调试首先是驱动加载,这里使用的是r8152.ko这里用的是模块模式,用过A33——vstart方案的老铁也清楚它们的编译步骤,想直接加载进内核的话就去内核里配置一下,同样的我这个小白菜就不多说了此时执行ifconfig -a可以看到
eth0 Link encap:Ethernet HWaddr DA:FB:CA:AD:FD:88
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
gre0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
。。。。。。。。。。。。。。。。。。。。。。
lo Link encap:Local Loopback
LOOPBACK MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
sit0 Link encap:IPv6-in-IPv4
可以看到网卡,子网掩码,还有可能就是网关都没有设置
这个时候单单执行ifconfig还没有任何信息
在这里直接先设置了,免得麻烦
ifconfig eth0 192.168.1.33 netmask 255.255.255.0 up
route add default gw 192.168.1.1
此时执行ifconfig可以看到eth0的信息
网上说lo设备也是不可或缺的,执行此句ifconfig lo 127.0.0.1
(lo(回环设备)。lo设备是Linux系统中第一个网络设备,它在Linux网络中不可或缺,否则系统就无法接收来自本机的数据包)
此时ping 内网没有问题,但是无法ping 外网,原因是没有设置域名
echo nameserver 203.80.96.10 > /etc/resolv.conf
如果大佬们有更好的方法,麻烦赐教给我这个小白菜
由于工作中要去掉安卓层,所以接下来调试GPIO的时候做了以下工作,大神绕过就好
(这部分本人也是粘贴的,同事做的)
GPIO管脚分配
1. 内核源码查看
$ vim linux-3.4/arch/arm/mach-sunxi/include/mach/gpio.h
从中查看以及参考寄存器手册不难看出
GPIO编号 = 组编号BASE + 组内编号
例如: PB3 ==>
32 (PB : SUNXI_PB_BASE 32) + 3(PB3: 3) = 35
即:PB3 的GPIO编号为 35
2. 根据GPIO标号使用GPIO使用
1) 内核配置
① 进入linux-3.4 目录
$ cd linux-3.4
② 复制配置a33_vstar配置选项
$ cp a33_vstar_defconfig .config
③ 修改配置选项
$ make ARCH=arm menuconfig
Device Drivers --->
-*- GPIO Support --->
[ ] /sys/class/gpio/...(sys interface)(目的是为了给用户层提供操作接口,才有接下来的步骤)
选择 *
2) 编译内核,烧录至开发板。 详情点击跳转(嘿嘿,你可别真信了)
3) 运行开发板
① 进入gpio操作的目录下
cd /sys/class/gpio
② 操作方法(以PB3--GPIO编号为35 为例)
导出 /sys/class/gpio# echo 35 > export
取消导出 /sys/class/gpio# echo 35 > unexport
/sys/class/gpio# cd gpio35
设置方向 /sys/class/gpio/gpio35# echo out > direction
注: out --输出 in --输入
查看方向 /sys/class/gpio/gpio35# cat direction
设置输出 /sys/class/gpio/gpio35# echo 1 > value
注: 0 --低电平 1 --高电平
查看输出 /sys/class/gpio/gpio35# cat value
3. 调试过程中遇到的问题
1) GPIO 编号在操作手册中未明确给出,需要自己计算。
2) GPIO在调试时发现个别引脚,存在高电平输出时引脚电压只有 0.5V,如PB3 。
接下来的话会介绍pwm的调试过程
1. 查找LCD设备
cd /sys/devices
find . -name “*lcd*”
经查找和尝试,发现/sys/devices/virtual/disp/disp/attr/lcdbl 为背光控制的操作文件
2. 背光操作方法
命令行: echo 0 > /sys/devices/virtual/disp/disp/attr/lcdbl
背光控制参数范围:0 ~ 255
其中,0表示最暗,255表示最亮。
注意:(去看芯片手册,嘿嘿)
A33_vstar 具有PWM功能的引脚有2个。
15 | LCD-PWM/PWM0 |16 |TP-RST/PWM1/PH1
其中PH0 为LCD背光控制引脚,PH1为触摸屏reset引脚。
小白菜 说:晕哥 说:终于出声了?
这个容易啊, 每次播放前设置一次混音器。设置N次才会有一次发声!
这就尴尬了, 把你的混音器用 tinymix contents 都列出来。
Number of controls: 57
ctl type num name value
0 INT 1 headphone volume control 0 (range 0->63)
1 INT 1 earpiece volume control 0 (range 0->63)
2 INT 1 speaker volume control 0 (range 0->63)
3 INT 1 MIC1_G boost stage output mixer control 3 (range 0->7)
4 INT 1 MIC2_G boost stage output mixer control 3 (range 0->7)
5 INT 1 LINEIN_G boost stage output mixer control3 (range 0->7)
6 INT 1 PHONE_G boost stage output mixer control3 (range 0->7)
7 INT 1 PHONE_PG boost stage output mixer control3 (range 0->7)
8 INT 1 PHONE_NG boost stage output mixer control3 (range 0->7)
9 INT 1 MIC1 boost AMP gain control 4 (range 0->7)
10 INT 1 MIC2 boost AMP gain control 4 (range 0->7)
11 INT 1 Lineout volume control 0 (range 0->63)
12 INT 1 PHONEP-PHONEN pre-amp gain control 4 (range 0->7)
13 INT 1 Phoneout gain control 3 (range 0->7)
14 INT 1 ADC input gain ctrl 3 (range 0->7)
15 BOOL 1 Audio phone out Off
16 BOOL 1 Audio phone in Off
17 BOOL 1 Audio earpiece out Off
18 BOOL 1 Audio headphone out Off
19 BOOL 1 Audio speaker out Off
20 BOOL 1 Audio analog main mic Off
21 BOOL 1 Audio analog headsetmic Off
22 BOOL 1 Audio phone voicerecord Off
23 BOOL 1 Audio phone endcall Off
24 BOOL 1 Audio linein record Off
25 BOOL 1 Audio linein in Off
26 ENUM 1 Speaker Function , headsetspkspk_headsetearpiecebtoutbt_button_voice
27 BOOL 1 Audio digital main mic Off
28 BOOL 1 Audio digital headset mic Off
29 BOOL 1 Audio digital phone out Off
30 BOOL 1 Audio digital phonein Off
31 BOOL 1 Audio digital clk format status Off
32 BOOL 1 Audio bt clk format status Off
33 BOOL 1 Audio bt out Off
34 BOOL 1 Audio analog bt mic Off
35 BOOL 1 Audio analog bt phonein Off
36 BOOL 1 Audio digital bt mic Off
37 BOOL 1 Audio digital bt phonein Off
38 BOOL 1 Audio bt button voice Off
39 BOOL 1 Audio digital bb bt clk format Off
40 BOOL 1 Audio system bt capture flag Off
41 BOOL 1 aif3 loopback Off
42 BOOL 1 aif2 loopback Off
43 BOOL 1 digital_bb_bt Off
44 INT 1 system play_capture set 1 0 (range 0->15)
45 INT 1 system play_capture set 2 0 (range 0->15)
46 BOOL 1 AIF1_AD0L_MXR_SRC AIF1DA0Ldata Off
47 BOOL 1 AIF1_AD0L_MXR_SRC AIF2DACLdata Off
48 BOOL 1 AIF1_AD0L_MXR_SRC ADCLdata Off
49 BOOL 1 AIF1_AD0L_MXR_SRC AIF2DACRdata Off
50 BOOL 1 AIF1_AD0R_MXR_SRC AIF1DA0Rdata Off
51 BOOL 1 AIF1_AD0R_MXR_SRC AIF2DACRdata Off
52 BOOL 1 AIF1_AD0R_MXR_SRC ADCRdata Off
53 BOOL 1 AIF1_AD0R_MXR_SRC AIF2DACLdata Off
54 BOOL 1 Analog cap test disable phonein Off
55 BOOL 1 Analog cap test disable mic1 Off
56 BOOL 1 Analog cap test disable mic2 Off
看是不是混音器开关没打开?
https://whycan.cn/t_489.html
每次使用tinyalsa设置完音量以后,播放音乐(偶尔一次会发出声音,多说情况下没有音),执行完tinyaplay之后再查看音量又变为零了
我帮你查了一下 sunxi_udc.c 与 f_mass_storage.c 耦合了,点此处看 allwinner-zh/linux-3.4-sunxi
https://whycan.cn/files/members/3/QQ20171220105424.png
https://whycan.cn/files/members/3/QQ20171220105429.png
原因: drivers/usb/gadget/f_mass_storage.c 未参与编译链接。
解决方式: menuconfig 把 gadget/mass storage 启用。
恩,谢谢老板,我试试
这种问题确实头大, 讨论的人都找不到,
看看这个链接有没有帮助:
https://www.deyisupport.com/question_answer/dsp_arm/sitara_arm/f/25/t/57715.aspx
贺大哥,我默默地哭了出来,我前几天就看到了这个帖子,很绝望
小白菜 说:晕哥 说:https://github.com/hadess/rtl8723bs
是RTL8723 wifi网卡吗? 看下这个是不是你要的?用的是ap6212
ap6212 firmware:
https://github.com/armbian/firmware/tree/master/ap6212
根文件里已经有这个文件了
https://github.com/hadess/rtl8723bs
是RTL8723 wifi网卡吗? 看下这个是不是你要的?
用的是ap6212
ifconfig报错:SIOCSIFFLAGS: Operation not permitted
应该是这个原因了, 缺少wifi芯片要找的二进制文件。
据说芯片厂商为了节省成本,或者说为了升级方便,把部分ROM程序弄到CPU.
那应该怎么找到二进制文件弄进去呢
1
内核版本linux-zero-4.13.y.zip
基于i2c的AXP203电源管理芯片
在设备书中添加
};
axp209: axp209@34{
reg = <0x34>;
interrupt-parent=<&pio>;
interrupts=<1 2 IRQ_TYPE_EDGE_FALLING>;
/* focaltech,irq-gpio=<&pio 1 2 GPIO_ACTIVE_HIGH>;
focaltech,group-id=<1>;
focaltech,i2c-pull-up;*/
status="okay";
};
};
#include "axp209.dtsi"
&ohci0 {
这一段代表设备树中的i2c上的axp设备,其作用,是用于匹配内核中的AXP驱动,带有设备树的linux内核魅力所在
添加完之后接下来是linux内核的配置
执行make menuconfig
进入
Device Drivers --->
Industrial I/O support ---> 一种新的工业级iio文件,困扰了很久,axp的部分实现依赖于这个文件
Analog to digital converters --->
X-Powers AXP20X and AXP22X ADC driver 配置这个文件很有用途,因为我们使用的驱动就是依赖与此
然后返回到Device Drivers --->
Power supply class support --->
X-Powers AXP20X and AXP22X AC power supply driver
X-Powers AXP20X battery driver
AXP20x power supply driver
编译内核和dtb文件添加到下位机,此时驱动已经加载完成,
期间遇到的问题
具体的驱动文件目录在4.13中直接在内核源码根目录下直接搜索axp然后出来一大堆,一开始一直以为4.13里面没有像3.14那样提供axp驱动,只因为集成了一个iio文件而axp的device就在iio文件中
还有的就是在axp209.dtsi最初定义了初始的启动电压和电流,由于在自己的开发板上供电不足,所以启动到一半的时候会关机,将其注释掉便好,后面优化的的时候可以在根据自身硬件环境的支持去修改适配
具体注释如下
regulators {
/* Default work frequency for buck regulators */
x-powers,dcdc-freq = <1500>;
reg_dcdc2: dcdc2 {
regulator-name = "dcdc2";
};
reg_dcdc3: dcdc3 {
regulator-name = "dcdc3";
};
reg_ldo1: ldo1 {
/* LDO1 is a fixed output regulator */
regulator-always-on;
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1300000>;
regulator-name = "ldo1";
};
reg_ldo2: ldo2 {
regulator-name = "ldo2";
};
reg_ldo3: ldo3 {
regulator-name = "ldo3";
};
reg_ldo4: ldo4 {
regulator-name = "ldo4";
};
将这一段话整个干掉
reg_ldo5: ldo5 {
regulator-name = "ldo5";
status = "disabled";
};
};
用户级的调试接口
路径
/sys/class/power_supply
具体功能接口功能参考axp power驱动应用说明(详细版)v1.1.pdf,这个文件在附录中
有些名字可能不一样,以为这个pdf是旧版本的axp驱动基于3.14的,个人体会是千万不要试图根据这个文档去编译内核,会死的很惨,因为两个内核中自定义的驱动实现函数很多方面都不一样
这里有比较详细的配置信息: 荔枝派Zero V3s开发板入坑教程
这个链接打开还是帖子没变,麻烦站长给网址
晕哥 说:使用buildroot构建文件系统, mplayer视频播放器, Qt运行库等
1. VMWare建立新磁盘,创建一个干净清洁方便复制的环境。
https://whycan.cn/t_251.html2. 下载最新的buildroot稳定版本
https://buildroot.org/download.html
buildroot-2017.02.7.tar.gz3. 配置buildroot 参数, make menuconfig; make
如果不会配置, 就下载下面这个文件,然后把 buildroot-2017.08.1_LicheePi0_V3s.config 拷贝到 buidroot目录成 .config 文件。
buildroot-2017_08_1_LicheePi0_V3s_config.zip4. 执行编译, 生成文件跟文件系统。
5. ___________________
6. ___________________
7. 构建 Qt应用程序
视频地址: https://www.bilibili.com/video/av16396112/我想通过buildroot编译bluez请问编译出来的bluez可以移植到其他的根文件系统里吗,如果能求赐教
第三部怎么生成.config的呢?
使用buildroot构建文件系统, mplayer视频播放器, Qt运行库等
1. VMWare建立新磁盘,创建一个干净清洁方便复制的环境。
https://whycan.cn/t_251.html2. 下载最新的buildroot稳定版本
https://buildroot.org/download.html
buildroot-2017.02.7.tar.gz3. 配置buildroot 参数, make menuconfig; make
如果不会配置, 就下载下面这个文件,然后把 buildroot-2017.08.1_LicheePi0_V3s.config 拷贝到 buidroot目录成 .config 文件。
buildroot-2017_08_1_LicheePi0_V3s_config.zip4. 执行编译, 生成文件跟文件系统。
5. ___________________
6. ___________________
7. 构建 Qt应用程序
视频地址: https://www.bilibili.com/video/av16396112/
我想通过buildroot编译bluez请问编译出来的bluez可以移植到其他的根文件系统里吗,如果能求赐教
硬件上要把GD32的四个串口引脚断开, 从AP6210B的串口飞线, 接USB的FT232R, 挂载到VMWARE+UBUNTU上
执行Broadcom 蓝牙初始化程序:
http://linux-sunxi.org/Cubietruck/Bluetooth
./brcm_patchram_plus -d --patchram /lib/firmware/ap6210/bcm20710a1.hcd --enable_hci --bd_addr 11:22:33:44:55:66 --no2bytes --tosleep 1000 /dev/ttyS1brcm_patchram_plus源码:
http://distro.ibiblio.org/fatdog/source/700/patches/brcm_patchram_plus.cAP6210B/bcm2076b1.hcd 补丁:
https://github.com/thesawolf/android_device_rockchip_rk3188/tree/master/libs/bluetooth/firmware无论做A2DP source还是sink, 声音都卡出翔了, 估计应该是串口的速率没设置好, 博通的蓝牙模组上3Mbps问题不大。
https://whycan.cn/files/members/3/20160218142727628.jpg
https://whycan.cn/files/members/3/20160218142745134.jpg
https://whycan.cn/files/members/3/20160218142913041.jpg
https://whycan.cn/files/members/3/20160218142921614.png
https://whycan.cn/files/members/3/20160218142925541.png
https://whycan.cn/files/members/3/20160218142938287.jpg
https://whycan.cn/files/members/3/20160218142942229.png
https://whycan.cn/files/members/3/20160218142948370.png
https://whycan.cn/files/members/3/20160218142952662.jpg
编译glib的时候遇到过什么问题吗
按群主这个 入坑教程, 看到logo旁边有一行打印信息,
是只这一行吗?
https://whycan.cn/files/members/370/QQ20171122140859.jpg
是内核启动的时候
AXP203手册下载: Allwinner_AXP203_Datasheet_V1_0.pdf
请问你用这份驱动在v3s上使用成功了吗?期间遇到过什么问题