上一节完成时钟和串口的修改,下面进行nandflash的启动。
本节介绍如何从nandflash启动并从nandflash重定位到SDRAM
1、原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)",使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K)
1.1、去掉 "-pie"选项
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行
1.2、参考"毕业班第1课"的start.S, init.c来修改代码
1.2.1、把init.c放入board/samsung/smdk2440目录, 修改config.mk(arch/arm/config.mk)
1.2.2、修改CONFIG_SYS_TEXT_BASE为0x33f80000(内存是64M(0x34000000),0x34000000-0x33f80000 = 0x80000=512k,uboot一般不会超过512k):
#define CONFIG_SYS_TEXT_BASE 0x33f80000 //include/configs/smdk2440.h
1.2.3、修改start.S
/* Set stackpointer in internal RAM to call board_init_f */
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
bl nand_init_ll
mov r0, #0
//ldr r1, =_start
//_TEXT_BASE = CONFIG_SYS_TEXT_BASE = 0x33f80000
// 内存是64M(0x34000000),0x34000000-0x33f80000 = 0x80000=512k,uboot一般不会超过512k
ldr r1, _TEXT_BASE
ldr r2, _bss_start_ofs
bl copy_code_to_sdram
bl clear_bss
ldr pc, =call_board_init_f
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f
#if 0
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
bl board_init_f
#endif
说明:清bss段时参考官方代码获取bss段起始地址(在arch\arm\cpu/u-boot.lds)
void clear_bss(void)
{
extern int __bss_start, __bss_end__;
int *p = &__bss_start;
for (; p < &__bss_end__; p++)
*p = 0;
}
1.3、修改board_init_f, 把relocate_code去掉
修改start.s时已经进行代码的重定位,所以需要将relocate_code去掉。(board_init_f(arch/arm/lib/board.c)-->relocate_code)
1.4、开始第二阶段board_init_r(arch/arm/lib/board.c)
在完成第一阶段时跳转到第二阶段:
board_init_r(gd_t *id, ulong dest_addr) 参数是id和链接地址;board_init_f函数中已经确定id值,直接返回可用。
arch/arm/lib/board.c
unsigned int board_init_f(ulong bootflag)
{
......
return (unsigned int)id;
}
arch/arm/cpu/arm920t/start.s
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f
/*函数board_init_f返回的id值已经存在r0里,刚好给board_init_r*/
ldr r1,_TEXT_BASE
/*调用第二阶段*/
bl board_init_r
1.5、修改makefile和链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
board/samsung/smdk2440/makefile:
COBJS := smdk2410.o init.o
SOBJS := lowlevel_init.o
./arch/arm/cpu/u-boot.lds:
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
__image_copy_start = .;
CPUDIR/start.o (.text)
board/samsung/smdk2440/libsmdk2440.o(.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
*(.data)
}
由于添加的init.c回合smdk2410.c共同编译成libsmdk2440.o,所以只添加smdk2410.o。
编译make,编译成功后进行反汇编查看重定位代码copy_code_to_sdram是否在前4k。
arm-linux-objdump -D u-boot > u-boot.dis
上图可以在前4k,查看
编译后的链接脚本确定代码运行大小,因为全局变量放在bss段,所以查看反汇编的bss地址
0xa34ec=653k > 512k;所以之前设置的#define CONFIG_SYS_TEXT_BASE 0x33f80000 满足不了空间,修改
#define CONFIG_SYS_TEXT_BASE 0x33f00000 (1M空间),重新编译烧录到nandflash。
表明从nandflash启动成功,下一步进行根据打印信息进行修改