u-boot屬於兩階段的bootloader,第一階段的文件為 arch/arm/cpu/armv7/start.S 和 arch/arm/cpu/armv7/lowlevel_init.S,前者是平台相關的,后者是開發板相關的。
1. u-boot第一階段代碼分析
(1)硬件設備初始化
將CPU的工作模式設為管理模式(SVC);
關閉中斷;
禁用MMU,TLB ;
板級初始化;
(2)為加載Bootloader的第二階段代碼准備RAM空間
加載u-boot.img,跳轉到u-boot.img;
上述工作,也就是uboot-spl代碼流程的核心。
代碼如下:
arch/arm/cpu/armv7/start.S
1 /* 2 * the actual reset code 3 */ 4 reset: 5 bl save_boot_params 6 /* 7 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, 8 * except if in HYP mode already 9 */ 10 mrs r0, cpsr 11 and r1, r0, #0x1f @ mask mode bits 12 teq r1, #0x1a @ test for HYP mode 13 bicne r0, r0, #0x1f @ clear all mode bits 14 orrne r0, r0, #0x13 @ set SVC mode 15 orr r0, r0, #0xc0 @ disable FIQ and IRQ 16 msr cpsr,r0 17 @@ 以上通過設置CPSR寄存器里設置CPU為SVC模式,禁止中斷 18 @@ 具體操作可以參考《[kernel 啟動流程] (第二章)第一階段之——設置SVC、關閉中斷》的分析 19 20 /* the mask ROM code should have PLL and others stable */ 21 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 22 bl cpu_init_cp15 23 @@ 調用cpu_init_cp15,初始化協處理器CP15,從而禁用MMU和TLB。 24 @@ 具體操作可以參考[kernel 啟動流程] (第六章)第一階段之——打開MMU兩篇文章的分析 25 bl cpu_init_crit 26 @@ 調用cpu_init_crit,進行一些關鍵的初始化動作,也就是板級的初始化 27 @@ 后面會有一小節進行分析 28 #endif 29 30 bl _main 31 @@ 跳轉到主函數,也就是要加載BL2以及跳轉到BL2的主體部分 32 /*------------------------------------------------------------------------------*/
cpu_init_crit
cpu_init_crit,進行一些關鍵的初始化動作,也就是平台級和板級的初始化。其代碼核心就是lowlevel_init,如下
arch/arm/cpu/armv7/start.S
1 ENTRY(cpu_init_crit) 2 /* 3 * Jump to board specific initialization... 4 * The Mask ROM will have already initialized 5 * basic memory. Go here to bump up clock rate and handle 6 * wake up conditions. 7 */ 8 b lowlevel_init @ go setup pll,mux,memory 9 ENDPROC(cpu_init_crit)
所以說lowlevel_init就是這個函數的核心。
arch/arm/cpu/armv7/lowlevel_init.S
1 ENTRY(lowlevel_init) 2 /* 3 * Setup a temporary stack 4 */ 5 ldr sp, =CONFIG_SYS_INIT_SP_ADDR 6 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 7 #ifdef CONFIG_SPL_BUILD 8 ldr r9, =gdata 9 #else 10 sub sp, sp, #GD_SIZE 11 bic sp, sp, #7 12 mov r9, sp 13 #endif 14 /* 15 * Save the old lr(passed in ip) and the current lr to stack 16 */ 17 push {ip, lr} 18 @@設置好棧,為接下來的C環境做好准備 19 /* 20 * go setup pll, mux, memory 21 */ 22 bl s_init 23 pop {ip, pc} 24 ENDPROC(lowlevel_init)
以Am335x為例,在移植過程中,就需要在lowlevel_init.S里加入一些簡單的板級初始化,例如在lowlevle_init.s------->s_init中:
arch/arm/cpu/armv7/am33xx/board.c
void s_init(void) { .... /* * Save the boot parameters passed from romcode. * We cannot delay the saving further than this, * to prevent overwrites. */ #ifdef CONFIG_SPL_BUILD save_omap_boot_params(); @@ #endif #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_NOR_BOOT) watchdog_disable(); //arch/arm/cpu/armv7/am33xx/board.c timer_init(); set_uart_mux_conf(); // board/ti/am335x/board.c setup_clocks_for_console(); // arch/arm/cpu/armv7/am335x/Clock_am33xx.c uart_soft_reset(); // arch/arm/cpu/armv7/am33xx/board.c #endif .... gd = &gdata; preloader_console_init(); @@ .... #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_NOR_BOOT) prcm_init(); set_mux_conf_regs(); #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) /* Enable RTC32K clock */ rtc32k_enable(); #endif sdram_init(); #endif }
(待續...)
