u-boot中SPL源代码分析

系统大全为您提供

 本文将使用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

u/armv7/start.S> (b lowlevel_init: arch/arm

u/armv7/lowlevel_init.S) (b _main) --> <arch/arm

b/crt0.S> (bl board_init_f) --> <arch/arm

b/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

u/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

u/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

u/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)

22: 对stack pointer赋值成CONfig_SYS_INIT_SP_ADDR

23: 确保sp是8字节对齐。

25:将gdata的地址存入到r9寄存器中。

39:跳转到s_init.对Atmel sama5d3xek board, s_init定义在:<arch/arm

u/at91-common/spl.c> 此处暂时不分析。

然后返回到start.S处,接下来调用:bl _main到<arch/arm

b/crt0.S>

58 ENTRY(_main)

59

60 /*

61  * Set up initial C runtime environment and call board_init_f(0)。

62  */

63

64 #if defined(CONfig_SPL_BUILD) && defined(CONfig_SPL_STACK)

65         ldr     sp, =(CONfig_SPL_STACK)

66 #else

67         ldr     sp, =(CONfig_SYS_INIT_SP_ADDR)

68 #endif

 70         sub     sp, #GD_SIZE    /* allocate one GD above SP */

71         bic     sp, sp, #7      /* 8-byte alignment for ABI compliance */

72         mov     r9, sp          /* GD is above SP */

73         mov     r0, #0

74         bl      board_init_f

65: 重新对SP赋值

69: 确认sp是8字对齐

70:相当于保留一个global_data的大小。

71: 确认更新后的sp是8字对齐

72:r9指向global_data

73:r0赋值0

74:跳转到board_init_f中运行。

board_init_f在<arch/arm

b/spl.c>定义:

20 /*

21  * In the context of SPL, board_init_f must ensure that any clocks/etc for

22  * DDR are enabled, ensure that the stack pointer is valid, clear the BSS

23  * and call board_init_f.  We provide this version by default but mark it

24  * as __weak to allow for platforms to do this in their own way if needed.

25  */

26 void __weak board_init_f(ulong dummy)

27 {

28         /* Clear the BSS. */

29         memset(__bss_start, 0, __bss_end - __bss_start);

30

31         /* Set global data pointer. */

32         gd = &gdata;

33

34         board_init_r(NULL, 0);

35 }

26: board_init_f是一个函数,是可以被重新定义的。

29:对BSS段进行清零操作。

34: 跳转到board_init_r

board_init_r在<common/spl/spl.c>中定义:

132 void board_init_r(gd_t *dummy1, ulong dummy2)

133 {

134         u32 boot_device;

135         debug("》spl:board_init_r()

");

136

137 #ifdef CONfig_SYS_SPL_MALLOC_START

138         mem_malloc_init(CONfig_SYS_SPL_MALLOC_START,

139                         CONfig_SYS_SPL_MALLOC_SIZE);

140 #endif

141

142 #ifndef CONfig_PPC

143         /*

144          * timer_init() does not exist on PPC systems. The timer is initialized

145          * and enabled (decrementer) in interrupt_init() here.

146          */

147         timer_init();

148 #endif

149

150 #ifdef CONfig_SPL_BOARD_INIT

151         spl_board_init();

152 #endif

135: 输出debug信息:》spl:board_init_r();

137~140: 如果定义了:CONfig_SYS_SPL_MALLOC_START, 则进行memory的malloc池初始化。以后调用malloc就在这个池子里面分配内存。

142~148: 如果没有定义:CONfig_PPC, 则进行timer的初始化:timer_init() <arm/arm

u/armv7/at91/time.c>

150~150: CONfig_SPL_BOARD_INIT, 则调用spl_board_init()。 这是board相关的定义,<board/atmel

ma5d3xek

ma5d3xek.c>

一切就绪后,就要检查从什么设备来启动了。这里就贴出RAM,MMC, NAND相关代码

154         boot_device = spl_boot_device();

155         debug("boot device - %d

", boot_device);

156         switch (boot_device) {

157 #ifdef CONfig_SPL_RAM_DEVICE

158         case BOOT_DEVICE_RAM:

159                 spl_ram_load_image();

160                 break;

161 #endif

162 #ifdef CONfig_SPL_MMC_SUPPORT

163         case BOOT_DEVICE_MMC1:

164         case BOOT_DEVICE_MMC2:

165         case BOOT_DEVICE_MMC2_2:

166                 spl_mmc_load_image();

167                 break;

168 #endif

169 #ifdef CONfig_SPL_NAND_SUPPORT

170         case BOOT_DEVICE_NAND:

171                 spl_nand_load_image();

172                 break;

173 #endif

154: 获取spl_boot_device,即从什么设备启动。

157~161:如果定义了CONfig_SPL_RAM_DEVICE, 则执行spl_ram_load_image(),其就是将image下载到ram中。

162~168:如果定义了CONfig_SPL_MMC_SUPPORT, 则执行spl_mmc_load_image(),其就是将image从mmc/sd里面读取到ram中。

169~173:如果定义了CONfig_SPL_NAND_SUPPORT, 则执行spl_nand_load_image(), 其就是将image从nand flash中读取到ram中。

当要启动的image位于RAM中后,我们就可以启动之。

213         switch (spl_image.os) {

214         case IH_OS_U_BOOT:

215                 debug("Jumping to U-Boot

");

216                 break;

217 #ifdef CONfig_SPL_OS_BOOT

218         case IH_OS_LINUX:

219                 debug("Jumping to Linux

");

220                 spl_board_prepare_for_linux();

221                 jump_to_image_linux((void *)CONfig_SYS_SPL_ARGS_ADDR);

222 #endif

223         default:

224                 debug("Unsupported OS image Jumping nevertheless

");

225         }

226         jump_to_image_no_args(&spl_image);

227 }

213: 判断image的类型。

 

214:如果是u-boot,则直接到227去运行u-boot.

218:如果是Linux,则到221去启动Linux.

至此,SPL结束它的生命,控制权交于u-boot或Linux.

 

以上就是系统大全给大家介绍的如何使的方法都有一定的了解了吧,好了,如果大家还想了解更多的资讯,那就赶紧点击系统大全官网吧。

 

本文来自系统大全http://www.win7cn.com/如需转载请注明!推荐:win7纯净版

相关文章

预装win11的电脑也可以安装win7系统,本文详细介绍了具体操作...
Win11和Win7双系统可以兼顾新系统的功能和旧系统的兼容性,但...
Win7无法直接升级Win11,需要全新安装。升级前请备份重要数据...
这篇win7改win11详细教程,带你一步步完成系统升级,包括备份...
Win7和Win11跑分对比结果出人意料,Win7在某些场景下性能表现...
Win7之家显卡天梯图为您提供最全面的显卡性能对比和选择指南...