相信本站的大部分读者都知道OpenWRT与ART:OpenWRT是一款基于Linux的开源无线路由器系统,目前广泛应用于很多厂商的无线设备;ART是Atheros Radio Test的简写,用于测试各种基于Qualcomm Atheros芯片设备的射频指标。近期有朋友寻求OpenWRT中的ART驱动程序, 笔者费了九牛二虎之力终于将其搞定,在此做简要总结,以便后续查阅。
1. 基于已有经验,移植ART驱动程序必须指定相应的内核路径与Toolchain路径,修改makefile.artmod如下
KDIR := /home/tom/openwrt/trunk/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.18.7 PWD := $(shell pwd) ROOTDIR := $(PWD)/modules # Default architecture is MIPS ARC :=mips CROSS_CC :=/home/tom/openwrt/trunk/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-uclibc-
2. 未作任何代码的更改情况下,开始编译。
3. 出现error: unknown field ‘ioctl’ specified in initializer,此前在移植i.MX6 ART驱动程序时已经遇到过类似问题,在http://www.zencheer.com/imx6-porting-art/一文中有介绍,修改modules/dk_func.c中dk_fops结构体中的ioctl为compat_ioctl,再次编译未报出ioctl的错误。
3. 出现error: ‘SPIN_LOCK_UNLOCKED’ undeclared here (not in a function),修改modules/dk_event.c中的
spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
为
DEFINE_SPINLOCK(driver_lock);
4. 再次编译,顺利通过,在modules目录下出现了art.ko。
5. 将art.ko上传至web服务器,并使用wget命令下载至DUT中,并使用insmod art.ko命令插入内核模块并运行nart.out,未出现任何异常。
6. 使用artgui Load DUT,出现如下错误:
deviceInit devIndex=0 device_fn=0 pdkInfo=0 Opening device /dev/dk0 Error: get version ioctl failed ! < 6006 ERROR Anwi driver load error. < 7502 CONTROL OFF < 7504 INFO |set|devid|| < 7504 INFO |set|mac|| < 7504 INFO |set|customer|| < 7506 CONTROL DONE load devid=-1; caldata=auto;
截图如下
7. 又出现了可怕的错误“Error: get version ioctl failed !”,这个错误曾在我移植i.MX6 ART驱动程序时折磨了我很多天,同样记录在http://www.zencheer.com/imx6-porting-art/一文中,当时更换为高版本ART后问题得到解决,然而这一次我采用同样方法却完全不奏效。既然无法避开,那就正面面对,彻查此问题。
8. 查看高版本ART代码modules/dk_func.c中的dk_fops结构体,如下
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31) static long dk_ioctl_new(struct file *file, unsigned int cmd, unsigned long arg) { struct inode *inode = file->f_path.dentry->d_inode; long ret; ret = dk_ioctl(inode, file, cmd, arg); return ret; } #endif
发现其定义了一个新的ioctl,在内核版本高于2.6.31时生效。
9. 此处引用自:http://blog.csdn.net/cbl709/article/details/7295772
今天调一个程序调了半天,发现应用程序的ioctl的cmd参数传送到驱动程序的ioctl发生改变。而根据《Linux设备驱动》这个cmd应该是不变的。因为在Kernel 2.6.36 中已经完全删除了struct file_operations 中的ioctl 函数指针,取而代之的是unlocked_ioctl ,所以我怀疑二者是不是兼容的。上网查了一些资料,很多文章只是泛泛谈了一下,说在应用程序中ioctl是兼容的,不必变化。而在驱动程序中这个指针函数变了之后最大的影响是参数中少了inode ,所以应用程序ioctl是兼容的,但驱动程序中我们的ioctl函数必须变化,否则就会发生cmd参数的变化。
10. 仿照这段代码,将低版本ART代码modules/dk_func.c中的dk_fops结构体作出修改,如下
static long dk_ioctl_new(struct file *file, unsigned int cmd, unsigned long arg) { struct inode *inode = file->f_path.dentry->d_inode; long ret; ret = dk_ioctl(inode, file, cmd, arg); return ret; } static struct file_operations dk_fops = { owner: THIS_MODULE, open: dk_open, release: dk_release, mmap: dk_mmap, unlocked_ioctl: dk_ioctl_new };
11. 再次编译,下载至DUT,并使用artgui Load DUT,一切正常。