现u-boot通过tftp下载运行的时候很正常,但是一旦将内核烧到flash上的时候,第一次通过nand read命令读取然后go运行的时候很正常,然而一旦saveenv的时候,再次nand read和go的时候内核就运行出错了。
猜测是保存参数的时候,参数将内核映像覆盖了。于是检查一下u-boot的大小。在smdk2410.h中发现两个定义:
#define CFG_ENV_OFFSET 0x30000
#define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
其中第一个是参数表的偏移地址,第二个是参数表的大小。这个偏移值是接着u-boot映像后面的,u-boot映像大小默认最大为0x30000,即192k,在start.S中也有体现:
cpu/arm920t/start.S
#define UBOOT_RAM_BASE 0x 33f 80000
@ copy U-BOOT to RAM
ldr r0, =UBOOT_RAM_BASE
mov r1, #0x0
mov r2, #0x30000
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
如上可以看到,nand_read_ll接收三个参数,第一个为内存目标地址(r0),这个值为UBOOT_RAM_BASE,即为0x 33f 80000,这个地址在 64M 内存的 63.5M 的位置,即u-boot在目标板内存的高端(最后512K)运行;第二个参数(r1)为flash上的起始地址,这里是0,即从flash的0地址开始拷贝;第三个就是拷贝的大小(r3),这里是30000,即为192k。
这里也可以看出,arm是通过寄存器来给c函数传递参数的。
所以如果要修改u-boot映像的大小,需要修改两处:一为start.S中的拷贝映像的大小,还有一处就是参数表的偏移地址CFG_ENV_OFFSET。
由上可以看出,u-boot在flash上所占的空间为0x30000 + 0x20000 = 0x50000即为320k,而对比一下内核的烧写地址,为0x40000。很明显,内核映像已经给u-boot的参数表覆盖了,所以造成了读出来的内核出错。这里将参数表的大小修改为0x10000(64k)后,一切都正常了。