本次移植跟以往的不同之處是采用了spl來引導u-boot,參考了博客http://blog.csdn.net/fulinus/article/details/42738641
下載鏈接:http://pan.baidu.com/s/1bnlRKgn
使用方法:
1、 編譯
make tq2440_defconfig
make
2、 然后會在u-boot根目錄下生成u-boot.bin,在spl目錄下會生成u-boot-spl.bin,目前的分區是:
| u-boot-spl.bin (1M) |
u-boot.bin (1M) |
kernel (3M) |
rootfs (剩余) |
自己可以改動,在arch/arm/lib/crt0.S中:
#if defined(CONFIG_SPL_BUILD)
/* Read u-boot from Nandflash to SDRAM address $CONFIG_SYS_TEXT_BASE */
ldr r0, =CONFIG_UBOOT_MTD_ADDR /*u-boot鏡像在NandFlash中存儲地址*/
ldr r1, =CONFIG_SYS_TEXT_BASE /*u-boot在內存中的加載地址*/
ldr r2, =CONFIG_UBOOT_LENGTH /*u-boot鏡像的大小*/
bl copy_code_to_sdram
ldr pc, =CONFIG_SYS_TEXT_BASE
#else
bl board_init_f
#endif
3、目前支持NandFlash和DM9000。
4、為什么要用spl來引導u-boot?
對於tq2440,采用的是S3C2440,當從NandFlash啟動時,上電時S3C2440內部固化的程序自動把NandFlash的前4KB程序拷貝到片內SRAM,然后執行IRAM中的程序,同時要保證這4KB中的程序是位置無關碼,在這4KB程序完成了內存的初始化,棧的設置,NandFlash的初始化,將u-boot鏡像從NandFlash中拷貝到內存中,將PC跳轉到內存中執行。
隨着u-boot的更新,在u-boot的前4K已經無法完成上面這些事,在前4KB會執行位置相關碼,導致u-boot無法正常運行。
為了解決這個問題,u-boot提供了SPL,用spl來引導u-boot,spl的體積很小,只完成將u-boot從NandFlash中拷貝到內存中,然后跳轉到內存。
5、可能存在的問題:
由於從NandFlash啟動的時候,IRAM被映射到了0地址處,現在是用spl引導u-boot,所以IRAM中是spl,如果有中斷發生,PC執行的是spl中程序,而不是u-boot中的,可以考慮u-boot啟動后,在將u-boot的前4KB拷貝到IRAM中。
后來再次閱讀了u-boot代碼,發現上面的這個擔心純屬多余,這個u-boot在代碼重定位,並且修改完相關的符號信息后,緊接着又將中斷向量也進行了重定位,即將最終u-boot代碼段在內存中運行起始地址的前64字節拷貝到了SRAM的0x0處,這樣如果發生了中斷也不用怕跳飛了。
下面我們簡單看一下:
相關代碼路徑:
中斷向量表:arch/arm/lib/vectors.S
復位異常入口:arch/arm/cpu/arm920t/start.S
_main: arch/arm/lib/crt0.S
board_init_f:common/board_f.c
relocate_code: arch/arm/lib/relocate.S
relocate_vectors: arch/arm/lib/relocate.S
board_init_r:common/board_r.c
main_loop: common/main.c
cli_loop: common/cli.c
parse_file_outer: common/cli_hush.c
crt0.S:
#if ! defined(CONFIG_SPL_BUILD)
/*
* Set up intermediate environment (new sp and gd) and call
* relocate_code(addr_moni). Trick here is that we'll return
* 'here' but relocated.
*/
ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
adr lr, here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
here:
/*
* now relocate vectors
*/
bl relocate_vectors
relocate_code 和 relocate_vectors:
ENTRY(relocate_vectors)
/*
* Copy the relocated exception vectors to the
* correct address
* CP15 c1 V bit gives us the location of the vectors:
* 0x00000000 or 0xFFFF0000.
*/
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
mrc p15, 0, r2, c1, c0, 0 /* V bit (bit[13]) in CP15 c1 */
ands r2, r2, #(1 << 13)
ldreq r1, =0x00000000 /* If V=0 */
ldrne r1, =0xFFFF0000 /* If V=1 */
ldmia r0!, {r2-r8,r10}
stmia r1!, {r2-r8,r10}
ldmia r0!, {r2-r8,r10}
stmia r1!, {r2-r8,r10}
bx lr
ENDPROC(relocate_vectors)
ENTRY(relocate_code)
ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */
subs r4, r0, r1 /* r4 <- relocation offset */
beq relocate_done /* skip relocation */
ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */
copy_loop:
ldmia r1!, {r10-r11} /* copy from source address [r1] */
stmia r0!, {r10-r11} /* copy to target address [r0] */
cmp r1, r2 /* until source end address [r2] */
blo copy_loop
/*
* fix .rel.dyn relocations
*/
ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */
ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */
fixloop:
ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */
and r1, r1, #0xff
cmp r1, #23 /* relative fixup? */
bne fixnext
/* relative fix: increase location by offset */
add r0, r0, r4
ldr r1, [r0]
add r1, r1, r4
str r1, [r0]
fixnext:
cmp r2, r3
blo fixloop
relocate_done:
這個關於relocation原理的解析參考博客:
uboot的relocation原理詳細分析
