芯片到uboot啟動流程
ROM → SPL→ uboot.img
簡介
在335x 中ROM code是第一級的bootlader。mpu上電后將會自動執行這里的代碼,完成部分初始化和引導第二級的bootlader,第二級的bootlader引導第三級bootader,在ti官方上對于第二級和第三級的bootlader由uboot提供。
SPL
To unify all existing implementations for a secondary program loader (SPL) and to allow simply adding of new implementations this generic SPL framework has been created. With this framework almost all source files for a board can be reused. No code duplication or symlinking is necessary anymore.
2》 UART console initialization
3》 Clocks and DPLL locking (minimal)
4》 SDRAM initialization
5》 Mux (minimal)
6》 BootDevice initialization(based on where we are booting from.MMC1/MMC2/Nand/Onenand)
7》 Bootloading real u-boot from the BootDevice and passing control to it.
uboot spl源代碼分析
一、makefile分析
打開spl文件夾只有一個makefile 可見spl都是復用uboot原先的代碼。
主要涉及的代碼文件為u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7
u-boot-2011.09-psp04.06.00.03/arch/arm/lib
u-boot-2011.09-psp04.06.00.03/drivers
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-spl.lds
這個為鏈接腳本
二、u-boot-spl.lds
__start 為程序開始
__image_copy_end
_end
三、代碼解析
__start 為程序開始 (arch/arm/cpu/armv7/start.S)
.globl _start 這是在定義u-boot的啟動定義入口點,匯編程序的缺省入口是 start標號,用戶也可以在連接腳本文件中用ENTRY標志指明其它入口點。
.global是GNU ARM匯編的一個偽操作,聲明一個符號可被其他文檔引用,相當于聲明了一個全局變量,.globl和.global相同。該部分為處理器的異常處理向量表。地址范圍為0x0000 0000 ~ 0x0000 0020,剛好8條指令。
為什么是8條指令呢?這里來算一算。首先,一條arm指令為32bit(位),0x0000 0020換算成十進制為2^5=32B(字節),而32(B) = 4 * 8(B) = 4 * 8 * 8( bit),所以剛好8條指令(一個字節Byte包含8個位bit)。
下面是在匯編程序種經常會遇到的異常向量表。Arm處理器一般包括復位、未定義指令、SWI、預取終止、數據終止、IRQ、FIQ等異常,其中U-Boot中關于異常向量的定義如下:
_start: b reset
_start 標號表明oot程序從這里開始執行。
b是不帶返回的跳轉(bl是帶返回的跳轉),意思是無條件直接跳轉到reset標號出執行程序。b是最簡單的分支,一旦遇到一個 b 指令,ARM處理器將立即跳轉到給定的地址,從那里繼續執行。注意存儲在分支指令中的實際的值是相對當前的R15的值的一個偏移量;而不是一個絕對地址。它的值由匯編器來計算,它是 24 位有符號數,左移兩位后有符號擴展為32 位,表示的有效偏移為 26 位。
ldr pc, _undefined_instr tion //未定義指令
ldr pc, _software_interrupt //軟中斷SWI
ldr pc, _prefetch_abort //預取終止
ldr pc, _data_abort //數訪問終止
ldr pc, _not_used
ldr pc, _irq //中斷請求IRQ
ldr pc, _fiq //快速中斷FIQ
#ifdef CONFIG_SPL_BUILD //該階段為spl執行下面代碼
_undefined_instruction: .word _undefined_instruction
_software_interrupt: .word _software_interrupt
_prefetch_abort: .word _prefetch_abort
_data_abort: .word _data_abort
_not_used: .word _not_used
_irq: .word _irq
_fiq: .word _fiq
_pad: .word 0x12345678 /* now 16*4=64 */
#else
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
_pad: .word 0x12345678 /* now 16*4=64 */
#endif /* CONFIG_SPL_BUILD */
.word為ARM匯編特有的偽操作符,語法如下:
.word {,} …
作用:插入一個32-bit的數據隊列。(與armasm中的DCD功能相同)
.balignl 16,0xdeadbeef
.align偽操作用于表示對齊方式:通過添加填充字節使當前位置滿足一定的對齊方式。
接下來是對各個段代碼的定義
略
Rest: (arch/arm/cpu/armv7/start.S)
bl save_boot_params
save_boot_params: (arch/arm/cpu/armv7/ti81xx/lowlevel_init.S)
#ifdef CONFIG_SPL_BUILD
ldr r4, =ti81xx_boot_device
//ti81xx_boot_device = BOOT_DEVICE_NAND
//啟動方式
ldr r5, [r0, #BOOT_DEVICE_OFFSET]
and r5, r5, #BOOT_DEVICE_MASK
str r5, [r4]
#endif
bx lr
回到reset:(arch/arm/cpu/armv7/start.S)
//設置cpu的工作模式設置CPU的狀態類型為SVC特權模式
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
cpu_init_crit: (arch/arm/cpu/armv7/start.S)
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
//關閉mmu 緩存
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
#ifdef CONFIG_SYS_ICACHE_OFF
bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache
#else
orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache
#endif
mcr p15, 0, r0, c1, c0, 0
//調用初始化函數
mov ip, lr @ persevere link reg across call
bl lowlevel_init @ go setup pll,mux,memory
lowlevel_init:(arch/arm/cpu/armv7/ti81xx/lowlevel.S)
/* The link register is saved in ip by start.S */
mov r6, ip
/* check if we are already running from RAM */
ldr r2, _lowlevel_init
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE /* Load address (RAM) */
#define CONFIG_SYS_TEXT_BASE 0x80800000
SDRAM的前8MB作為spl的bss段然后前64bytes做為u-boot.img的頭
ldr r3, _TEXT_BASE
sub r4, r2, r3
sub r0, pc, r4
//設置堆棧指針
/* require dummy instr or subtract pc by 4 instead i‘m doing stack init */
ldr sp, SRAM_STACK
mark1:
ldr r5, _mark1
sub r5, r5, r2 /* bytes between mark1 and lowlevel_init */
sub r0, r0, r5 /* r0 《- _start w.r.t current place of execution */
mov r10, #0x0 /* r10 has in_ddr used by s_init() */
ands r0, r0, #0xC0000000 /* MSB 2 bits 《》 0 then we are in ocmc or DDR */
cmp r0, #0x80000000
bne s_init_start
mov r10, #0x01
b s_init_start
s_init_start:(arch/arm/cpu/armv7/ti81xx/lowlevel.S)
mov r0, r10 /* passing in_ddr in r0 */
bl s_init
初始化pll mux memery
/* back to arch calling code */
mov pc, r6
call_board_init_f:(arch/arm/cpu/armv7/start.s)
//設置堆棧指針,并調用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
void board_init_f(ulong dummy)
『u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7/omap-common/spl.c』
調用relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE);
這里使用了 CONFIG_SPL_STACK
#define CONFIG_SPL_STACK LOW_LEVEL_SRAM_STACK
#define LOW_LEVEL_SRAM_STACK (SRAM0_START + SRAM0_SIZE – 4)
gdata 為.bss 前一段的空間描述鏡像頭
#define CONFIG_SPL_TEXT_BASE 0x402F0400
relocate_code: (arch/arm/cpu/armv7/start.s)
重載定位代碼
jump_2_ram: (arch/arm/cpu/armv7/start.s)
跳轉到spl的第二階段
board_init_r:(u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7/omap-common/spl.c)
初始化時鐘: timer_init()
i2c 初始化: i2c_init();
獲取啟動方式 omap_boot_device();
判斷啟動方式從不同的地方裝載鏡像
從mmc 中裝載鏡像 spl_mmc_load_image();
從nand 中裝載鏡像 spl_nand_load_image();
從 uart 中裝載鏡像 spl_ymodem_load_image();
判斷鏡像類型
跳轉到鏡像中執行鏡像 jump_to_image_no_args();
裝載鏡像 將會從配置的存儲介質中讀取數據 及uboot鏡像
然后跳轉到uboot中執行uboot
評論
查看更多