文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>U-BOOT调试心得(一)

U-BOOT调试心得(一)

时间:2007-01-22  来源:marsky

 

第一次接触u-boot,先介绍一下环境,实验环境是mpc866系列的cpu--mpc852,当然之所以选择这款芯片主要是出于成本考虑。14$的价格只比arm9贵了6$,十分适合简单的网络应用。

u-boot采用1.16版本,是当时最新的,支持的开发板也毕竟多。看了一些开发板的config.h文件之后,我决定使用Adder的模版。

按照之前调试vxworks bsp时的寄存器参数修改了Adder.h文件后,把生成的u-boot文件用bdi2000下载到flash中。运行后出现mechine check interrupt,发生的位置是0x20002550。经过追踪发现是调试器实现的问题,具体如下:

首先是第一个开始执行的文件start.s。下面是我反汇编出来的代码:

20000118 <boot_cold>:

20000118:       38 60 10 02   li      r3,4098

2000011c:       7c 60 01 24   mtmsr     r3

20000120:      7c 7b 03 a6    mtsrr1     r3

20000124:      7c 74 22 a6    mficr      r3

20000128:      7c 00 02 78   xor  r0,r0,r0

2000012c:      7c 1c 23 a6    mtlctrl1   r0

20000130:      7c 1d 23 a6    mtlctrl2   r0

20000134:      7c 16 23 a6    mtcounta r0

20000138:      7c 17 23 a6    mtcountb r0

2000013c:      7c 70 8a a6    mfic_cst  r3

20000140:      7c 78 8a a6    mfdc_cst r3

20000144:      3c 60 0a 00    lis    r3,2560

20000148:      7c 70 8b a6    mtspr      560,r3

2000014c:      7c 78 8b a6    mtspr      568,r3

20000150:      3c 60 0c 00   lis    r3,3072

20000154:      7c 70 8b a6    mtspr      560,r3

20000158:      7c 78 8b a6    mtspr      568,r3

2000015c:      3c 60 04 00   lis    r3,1024

20000160:      7c 78 8b a6    mtspr      568,r3

20000164:      4c 00 01 2c   isync

20000168:      3c 60 20 00   lis    r3,8192

2000016c:      60 63 00 00   ori   r3,r3,0

20000170:      38 63 01 7c   addi r3,r3,380

20000174:      7c 68 03 a6    mtlr r3

20000178:      4e 80 00 20    blr

下面是start.s的源代码:

boot_cold:

boot_warm:

 

       /* Initialize machine status; enable machine check interrupt        */

       /*----------------------------------------------------------------------*/

       li      r3, MSR_KERNEL        /* Set ME, RI flags */

       mtmsr     r3

       mtspr      SRR1, r3        /* Make SRR1 match MSR */

 

       mfspr      r3, ICR                 /* clear Interrupt Cause Register */

 

       /* Initialize debug port registers                                 */

       /*----------------------------------------------------------------------*/

       xor  r0, r0, r0        /* Clear R0 */

       mtspr      LCTRL1, r0           /* Initialize debug port regs */

       mtspr      LCTRL2, r0

       mtspr      COUNTA, r0

       mtspr      COUNTB, r0

 

       /* Reset the caches                                           */

       /*----------------------------------------------------------------------*/

 

       mfspr      r3, IC_CST           /* Clear error bits */

       mfspr      r3, DC_CST

 

       lis    r3, IDC_UNALL@h             /* Unlock all */

       mtspr      IC_CST, r3

       mtspr      DC_CST, r3

 

       lis    r3, IDC_INVALL@h      /* Invalidate all */

       mtspr      IC_CST, r3

       mtspr      DC_CST, r3

 

       lis    r3, IDC_DISABLE@h   /* Disable data cache */

       mtspr      DC_CST, r3

 

#if !(defined(CONFIG_IP860) || defined(CONFIG_PCU_E) || defined (CONFIG_FLAGADM))

                                   /* On IP860 and PCU E,

                                    * we cannot enable IC yet

                                    */

       lis    r3, IDC_ENABLE@h     /* Enable instruction cache */

#endif

       mtspr      IC_CST, r3

 

       /* invalidate all tlb's                                           */

       /*----------------------------------------------------------------------*/

 

       tlbia

       isync

 

       /*

        * Calculate absolute address in FLASH and jump there

        *----------------------------------------------------------------------*/

 

       lis    r3, CFG_MONITOR_BASE@h

       ori   r3, r3, CFG_MONITOR_BASE@l

       addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET

       mtlr r3

       blr

比较后我们发现,编译器编译了

#if !(defined(CONFIG_IP860) || defined(CONFIG_PCU_E) || defined (CONFIG_FLAGADM))

                                   /* On IP860 and PCU E, we cannot enable IC yet */

       lis    r3, IDC_ENABLE@h     /* Enable instruction cache */

#endif

这段代码,也就是说,打开了指令catche,而出现machine check的位置,是在cup_init.c中的cpu_init_f函数中,见下段:

       memctl->memc_br0 = CFG_BR0_PRELIM;

20002528:      3d 20 20 00   lis    r9,8192

2000252c:      55 6b 05 2a    rlwinm    r11,r11,0,20,21

       memctl->memc_or0 = CFG_OR0_PRELIM;

20002530:      3c 00 ff 00    lis    r0,-256

20002534:      60 00 0f f6    ori   r0,r0,4086

20002538:      61 6b 00 01   ori   r11,r11,1

2000253c:      61 29 08 01   ori   r9,r9,2049

20002540:      91 6a 00 00    stw  r11,0(r10)

20002544:      91 2a 00 00    stw  r9,0(r10)

20002548:      90 0a 00 04    stw  r0,4(r10)

 

       /*

        * Reset CPM

        */

       immr->im_cpm.cp_cpcr = CPM_CR_RST | CPM_CR_FLG;

2000254c:      38 00 80 01   li      r0,-32767

20002550:      b0 1f 09 c0    sth   r0,2496(r31)

       do {               /* Spin until command processed     */

              __asm__ ("eieio");

20002554:      7c 00 06 ac    eieio

       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);

20002558:      a0 1f 09 c0    lhz   r0,2496(r31)

2000255c:      70 09 00 01   andi.       r9,r0,1

20002560:      40 82 ff f4     bne+       20002554 <cpu_init_f+0xec>

20002564:      80 01 00 1c   lwz  r0,28(r1)

20002568:      83 e1 00 10    lwz  r31,16(r1)

2000256c:      7c 08 03 a6    mtlr r0

20002570:      38 21 00 18   addi r1,r1,24

20002574:      4e 80 00 20    blr

 

出现在0x20002550,此时cpu访问的数据是非法数据且随机变化,每次开机都不同。

追踪时发现,在上面绿色的语句中:

20002540:      91 6a 00 00    stw  r11,0(r10)

20002544:      91 2a 00 00    stw  r9,0(r10)

20002548:      90 0a 00 04    stw  r0,4(r10)

stw  r11,0(r10) 此时r10=0xff000100,是br0的地址,但是r11是0x00000801,然后在下一句中stw    r9,0(r10),r9存放的值是真正的br0的值,即0x20000801,但是此时LSU已经访问0x20002544寻找下一条指令,但由于此时的flash基地址已经变为0;因此会发生machine check也就不奇怪了。

之前之所以,频繁发生在0x20002550的错误,或者发生在20002554: eieio的错误,其实是由

#if !(defined(CONFIG_IP860) || defined(CONFIG_PCU_E) || defined (CONFIG_FLAGADM))

                                   /* On IP860 and PCU E,       * we cannot enable IC yet */

       lis    r3, IDC_ENABLE@h     /* Enable instruction cache */

#endif

打开了指令catche,因此实际发生的问题的位置被延后了,因为在br0设置错误的时候,指令catche中已经load到了后面的几条正确的指令,但此时仍在执行指令的load操作,读到的指令当然是machine check,然后在指令catche中的指令执行完后,引发mechine check,但此时已经距离问题发生的位置有一定距离。

    之所以会出现这样的问题是因为在memctl->memc_br0 = CFG_BR0_PRELIM; 之前,有这样一些处理:

reg = memctl->memc_br0;

       reg &= BR_PS_MSK;    /* Clear everything except Port Size bits */

       reg |= BR_V;          /* then add just the "Bank Valid" bit     */

       memctl->memc_br0 = reg;

这样,br0首先被清成0x00000801,当然这对于没有调试器的情况下,cpu会执行cs0上的存储器代码,而不会管他的地址。但是对于调试器则不会,我不是很清楚BDM调试器的原理,只能以JTAG调试器原理理解,虽然两者的原理完全不同,但是bdm试器的指令和数据应该和jtag一样,是在运行时,通过调试口插入到内核中,cpu以调试口输入的时钟工作。也就是说当配置bdi2000后,bdi2000会控制cpu从0x20000000的地址处执行指令,这也许是通过分析程序中的偏移量得到的。

这就是为什么使用bdi2000时,会出现mechine check ,而cpu自己运行时不会。解决的方法也很简单,把上面的语句删了就行了,我不太知道这句会在这里是什么作用,但是如果不放心的话,可以在调试完成后再加上,不会有什么影响。

相关阅读 更多 +
排行榜 更多 +
蛋花

蛋花

浏览阅读 下载
馅饼跑步者

馅饼跑步者

休闲益智 下载
富荔智选

富荔智选

学习教育 下载