驱动调试方法小结
1 . 调试输入子系统
在调试输入子系统时,input_system,可以通过hexdump 来打开并且实时读取对于输入设备的值,数值关系如下图所示:
每一次按键事件上报后,都会有type为0的EV_SYN同步事件触发。value中的1表示按下,0表示松开,2代表重复类事件,设置按键中断为边沿触发,一次按键会触发两次中断。
如果开启了图形界面,可以打开图形界面的记事本,按相应的按键,可以得到对于的数值
如果没有图形界面,可以执行 cat /dev/tty1 ,然后按相应的按键,可以得到
更改输入设备 exec 0 < /dev/tty1
2. 操作一组寄存器
在设置一些复杂设备的寄存器时,通常需要针对连续地址的多个寄存器进行设置,在Linux环境下,对于有关联关系的多个寄存器的操作,应该采取统一映射,结合将寄存器组合成结构体的方式来操作,这样,操作统一,简洁高效。
例如:对于显示屏相关寄存器的操作,可以构造如下的结构体:
1: struct lcd_regs {
2: unsigned long lcdcon1; //start addrss : 0x4D00_0000
3: unsigned long lcdcon2;
4: unsigned long lcdcon3;
5: unsigned long lcdcon4;
6: unsigned long lcdcon5;
7: unsigned long lcdsaddr1;
8: unsigned long lcdsaddr2;
9: unsigned long lcdsaddr3;
10: unsigned long redlut;
11: unsigned long greenlut;
12: unsigned long bluelut; //0x4D00_0028
13: unsigned long reserved[9]; // addr( dithmode - bluelut) = 36 = 4 * 9
14: unsigned long dithmode; //0x4D00_004C
15: unsigned long tpal;
16: unsigned long lcdintpnd;
17: unsigned long lcdsrcpnd;
18: unsigned long lcdintmsk;
19: unsigned long lpcsel;
20: };
21: static volatile struct lcd_regs* lcd_regs;
22: // lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));
23: // lcd_regs->lcdcon1 = (4<<8) | (3<<5) | (0x0c<<1);
24: // lcd_regs->lcdcon2 = (3<<24) | (319<<14) | (1<<6) | (0<<0);
25: // ....
26: // release operations : iounmap(lcd_regs);
构造时,注意保留空间的设置,在后续操作时,采用同样的方式进行。
3. 触摸屏优化设置
在检测到触摸屏发生中断后,如果检测到按下,则设置touch screen XY坐标连续测量模式,并且启动adc,在adc转换完成中断中,读取对于XY轴的电压值,并且通过 input_report来上报事件。
1. 在初始化adc,设置开始延迟寄存器为最大值,0xffff,稳定adc基准电压。
2. 在adc转换结果中断中,再次判断触摸屏是否按下。
3. 设定一个定时器,多次测量adc,求均值来减小误差
4. 在求均值前,对所有检测到的数据进行基本的误差过滤,去掉偏差较大的读书
5. 利用定时器来处理 长按和滑动事件
4. 利用Uboot自带命令来测试硬件
Uboot自带一些简单的命令,我们可以用它来测试一些硬件,这里以读取Nand Flash的Chip ID为例子。启动并且进入Uboot的命令行,因为Uboot是裸机程序,面对的是真实的物理地址,下面是命令示意:
.b w l 分别表示一次读取一个字节、两个字节和四个字节 后面的objects表示读取几次,寄存器长度为4字节。
读取Nand Flash ID的操作顺序如下:
选中 nand flash : 使能片选信号,操作设置 NFCONT寄存器的Reg_nCE为0
发出Read ID命令:往命令寄存器中写入 READ ID命令(0x90)
发出地址数据: 往地址寄存器中写入 0x00地址数据
读取返回值: 连续读取五次,和对应芯片的Read ID读取命令结果,依次相符合,证明 这种Nand Flash 芯片的类型为 K9F2G08U0A 。
退出读取ID的状态 : 向命令寄存器中写入 RESET命令(0xFF),复位设备。
上述是读取NAN FLASH ID的例子,同样,可以用Uboot的单个命令行来一个字节一个字节的读取nand flash里面存储的内容,也可以用nand dump 0来显示flash中第一页的内容。
5. 分析自带驱动的方法
一般来讲,内核都自带有标准的驱动,分析的入口,我们可以从内核启动过程中,打印的相关日志信息来作为突破口来入手,在内核代码中搜索对于的字符串信息,从而开始分析。
在进行内部设备的寄存器设置时,首先需要确保该模块的时钟使能,一般来说,内核在正常运行过程中,为了省电,会关掉一些外设的时钟,因此,在设置寄存器之间,必须要开启该模块的时钟,通用的方法如下:
1: struct clk *clk; //定义一个时钟结构
2: clk = clk_get(NULL,"nand"); //通过设备id来查找时钟
3: clk_enable(clk); //实际调用的是 nand类型的时钟使能函数 s3c2410_clkcon_enable
4:
5: //arch/arm/mach-s3c2410
6: static struct clk init_clocks_disable[] = {
7: {
8: .name = "nand",
9: .id = -1,
10: .parent = &clk_h,
11: .enable = s3c2410_clkcon_enable,
12: .ctrlbit = S3C2410_CLKCON_NAND,
13: }, {
先使能控制器的时钟,然后对其寄存器进行设置,最后,使能控制器本身,按照这样的操作顺序,一般是不会出错。
注销设备时,释放相关资源的顺序和注册设备时,要保持相反的顺序,这样比较合理。
在设置片内外设控制器和片外设备的时序匹配时,要明确两点,时钟信号都是有主芯片主动发出的,时序有 读时序,写时序、等待时序等等,考虑到一致性,我们只需要对比两边读时序的部分,使得发出和接收两侧的时序保持兼容就行。不确定的寄存器值,保持默认值就行。
6. 快速确定驱动所在内核配置脚本中的位置
在需要确定内核驱动文件对于的menuconfig中的位置时,可以使用如下的方法来快速查找:
例如:查找声卡驱动的对于配置选项在哪里?
首先,我们肯定是可以找到声卡对于的驱动文件里面的Makefile,复制对应文件的CONFIG选项,例如,如果选项配置是 CONFIG_WM8976,那么就复制WM8976,然后进入内核的配置页面,按下“/”,出现如下搜索框:
粘贴选项,回车,就可以发现该选项在内核配置界面中的具体路径了,方便快速,值得一试。
7. 移植madplayer播放器到JZ2440
参考链接:http://blog.163.com/kang_6530/blog/static/7219155720090525649537/
依次下载 zlib-1.2.3.tar.gz libid3tag-0.15.1b.tar.gz libad-0.15.1b.tar.gz madplay-0.15.2b.tar.gz 在其共有目录新建tmp文件夹。
下面以 /home/hao/madplay/tmp目录为例子
7.1 编译zlib
./configure --prefix=/home/hao/madplay/tmp
然后修改生成的Makefile,修改CC,AR和RANLIB,加上交叉编译前缀arm-linux-
然后make && make install ,
7.2 编译libid3tag
./configure --prefix=/home/hao/madplay/tmp/ --host=arm-linux --disable-shared CC=arm-linux-gcc CPPFLAGS=-I/home/hao/madplay/tmp/include LDFLAGS=-L/home/hao/madplay/tmp/lib
make && make install
7.2 编译 libmad
./configure --prefix=/home/hao/madplay/tmp/ CC=arm-linux-gcc --host=arm-linux --disable-shared CPPFLAGS=-I/home/hao/madplay/tmp/include LDFLAGS=-L/home/hao/madplay/tmp/lib
make && make install
7.4 编译 madplay
./configure --prefix=/home/hao/madplay/tmp/ CC=arm-linux-gcc --host=arm-linux --disable-shared --enable-static CPPFLAGS=-I/home/hao/madplay/tmp/include LDFLAGS=-L/home/hao/madplay/tmp/lib
make && make install
注意事项,不要在linux与windows的共享目录中执行编译过程,有可能因为权限问题而失败。
当出现madplay: error while loading shared libraries: cannot open shared object file: cannot load sharedobject file: No such file or directory,则是因为在编译时没有设置好静态链接和共享库,正确的配置就是在编译libid3tag、libmad 和madplay 时,加上disable-shared 选项,同时(只)在madplay 的配置语句上加上enable-static设置为静态。
8. Windows安装,要求以数字签名的驱动程序
在安装一些调试工具的驱动时,Windows自带的搜索驱动找不到,指定驱动安装路径也无法正常安装,弹出如下提示:
解决方法:用管理员身份进入命令行窗口,输入cmd,然后执行 bcdedit /set testsigning on ,然后重启电脑,这样,就打开Windows的测试模式,可以安装一些没有经过Windows驱动签名的驱动。
如果需要取消测试模式,可以输入 bcdedit /set testsigning off ,然后重启,就可以。经过实际测试,是可以工作。
9.ARM CACHE
ARM体系结构的 DCACHE开启,需要事先使能MMU才能。而ICACHE无需其他限制条件,直接开启即可。
1: /* 启动ICACHE */
2: mrc p15, 0, r0, c1, c0, 0 @ read control reg
3: orr r0, r0, #(1<<12)
4: mcr p15, 0, r0, c1, c0, 0 @ write it back