之前介绍的uboot源码中smdk2410开发板的重定位方式只支持板子从nand启动,可以从重定位的copy_loop看出:
重定位时cpu直接从flash中读数据,写入目的地址(位于SDRAM),这样的方式只能用在norflash中启动的代码上,nandflash中的内容不能像这样简单地通过指令读写。
smdk2410的重定位方式支持把代码重定位到任何地址上,但这种方式有两个缺点:
1、重定位代码复杂
2、会增加需要移植的uboot的体积,因为需要增加rel.dyn段,记录 保存着全局变量地址的LABEL的地址
现在采用直接指定uboot链接地址的方法,重写重定位代码,使板子能从nandflash启动。
需要做如下工作:
1、去掉 "-pie"选项,链接时不生成rel.dyn段
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 注释掉这行
2、board/samsung/smdk2440目录中增加init.c文件,里面加入对nandflash读写的代码:
并在makefile中添加init.o目标文件:
3、修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
./arch/arm/cpu/u-boot.lds:
这是因为s3c2440如果设置为nand启动,上电后会nandflash中的前4k内容读到cpu内部ram执行,要保证我们自己实现的nand的读写、初始化函数、重定位等代码位于前4k才能被正确执行。
4、修改start.S
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /*sp = 30000f80*/ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ //由于nandflash是c函数,在调用c函数之前要先设置栈 bl nand_init_ll //调用nand初始化函数 mov r0, #0 //设置r0,r1,r2,传参给copy_code_to_sdram //ldr r1, =_start ldr r1, _TEXT_BASE ldr r2, _bss_start_ofs bl copy_code_to_sdram //重定位代码c函数 bl clear_bss //清除bss段 ldr pc, =call_board_init_f /* Set stackpointer in internal RAM to call board_init_f */ call_board_init_f: ldr r0,=0x00000000 bl board_init_f /*board_init_f 的返回值(unsigned int)id的值存在r0里,传参给board_init_r用*/ ldr r1, _TEXT_BASE /*调用第二阶段代码*/ bl board_init_r
5、在board.c文件中,在board_init_f函数末尾把relocate_code(addr_sp, id, addr)注释掉
因为之前在start.S中调用了重定位函数,这边就不需要再重定位了。
6、之前smdk2410在SDRAM中给uboot留了一段空间用于保存重定位之后的uboot代码,现在保存uboot的地址由自己定义,为0x33f000000,需要把borad.c中的
board_init_f函数里addr变量赋值为0x33f000000。
重新编译uboot,从nandflash启动会打印出uboot信息,说明nandflash启动成功: