转载地址:http://blog.sina.com.cn/s/blog_6adcb353010113t9.html
1、准备从bootrom开始调试,使用probe烧录。打开workbench3.0发现不支持MPC8572。打电话给OCD专家结果找不到人。
2、改一下思路,先不调试bootrom了,因为现在里面已经有了uBoot,会有一些地址信息从中能够查到,如果使用bootrom覆盖了,后面查地址必须看原理图了。现在准备从uBoot启动,然后加在vxWorks的image。
3、启动uBoot以后发现加载不了,找freescale的工程师Liu Yi [Yi.Liu@freescale.com]要了资料。后来发现里面不但烧了uBoot还烧了linux的bsp,在启动linux之前有一个10秒的间隙,如果不输入任何东西会自动启动linux的bsp。在10秒间隙内输入任何值,就是uBoot的状态了。
4、根据8572ADS板的target.ref文档找到了uBoot的使用方法。加载vxWorks的image。结果显示指令错,可能是config.h里面的地址不匹配。
5、串口和网口都没起来,没有调试手段,准备点灯。查看了原理图,8个GPIO都通过阻排接地了,阻排在cpu风扇的下面,想用示波器或万用表检测管脚都做不到。板子上有10几个灯,查了一些原理图,有3个是电源灯,8个是总线低8位的检测。没办法了,看来是点灯是没戏了。
6、只能寄希望于异常打印上了。
2008-5-14
1、把config.h看了一遍,把flash地址和DRAM的地址都修正了。还是起不来。
=> tftp 100000 vxWorks.bin
Speed: 10, half duplex
Using eTSEC1 device
TFTP from server 172.25.48.32; our IP address is 172.25.48.13
Filename 'vxWorks.bin'.
Load address: 0x100000
Loading: Got error 4
T #################################################################
done
Bytes transferred = 1642720 (1910e0 hex)
=> go 0x00100000
## Starting application at 0x00100000 ...
NIP: 0012D20C XER: 00000000 LR: 0011BD78 REGS: 000ffec0 TRAP: 0700 DAR: 00000000
MSR: 00008000 EE: 1 PR: 0 FP: 0 ME: 0 IR/DR: 00
GPR00: 0011D8B0 000FFFB0 00000200 00000001 4C000064 00000010 002910F8 00000001
GPR08: 00000001 00000020 FFFFFFFF 00000007 0FF8DC00 A19272A0 0FFF4A00 20030000
GPR16: 00000000 00000000 00000000 00000000 00000000 000FFEB0 00000000 00000000
GPR24: 0FF90A40 00000000 00000000 00000002 00100000 0FF8DF7C 0FFF5598 000FFFB0
** Illegal Instruction **
Call backtrace:
DEADBEEF 0011D8B0 0FFC8B50
Program Check Exception
### ERROR ### Please RESET the board ###
增加了编译map的选项,查看map,0011D80地址是prjConfig.c文件中函数usrInit里面调用的第二个函数cacheLibInit。
2、可能是这句不对,注释掉后,重新跑,没有任何变化。
3、在cacheLibInit前面增加while(1)。如果是cacheLibInit出错,那么增加了while后,就应该停在前面,不会再报异常。测试结果是依然异常。
4、把while往前提一句,看一下是不是我的做法不对,根本就没跑进我的代码,结果把while加在usrInit的第一句时,系统不再报错,而是停住了。说明我的这种调试方法是可行的。
5、记得曾经遇到过不配置mmu就会出现不能调用函数的情况,估计这次也是这个原因,因为usrInit里面的第一个函数sysStart只是简单的赋值,不应该有其他可能。
6、在sysAlib.s里面增加了对flash段和内存段的映射。结果还是报异常:
=> go 0x100000
## Starting application at 0x00100000 ...
NIP: 00123CB8 XER: 00000000 LR: 0011D93C REGS: 000ffee0 TRAP: 0700 DAR: 00000000
MSR: 00008000 EE: 1 PR: 0 FP: 0 ME: 0 IR/DR: 00
GPR00: 0011D930 000FFFD0 002867A8 00000012 00000012 00000000 0000A9EC 00000001
GPR08: 00000000 00290000 00000020 000FFFD0 00198B24 002985A0 0FFF4A00 20030000
GPR16: 00000000 00000000 00000000 00000000 00000000 000FFED0 00000000 00000000
GPR24: 0FF90A40 00000000 00000000 00000002 00100000 0FF8DF7C 0FFF5598 000FFFD0
** Illegal Instruction **
Call backtrace:
0011D930 0FFC8B50
Program Check Exception
### ERROR ### Please RESET the board ###
不过这次有了点变化,上面红色的部分即R3和R4,值是18,这是cacheLibInit的两个输入参数。绿色的两处分别是R2和R13,在函数sysStart中,这两个寄存器分别保存了_SDA2_BASE_和_SDA_BASE_,查了一下map表,果然是这两个值。说明函数能够调用了,现在情况已经发生了变化,问题集中到了cacheLibInit上。
7、最直接的想法,注释掉这个函数,并且把cache改成disable。结果在调用下一个函数excVecInit的时候又非法指令了,函数调用还是有问题。
2008-5-15
1、每次在集成环境上先编译完vxWorks文件,再手工使用命令:objcopyppc -O binary --binary-without-bss vxWorks vxWorks.bin把vxWorks转换成vxWorks.bin太麻烦了。准备改一下集成环境的设置,直接编译出bin文件。不过一直没有找到地方,后来咨询了上海的同事,终于找到了地方:工程点右键选择properties->Build Properties->Build Macros->POST_BUILD_RULE,在后面增加$(EXTRACT_BIN) vxWorks vxWorks.bin可以直接编译出bin来。
2、由于调试没什么进展,准备换个思路,可能uBoot对后面的vxWorks有影响,不使用uBoot,直接把bootrom烧到flash里面去。使用升级后的workbench OCD可以连上,flash的读取也正常。查看了原理图,flash的型号是MX29LV640BT。Probe连接上以后自动选择的flash型号是S29GL01GP,明显不对,但列表里面没有MX29LV640BT,应该跟29LV640是兼容的,但我不知道板子上的是B还是T,这涉及到小扇区的分布。选了29LV640MB,能够使用,烧录没有显示异常。但是启动没有反映,单步跟踪,第一条执行是跳转到0xFFFFF000,跳过去后看到的不是二进制代码,而是一片0。感觉到这里面有不对的地方。按照MPC85XX的启动流程,第一条指令在0xFFFFFFFC。MPC85XX的运行是一定需要mmu支持的,初始状态的Mmu只映射了地址空间末尾的4K。所以第一条指令只能做一个4K内的跳转,也就是0xFFFFF000内的一个地址,在这里可以写一些简单的代码扩大mmu的映射空间,然后在从这里跳到其他地址去,vxWorks习惯于跳到0xFFF00100。但是现在明显没有按照流程来,反复烧了几次都是这个结果。
3、放弃了再烧bootrom的想法,准备把uBoot再烧回去,慢慢来吧。烧回去的时候发现最后一个block烧录过程中报错,复位、断电、多次烧录都同一个结果。查看前面的都正常,可能是flash小扇区的问题,极有可能是flash型号选错了。换成29LV640MT,烧录成功,每次换很麻烦,直接修改MPC8572的寄存器文件,使之一劳永逸,位置在\ocd\0127\RegisterFiles\PowerPC\85xx\Motorola\MPC8572E_WhiteFIN_Uboot_core0.reg,将:
TF CONF 133 00005000 65436 F8000000 'AMD
改为:
TF CONF 133 00005000 65436 FF800000 'AMD
这里面我不理解为什么烧bootrom的时候没有报错,可能是我们的OCD在flash烧录校验方面的算法有问题,我看了一下uBoot和bootrom在最后一个block空间内的区别,uBoot只有最后4字节是有内容的(跳转指令),其他都是F,而bootrom是有数据,在烧录bootrom的时候大部分空间都是可写的,只有最后4个字节不同,uBoot的是0x4BFFF004,bootrom的是0x4BFFF804,有一位的差别,我查看了前面烧录的内容,bootrom烧完以后,最后4字节仍然是0x4BFFF004,所以才会出现跳转以后遇到的是0不是代码的情况。我怀疑我们的OCD在校验的时候对最后4位的校验有bug。
4、既然找到了bootrom走不下去的原因,就再继续把这条路走走看。烧录后,单步跟踪正常,程序按照预定跳转到了0xFFFFF800继续执行,设置完内存的片选以后有个循环等待,循环0x2000次,我使用run to here和设置断点都无效,只有单步跟踪有用。点了run,再也停不住了,飞了。
5、注释掉循环的地方,这里的循环无非是要等个时间,我单步的执行时间足够用了。单步跟踪发现在
useBuildOscFreq:
与
之间存在循环。从表面看,应该是内存主频配置不对。
2008-5-16
1、内存的主频配置不对可能引发了昨天的内存初始化大循环,早上查看了资料,系统晶振是66M,所以不让代码去读0xF0000000的地址了,直接配置66M。发现仍然不行,代码运行到0xFFF00354的地方,这个地方在文件bootInit.c里面,对应的语句是退栈操作,把一个数据写入0x010000f0的地方。估计是内存不可写导致了错误。
2008-5-20
1、这几天一直在看MPC8572的文档,把rominit又过了一遍。E500与其他架构有些不同,E500支持36位地址,这种模式超出了软件的4G空间限制。为了让软件能够访问到所有的地址空间,E500提供了一个window的概念,所有的地址只有映射到window以后才能被访问,系统提供了12个window,每个window由一组两个寄存器配置(LAWBAR,LAWAR),一个负责起始地址,一个负责大小和属性,每个window的大小必须是2的整数次幂,最小可配置的大小为4K,所以起始地址的配置寄存器只有低24为有效。也有例外,CCSRBAR、SRAM和BootRom不需要window,这是为了启动上的方便。CCSRBAR是芯片的寄存器空间,共1M,所有片内的寄存器都集中在这里,缺省地址是0x0_FF70_0000。BootRom缺省可访问空间是4K,位置在低4G空间的末尾(0x0_FFFF_F000 到0x0_FFFF_FFFF),按照FreeScale提供的启动流程,第一条指令在低4G空间的最后4个字节(0x0_FFFF_FFFC),这里一般放一条跳转指令,跳到4K范围内的一个地址,在这段最大4K的代码里面初始化内存和mmu,执行完以后再跳转到Windriver传统的启动地址0xFFF00100。SRAM被L2SRBAR缺省映射。
自己总结了一下,如果要访问一个地址,需要片选(OR/BR)、MMU、Window同时映射才可以。
在Rominit.s里面需要访问的地址,包括CCSRBAR、Flash、SDRAM三种。
2008-5-21
1、在查看代码的时候发现一个问题,我们在代码中前面一部分配置的mmu表项都是TS0的,直到usrconfig以后才会有TS1的表项配置,但是TS0能够起作用是要依靠msr的一个特定位为0为前提的。如果这个位不为0,mmu如何配置都没用了。想到前面几天一直重复的一个内存无法访问的问题,感觉可能跟这里有点关系。我们缺省的代码里对msr也做了处理,不过比较简单:
实际上是只清了中断位。
我对这个地方做了一下修改,把整个msr都初始化为0:
测试一下,单步跟踪果然过了bootinit前面的压栈操作,说明内存可以访问了。
2、在前面的基础上go一下,停住,通过map表比较当前位置,还在bootinit里面,单步跟踪,发现在做一个拷贝操作。代码上是在对内存做填充0的操作。我感觉这个动作也没有多大的必要,就在rominit入口的地方修改了启动参数,把BOOT_COLD改为BOOT_NORMAL。这样就避免了内存清0操作,加快了启动速度。
3、再往下跑,发现跑飞了,并且串口仍然没有打印。通过点灯,查到原因在vxBus的初始化里面,由于此时的串口还没有打印,问题比较难查了。每次加点灯可以知道代码跑到哪一行,但是遇到循环就麻烦了,没办法用点灯来看变量和字符串,麻烦的很。个人感觉,在“复杂”的vxBus初始化之前,串口应该完成初始化,并且vxBus应该提供很方便的调试开关,而不是依靠重新编译vxBus的源码。
2008-5-24
1、今天周末,前面几天都在处理中兴的网口和编译问题,没时间搞,周末把板子带回家来调试。我准备延续21日的思路,在vxBus之前把串口跑通,我以前曾经自己做过一个print的打印,功能跟printf差不多,只要串口的初始化完成了,我的print应该能够派上用场。我看了一下MPC8572的datasheet,串口跟ns16552差别不大,在bsp目录下缺省没有这样的初始化文件,我从834x的bsp下拷贝了一份sysDuart.c,编译上除了INUM_UART不认识,其他都编译正常。在vxBus初始化之前调用了一下sysDuartHwInit,然后通过直接写寄存器的方式写了一个字符,测试一下是否好使。串口上没有任何打印,可能是波特率不对或者sysDuart里面的其他内容对串口有影响,把串口寄存器初始化部分拷贝出来,自己做成了一个串口的初始化函数使用。串口的寄存器部分有一点特殊,500、501、502三个寄存器有两个功能,当503的DLAB位为1的时候,是配置波特率分频,DLAB为0的时候是其他功能。按照MPC8572的datasheet上选择533M时9600的波特率,数据是打印出来了,但是不知道是什么。看来波特率还是不对。手头没有原理图,没法知道系统时钟,不过我记得在配置内存的时候用的时钟是500M,按照500M算出来一个波特率除数0xcb7,加进去,好使,串口有输出了。
2、下一步把串口的打印做成一个函数,然后接管printf。这个步骤简单的跟1一样。
void usrSerialInit()
{
}
void usrSerialOutput(char c)
{
}
void Drv_Print(const char *pStr, ...)
{
}
做了一个打印Drv_Print("\r\n line = %d", __LINE__);编译后烧进去运行,没有任何输出。看来1并不简单,开始以为是内核没有初始化,还不支持va_start这种函数,后来一看是前面删除了usrSerialInit没有再调用。虚惊一场。
3、开始跟踪vxBus的初始化流程,前面已经使用点灯的方法跟踪了一部分:
sysHwInit->hardWareInterFaceInit->hardWareInterFaceBusInit
最后一个函数里面有循环才没办法跟了,这次直接跟踪plbInit1。打开文件vxbPlb.c里面的VXBPLB_DEBUG_MSG,用刚刚实现的Drv_Print替代printf。vxBus部分的文件都是直接参与编译的,没有以库的形式提供,这为调试提供了方便。
plbInit1(): processing device ns16550
plbInit1(): announcing device ns16550
plbDevMatch((0x010af180,ppcIntCtlr),(0x010b2fe8,0xe0004500)) called
plbDevMatch((0x010afc04,openPicTimer),(0x010b2fe8,0xe0004500)) called
plbDevMatch((0x010afb74,ns16550),(0x010b2fe8,0xe0004500)) called
plbDevMatch(): checking epic
plbDevMatch(): checking ppcIntCtlr
plbDevMatch(): checking motetsec
plbDevMatch(): checking motetsec
plbDevMatch(): checking motetsec
plbDevMatch(): checking motetsec
plbDevMatch(): checking tsecMdio
plbDevMatch(): checking ns16550
发现了串口设备后就不动了。开始以为是vxBus初始化串口的波特率不对,导致串口初始化的覆盖,后面的内容输出不了。但是即使不对应该屏幕上也有乱码,现在什么都没有了,显然不对。查看plbDevMatch函数,check OK, dev=ns16550 drv=ns16550是函数最后一句打印,这以后函数就退出了。而plbDevMatch的调用者是vxbDeviceAnnounce,继续跟踪。用上面同样的方法打开vxBus.c的调试开关。在前面的基础上又增加了下面两行:
vxbDeviceAnnounce(): calling driver probe
vxbDeviceAnnounce(): found match, driver @ 0x10b0374
有了打印了,问题会查的比较快,最后找到,是ns16550初始化的过程中调用sysClkFreqGet获取主频计算波特率惹得祸。缺省的MPC8572代码中有个PIXIS模块,我在新的板子上没有看到他的片选,所以没有初始化他,但是还保留了它的地址,在这里读取主频要去PIXIS的一个寄存器里面取数据,以至于访问了非法地址出错。把这块注释调,调整了一下sysClkFreqGet,直接返回500M。系统开始启动了,不过出现了Error in boot line:的错误,后面的打印很长。
4、应该是bootline出错了,每次启动的时候bootline在0x4200的地方读出来,如果是冷启动,内存不作处理是会有一些乱数据的,打印应该是这些数据引起的。本来在bootinit.c里面有
这段是清bootline的,在我把BOOT_CLEAR改成BOOT_NORMAL以后就没法清了,我决定把启动方式还是改回去。
5、改回去后,熟悉的界面出来了,但是在我配置完启动参数后,保存的一刹那,又出错了:
0xffffd10 (tRootTask): task 0xffffd10 has had a failure and has been stopped.
0xffffd10 (tRootTask): fatal exception stack overflow!
2008-5-25
1、前面出的错误很奇怪,地方不是固定的,并且也不是每次都发生。估计跟cache或内存缺省数据相关。查看了config.h的配置,发现L2cache的配置还保留着,将其去除。另外bootrom没有设置保留内存,High作为bootrom的起始地址,memtop在内存的顶端256M,感觉这样使用不好,在makefile里面增加了一个-DMAKE_BOOTROM,当制作bootrom的时候只使用前面的32M内存。修改后熟悉的界面出来了:
Copyright 1984-2007
CPU: Freescale MPC8572E - Security Engine
Version: VxWorks 6.6
BSP version: 2.0/1
Creation date: May 25 2008, 15:00:22
Press any key to stop auto-boot...
[VxWorks Boot]: p
boot device
unit number
processor number
host name
file name
inet on ethernet (e) : 192.168.0.2
host inet (h)
gateway inet (g)
user (u)
ftp password (pw)
flags (f)
target name (tn)
other (o)
[VxWorks Boot]:
2、输入@,网络不好使,输入‘?’,看到的网口已经attach上了:
[VxWorks Boot]: ?
Commands:
Bootline Format:
Device Formats:
Boot Flags:
Available Boot Devices:
怕是网口的标识不好,每个网口都插网线试了一下,没效果,一个报文都没发出来。
2008-5-29
1、直接查看网口部分的寄存器,RBASE与RPTR是相同的,说明硬件上没有报文收到。可能是phy的地址不对。前面两天,想了好多办法,都不奏效。上午准备把phy地址都读出来,发现使用vxbEtsecHend.c里面的etsecPhyRead没读到任何有用的内容,换成mii的read,却没有调用。
2、被同事提醒了一下,说uboot能够启动这个板子,并且在打印里面可能有phy地址,烧录进去uboot,启动后果然有phy地址。对应4个phy的地址应该是4、5、3、6,缺省的0、1、2、3没有一个能对的上的。配置正确后使用etheral抓包能够抓到了。
3、抓到包以后发现IP地址和MAC地址都不对。后面就再也抓不到了。直接查看芯片的发送寄存器,看到了待发送的报文,发现IP是对的,MAC不对,估计不能与host通信的原因在于MAC地址的非法。sysNet里面配置了正确的地址,加了跟踪后发现没调到。顺藤摸瓜,发现vxbEtsecHend.c里面的etsecInstInit2也没调到,这里是初始化MAC地址的地方。准备进一步跟踪vxBus,但是有一点不太明白,pDev->pDrvCtrl的内存空间也是在这里申请的,如果这个函数没调到,后面怎么会运行正确呢?先跟踪vxBus,加了打印,发现里面的vxbDevConnectInternal调用到了,这是调用设备的devConnect函数的,我在前面对网口的跟踪是也跟踪到了。不过vxbLibInit、vxbInit、vxbDevInitInternal却没有调用,vxbDevInitInternal就是调用devInstanceInit2函数的地方,也是我们要找的初始化MAC地址的地方,感觉不对啊,vxbLibInit是必然要调用的。突然想明白,可能前面没有初始化串口,光凭打印是不行的。找块空闲内存,把打印记录进去,后面再查看。果然都调用到了,那么没有调网口的devInstanceInit2的问题可能也是因为没打印出来的缘故。用同样的方法在devInstanceInit2和sysNet里面增加内存记录,发现果然调用到了,只不过MAC地址取错了而已。继续追查错误的原因,原来是NVRAM的判断引起的,nvram取了flash的一段空间模拟,没有初始化。
STATUS sysNetMacNVRamAddrGet
#if (NV_RAM_SIZE != NONE)
#endif
把nvram部分注释掉,直接使用全局数组里面的mac地址。个人感觉这样比较直接。修改以后,可以加载了。
4、BootRom的调试工作告一段落。
5、从workbench3.0重新创建一下工程,vxWorks image启动也成功了。到目前为止,除了L2Cache还未配置,其他都已经调试完成。