韦东山嵌入式Linux视频教程_3期项目实战之ALSA声卡_裸板之编译和测试(基于优龙FS2410开发板)

一、实验环境

1.1 虚拟机环境

    a) Vmware版本:Vmware Workstation 12.5.7

    b) Ubuntu版本:9.10

    c) 内核版本:2.6.31.14

    d) toolchain版本:arm-linux-gcc 3.4.5

1.2 开发板

    优龙FS2410开发板,UDA1341声卡

1.3 调试器

    硬件:百问网OpenJTAG

    软件:OpenOCD、Eclipse 3.6 Helios


二、调试过程记录

1、开发板的JP1设置为NOR启动,然后通过u-boot和DNW的USB功能把sound.bin烧写到nandflash的地址0处,把windows.wav烧写到0x60000处,

      然后JP1设置为NAND启动。重新上电,耳机插入开发板 ,在串口终端的菜单里,选择:[M] MINI2440 或者 [T] TQ2440,但是耳机里没有任何声音!

2、用OpenJTAG+Eclipse调试代码

   (具体方法详见:百问网OpenJTAG 调试器产品手册《Eclipse,OpenOCD,OpenJTAGv3.1 开发教程v5.pdf》2.4 使用Eclipse 调试程序:以S3C2440 的leds 程序为例)

      启动调试后,报:

           0x33f8028c in nand_addr (addr=<optimized out>) at init.c:125

     经查,是因为init.c中:#define NFADDR (*((volatile unsigned char *)0x4E00000C)),这是2440的,不是2410的。

     解决办法:

          修改init.c:

         // #define NFCONT (*((volatile unsigned long *)0x4E000004))

          // #define NFCMMD (*((volatile unsigned char *)0x4E000008))

          // #define NFADDR (*((volatile unsigned char *)0x4E00000C))

          // #define NFDATA (*((volatile unsigned char *)0x4E000010))

          // #define NFSTAT (*((volatile unsigned char *)0x4E000020))

          #define NFCMMD (*((volatile unsigned char *)0x4E000004))

          #define NFADDR (*((volatile unsigned char *)0x4E000008))

          #define NFDATA (*((volatile unsigned char *)0x4E00000C))

          #define NFSTAT (*((volatile unsigned char *)0x4E000010))

3、再次在串口终端的菜单里,选择:[M] MINI2440 或者 [T] TQ2440,这次耳机里能听见声音了!

     但是,当把sound.bin重新烧写到nandflash后,重启开发板,再试,耳机里还是没有任何声音!

4、由于eclipse不支持调试位于nand中的代码,所以只能用telnet客户端登陆到OpenOCD来调试

     (具体方法详见:百问网OpenJTAG 调试器产品手册《Eclipse,OpenOCD,OpenJTAGv3.1 开发教程v5.pdf》2.2 使用OpenOCD、OpenJTAG 烧写程序、调试程序)

     halt

     load_image sound.bin 0x0

     step 0

     resume之后,有时会进入undefined instruction 异常!

     有时却会pc反复的在b8,bc之间辗转:

       clip_image002[4]

      实在找不出原因Sad smile。 无奈之下,只能用step逐条语句运行,经过一系列的step(为了提高定位效率,可以用二分法),最终发现问题的症结:

image

image

      查sound.dis的反汇编代码:

33f80330 <nand_read>:

      33f80330: e92d41f0 push {r4, r5, r6, r7, r8, lr}

      33f80334: e1823000 orr r3, r2, r0

      33f80338: e1a0cb83 lsl ip, r3, #23

      33f8033c: e1a0cbac lsr ip, ip, #23

      33f80340: e35c0000 cmp ip, #0 ; 0x0

      33f80344: e24dd008 sub sp, sp, #8 ; 0x8

      33f80348: e1a05002 mov r5, r2

      33f8034c: e1a04001 mov r4, r1

      33f80350: 1a000031 bne 33f8041c <nand_read+0xec>

      …

      33f8041c: e28dd008 add sp, sp, #8 ; 0x8

      33f80420: e8bd41f0 pop {r4, r5, r6, r7, r8, lr}

      33f80424: e12fff1e bx lr


      对应于init.c的nand_read:

      if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { //NAND_BLOCK_MASK=511,因为K9F1208 一页大小是512字节

          return ; /* 如果地址或长度不对齐,就直接返回*/

      }


    通过查看r2寄存器的值,可知size=0x33D4,而0x33D4& 1ff !=0 ,所以程序直接return了!最终导致nand里的代码段未能拷贝到程序的链接地址,因此程序跑飞了!

    经查,调用栈是这样的:

    (head.S)

     mov r0, #0
     ldr r1, =_start
     ldr r2, =__bss_start
     sub r2, r2, r1
     bl copy_code_to_sdram # 会调用init.c的copy_code_to_sdram(0, _start, __bss_start) ,其中,_start即.text ,而.text 和__bss_start都定义在sound.lds中

        copy_code_to_sdram(src, dst, len) # 把程序从nand读出来拷贝到内存_start地址处,长度为__bss_start-_start

            nand_read(src, dest, len)

      查看sound.lds,有:

      …

      . = ALIGN(4); //表明当前链接地址按4字节对齐

      __bss_start = .;

      …

      遂改为:. = ALIGN(512); 再试,终于能播放声音了!

      注:FS2410使用的 NAND是K9F1208, 一页大小是512字节,根据数据手册以及网文,它的读操作,支持页内任意地址读,但目前nand_read代码先不改了,等以后有时间再改。


三、总结

    通过在优龙FS2410开发板上进行UDA1341声卡的裸板驱动调试,进一步了解了声卡驱动的硬件操作框架和流程,以及裸板驱动的调试方法。

    裸板驱动的难点主要是:

1、 codec芯片的配置, soc的配置(包括DAI(比如IIS)、DMA),machine的配置(哪些管脚用于连接codec芯片的控制引脚(CSB、SCLK、SDIN))

2、 一旦出了问题,怎么调试?

      一个比较好的办法是,用OpenJTAG+OpenOCD结合Eclipse进行源码级的调试,而如果要调试NAND里的代码,可以用telnet到OpenOCD来进行汇编级的调试(缺点是操作比较繁琐,而且还要分析汇编代码)


四、参考资料

  1、韦东山 《嵌入式Linux应用开发完全手册》

  2、韦东山 《Eclipse,OpenOCD,OpenJTAGv3.1 开发教程v5.pdf》

  3、 NandFlash K9F1208U0A/ K9F1208U0B的读取操作

猜你喜欢

转载自www.cnblogs.com/normalmanzhao2003/p/12324519.html