目錄
-
-
-
- s5p4418 uboot sd卡方式啟動流程
- 鏡像檔案記憶體布局
- uboot啟動(BL1)
-
- start.S
- lowlevel_init.S
- _main
- board_init_f
- board_init_r
- main_loop
-
-
s5p4418 uboot sd卡方式啟動流程
4418上電後會先加載運作片内啟動代碼(BL0),大緻工作是判斷CPU的啟動方式,初始化啟動裝置。拷貝uboot前16k(BL1)到内部RAM,對代碼做校驗,然後開始運作BL1。4418的BL1也是廠商直接提供的,屬于閉源代碼。4418的BL1大緻由2nboot和2nboot配置組成,2nboot的配置可以在友善之臂的uboot源碼中找到(tools/nexell/nish/nanop2.txt)。2nboot大緻工作是初始化中斷向量,關閉看門口,初始化ddr記憶體,拷貝整個uboot到ddr,然後跳轉到ddr中運作uboot的後半部分(BL2)。
鏡像檔案記憶體布局
友善支之臂不同版本的2nboot代碼量大小不一樣,具體見我前兩篇部落格中的介紹
uboot 2010:https://blog.csdn.net/qq_16054639/article/details/105770048
uboot 2016:https://blog.csdn.net/qq_16054639/article/details/105829051
uboot啟動(BL1)
uboot中的CONFIG_SPL是沒有啟用的,整個uboot的前半部分啟動代碼是閉源的,是以手裡的源碼都是從後半部分開始的。
檢視源碼檔案/arch/arm/armv7/s5p4418/u-boot.lds
.text :
{
*(.__image_copy_start) //拷貝開始的位置
*(.vectors) //存放中斷向量表
CPUDIR/start.o (.text*)//代碼開始
*(.text*)
}
發現開始代碼段為vectors,這個vectors的來源是在配置檔案tools/nexell/nish/nanop2.txt中
E59FF018 // 0x000 : MOV PC, ResetV
E59FF018 // 0x004 : MOV PC, UndefV
E59FF018 // 0x008 : MOV PC, SWIV
E59FF018 // 0x00C : MOV PC, PAbortV
E59FF018 // 0x010 : MOV PC, DAbortV
E59FF018 // 0x014 : MOV PC, NotUsed
E59FF018 // 0x018 : MOV PC, IRQV
E59FF018 // 0x01C : MOV PC, FIQV
FFFF0200 // 0x020 : SRAMBASE + Header
FFFF0204 // 0x024 : SRAMBASE + Header
FFFF0208 // 0x028 : SRAMBASE + Header
FFFF020C // 0x02C : SRAMBASE + Header
FFFF0210 // 0x030 : SRAMBASE + Header
FFFF0214 // 0x034 : SRAMBASE + Header
FFFF0218 // 0x038 : SRAMBASE + Header
FFFF021C // 0x03C : SRAMBASE + Header
start.S
之後接着開始代碼/arch/arm/armv7/start.S
.globl reset
.globl save_boot_params_ret
reset:
/* Allow the board to save important registers */
b save_boot_params
save_boot_params_ret:
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr
and r1, r0, #0x1f @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #0x1f @ clear all mode bits
orrne r0, r0, #0x13 @ set SVC mode
orr r0, r0, #0xc0 @ disable FIQ and IRQ
msr cpsr,r0
/*
* Setup vector:
* (OMAP4 spl TEXT_BASE is not 32 byte aligned.
* Continue to use ROM code vector only in OMAP4 spl)
*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) //沒配置這裡不會執行
/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
bic r0, #CR_V @ V = 0
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15
bl cpu_init_crit
#endif
bl _main
執行流程:
- save_boot_params(沒做什麼)
- save_boot_params_ret(禁用中斷,設定運作模式)
- cpu_init_cp15(初始化cp15寄存器,主要設定cache,mmu,TLBs位址映射表,不深入分析)
- cpu_init_crit
- ->lowlevel_init(其實也沒做什麼,祥見下文)
- _main(開始後半部分初始化)
lowlevel_init.S
/arch/arm/armv7/lowlevel_init.S

執行流程:
- 初始化C語言棧
- 初始化global data全局結構體起始位址
- s_init(什麼也沒做)
_main
/arch/arm/lib/crt0.S
執行流程:
- 設定c語言運作環境(設定sp指針)
- board_init_f_mem(初始化記憶體配置,起始就是向global data寫入棧頂位址,malloc起始位址)
- board_init_f(這個很重要,初始化了很多功能)
- 繼續填充global data結構體參數(不深入分析)
- coloured_LED_init(初始化LED)
- red_led_on(點亮LED)
- board_init_r(很重要初始化了非常多東西)
board_init_f
/common/board_f.c
board_init_f這個函數主要周遊執行了init_sequence_f這個數組中的函數
挑出幾個主要關鍵函數解釋:
- fdtdec_setup(初始化裝置樹描述符)
- arch_cpu_init(初始化cpu,時鐘)
- initf_dm(初始化dm驅動架構,掃描裝置樹,初始化裝置節點)
- timer_init(初始化時鐘線)
- env_init(讀取環境變量)
- show_board_info(列印闆子資訊)
board_init_r
/common/board_c.c
board_init_r函數跟board_init_f函數類似,也是周遊執行一個數組中的所有函數
挑出幾個主要關鍵函數解釋:
- initr_dm(初始化裝置樹描述符)
- board_init(闆級初始化)
- initr_net(初始化網絡驅動)
- run_main_loop(進入主循環)
main_loop
執行流程:
-
run_preboot_environment_command(執行預設環境變量指令,也就是啟動指令preboot)
preboot定義在include/env_default.h
#ifdef CONFIG_PREBOOT
"preboot=" CONFIG_PREBOOT "\0" //CONFIG_PREBOOT這個宏沒有定義,是以這裡等于什麼也沒做
#endif
- bootdelay_process(等待使用者按下按鍵,按下按鍵将進入指令行模式,如果沒有按下将傳回系統啟動指令bootcmd)
- autoboot_command(如果上一步有指令,執行上一步傳回的指令)
- cli_loop(進入指令行模式)
至此整個uboot的主要啟動流程就梳理結束了