硬件平台:飛思卡爾iMX258 ARM9 CPU +256MB的Nand Flash(uboot存放在此中)
首先通過uboot的鏈接文件,其中text段為uboot的代碼段,我們可以看到uboot運行時執行的第一段代碼在start.S中:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4); //於4個字節對齊
.text : //代碼段
{
cpu/arm926ejs/start.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } //只讀數據段
. = ALIGN(4);
.data : { *(.data) } //讀寫數據段
. = ALIGN(4);
.got : { *(.got) } //uboot特有段
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) } //uboot命令段
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); } // bss段
_end = .;
}
找到start.s這個文件,以這個文件為起點看uboot的啟動流程。這裡我通過一個圖來說明這個過程。
由於iMX258內部具有有32KB的ROM(包括HAB)和128KB的RAM,在uboot加載前,CPU先運行iROM裡面的一部分代碼,這部分代碼為芯片出廠時固化,它根據熔絲配置值可以檢測到uboot存放在外部Nand Flash中,所以先copy最前邊的一部分uboot代碼(即start.s)到內部RAM運行。以上過程CPU上電後就會自動執行,前提是你已經通過熔絲配置好CPU的啟動模式等參數。
下面是iMAX25在start.s特有的一部分代碼,它完成了把uboot接下來的代碼copy到RAM的功能(內部RAM的地址為0x7802_0000~0x7fff_ffff,外部SDRAM的地址為0x8000_0000~0x8fff_ffff)。
#ifdef CONFIG_MX25
/* Copy vectors to mask ROM indirect addr */
adr r0, _start /* r0 <- current position of code */
ldr r1, =0x7801FFC0 /*把RAM 從0x7801FFC0開始的地址裝入r1*/
mov r2, #16 /*計數寄存器*/
copyex:
subs r2, r2, #1 /*循環16次,一次copy 4個字,總共1kb*/
ldr r3, [r0], #4 /*將存儲器地址為r0的字數據-> r3,然後再把r0+4->r0*/
str r3, [r1], #4 /*把r3中的數據加載到r1所對應的地址上,然後r1+4->r1*/
bne copyex /*r2若不等於0,跳至copyex*/