芯片到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.
1》 Basic ARM initialization
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