驱动调试方法小结

1 . 调试输入子系统

     在调试输入子系统时,input_system,可以通过hexdump 来打开并且实时读取对于输入设备的值,数值关系如下图所示:

image

    每一次按键事件上报后,都会有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是裸机程序,面对的是真实的物理地址,下面是命令示意:

      image

     .b w l 分别表示一次读取一个字节、两个字节和四个字节 后面的objects表示读取几次,寄存器长度为4字节。

     读取Nand Flash ID的操作顺序如下:

      选中 nand flash :    使能片选信号,操作设置 NFCONT寄存器的Reg_nCE为0

                                image            

      发出Read ID命令:往命令寄存器中写入 READ ID命令(0x90)

                                image

      发出地址数据: 往地址寄存器中写入 0x00地址数据

                               image

      读取返回值: 连续读取五次,和对应芯片的Read ID读取命令结果,依次相符合,证明 这种Nand Flash 芯片的类型为 K9F2G08U0A 。

  image        退出读取ID的状态 : 向命令寄存器中写入 RESET命令(0xFF),复位设备。 image

上述是读取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,然后进入内核的配置页面,按下“/”,出现如下搜索框:

     image

     粘贴选项,回车,就可以发现该选项在内核配置界面中的具体路径了,方便快速,值得一试。

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自带的搜索驱动找不到,指定驱动安装路径也无法正常安装,弹出如下提示:

      image

    解决方法:用管理员身份进入命令行窗口,输入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
Technorati 标签: linux 调试
posted @ 2015-04-08 21:55  浩天之家  阅读(1084)  评论(0编辑  收藏  举报