欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入
本文将使用sama5d3xek SPL实现做为例子
u-boot SPL (second program loader), 对许多人来说也说很陌生。下面对此进行一个简单介绍。
1. arm SoC的启动过程:
RomBoot –> SPL –> u-boot –> Linux kernel –> file system –> start application
(RomBoot是固化在SoC内部的。)
u-boot实现了一个新功能,能在编译u-boot的同时生成SPL二进制文件。
2. SPL运行代码go through
从u-boot-spl.lds链接文件可知,启动代码也是start.S.
(reset) <arch/arm/cpu/armv7/start.S> (b lowlevel_init: arch/arm/cpu/armv7/lowlevel_init.S) (b _main) –> <arch/arm/lib/crt0.S> (bl board_init_f) –> <arch/arm/lib/spl.c> (board_init_r) –> <common/spl/spl.c> (jump_to_image_no_args去启动u-boot) 到此SPL的生命周期结束。
简单来讲:SPL所做工作,一些硬件的初始化,然后读取u-boot,最后调转至u-boot.
3. 下面具体分析SPL的相关代码。
<arch/arm/cpu/armv7/start.S>
110 reset:
111 bl save_boot_params
112 /*
113 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
114 * except if in HYP mode already
115 */
116 mrs r0, cpsr
117 and r1, r0, #0x1f @ mask mode bits
118 teq r1, #0x1a @ test for HYP mode
119 bicne r0, r0, #0x1f @ clear all mode bits
120 orrne r0, r0, #0x13 @ set SVC mode
121 orr r0, r0, #0xc0 @ disable FIQ and IRQ
122 msr cpsr,r0
123
124 /*
125 * Setup vector:
126 * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
127 * Continue to use ROM code vector only in OMAP4 spl)
128 */
129 #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
130 /* Set V=0 in CP15 SCTRL register – for VBAR to point to vector */
131 mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register
132 bic r0, #CR_V @ V = 0
133 mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register
134
135 /* Set vector address in CP15 VBAR register */
136 ldr r0, =_start
137 mcr p15, 0, r0, c12, c0, 0 @Set VBAR
138 #endif
139
140 /* the mask ROM code should have PLL and others stable */
141 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
142 bl cpu_init_cp15
143 bl cpu_init_crit
144 #endif
145
146 bl _main
111:如果没有重新定义save_boot_params,则使用<arch/arm/cpu/armv7/start.S>中的save_boot_params.其不做任何事情,直接返回。
116~138: 看注释即可明白。
141: 因为SPL主要是对SoC进行初始化,所以不会定义CONFIG_SKIP_LOWLEVE_INIT, 即142,143行得以执行。
142: cpu_init_cpu15, 主要作用invalidate L1 I/D cache, disable MMU. 检查是否需要workaround.
143: cpu_init_crit直接跳转到lowlevel_init
下面看看lowlevel_init的实现:
<arch/arm/cpu/armv7/lowlevel_init.S>
18 ENTRY(lowlevel_init)
19 /*
20 * Setup a temporary stack
21 */
22 ldr sp, =CONFIG_SYS_INIT_SP_ADDR
23 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
24 #ifdef CONFIG_SPL_BUILD
25 ldr r9, =gdata
26 #else
27 sub sp, #GD_SIZE
28 bic sp, sp, #7
29 mov r9, sp
30 #endif
31 /*
32 * Save the old lr(passed in ip) and the current lr to stack
33 */
34 push {ip, lr}
35
36 /*
37 * go setup pll, mux, memory
38 */
39 bl s_init
40 pop {ip, pc}
41 ENDPROC(lowlevel_init)
[1][2][3]
相信人生有挫折没有失败,相信生命的质量来自决不妥协的信念。