arch/arm/lib/crt0.S:
/*
此文件处理U-Boot启动的与目标无关的阶段,其中需要C运行时环境。它的入口点是_main,并从目标的
start.S文件跳转到它。
_main执行顺序为:
1.为调用board_init_f()设置初始环境。该环境只提供一个堆栈和一个存储GD(“全局数据”)结构的位置,两
者都位于一些可用的RAM (SRAM、锁定的缓存……)中。在这种情况下,变量全局数据,不管是否初始化(BSS),
都是不可用的;只有常量初始化的数据可用。在调用board_init_f()之前,GD应该被归零。
2.调用board_init_f ()。该函数为从系统RAM (DRAM, DDR…)执行准备硬件。由于系统RAM可能还不可用,所
以board_init_f()必须使用当前的GD来存储必须传递给后续阶段的数据。这些数据包括重定位目的地、未来堆
栈和未来的GD位置。
3.设置中间环境,其中堆栈和GD是由系统RAM中的board_init_f()分配的,但是BSS和初始化的非const数据仍
然不可用。
4a.对于U-Boot(不是SPL),调用relocate_code()。此函数将U-Boot从当前位置重定位到由board_init_f()
计算的重定位目的地。
4b.对于SPL, board_init_f()只返回(到crt0)。在SPL中没有代码重定位。
5.设置调用board_init_r()的最终环境。这个环境有BSS(初始化为0)、non-const数据(初始化为它们的预期
值)和系统RAM中的堆栈(SPL将堆栈和GD移到RAM中是可选的—请参阅CONFIG_SPL_STACK_R)。GD保留了
board_init_f()设置的值。
6.对于U-Boot来说(不是SPL),有些cpu此时还有一些内存方面的工作要做,所以调用
c_runtime_cpu_setup。
7.部门board_init_r ()。
有关更多信息,请参见“自述板初始化流程”。
*/
ENTRY(_main)
/*
* Set up initial C runtime environment and call board_init_f(0).
*/
//#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
// ldr r0, =(CONFIG_SPL_STACK)
//#else
ldr r0, =(CONFIG_SYS_INIT_SP_ADDR)
//#endif
bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
mov sp, r0
bl board_init_f_alloc_reserve /* 申请struct global_data结构,其实就是在栈上分配而已 */
mov sp, r0
/* set up gd here, outside any C code */
mov r9, r0
bl board_init_f_init_reserve /* 初始化struct global_data,其实就是把struct global_data清零 */
mov r0, #0
bl board_init_f /* 初始化环境 */
//#if ! defined(CONFIG_SPL_BUILD)
/*
* Set up intermediate environment (new sp and gd) and call
* relocate_code(addr_moni). Trick here is that we'll return
* 'here' but relocated.
*/
ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
mov sp, r0
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
adr lr, here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0 /* lr中现在存储的是重定位之后的here地址 */
//#if defined(CONFIG_CPU_V7M)
// orr lr, #1 /* As required by Thumb-only */
//#endif
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code /* 重定位代码,并返回到重定位之后的here标签处 */
here:
/*
* now relocate vectors
*/
/* 重定位向量表 */
bl relocate_vectors
/* Set up final (full) environment */
/* 没有什么实际操作,函数内直接返回 */
bl c_runtime_cpu_setup /* we still call old routine here */
//#endif
//#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
//# ifdef CONFIG_SPL_BUILD
// /* Use a DRAM stack for the rest of SPL, if requested */
// bl spl_relocate_stack_gd
// cmp r0, #0
// movne sp, r0
// movne r9, r0
//# endif
/* 清零BSS */
ldr r0, =__bss_start /* this is auto-relocated! */
//#ifdef CONFIG_USE_ARCH_MEMSET
ldr r3, =__bss_end /* this is auto-relocated! */
mov r1, #0x00000000 /* prepare zero to clear BSS */
subs r2, r3, r0 /* r2 = memset len */
bl memset
//#else
// ldr r1, =__bss_end /* this is auto-relocated! */
// mov r2, #0x00000000 /* prepare zero to clear BSS */
//clbss_l:cmp r0, r1 /* while not at end of BSS */
// strlo r2, [r0] /* clear 32-bit BSS word */
// addlo r0, r0, #4 /* move to next */
// blo clbss_l
//#endif
//#if ! defined(CONFIG_SPL_BUILD)
bl coloured_LED_init /* board_f.c中定义为__weak类型的函数,所以什么都没有做 */
bl red_led_on
//#endif
/* call board_init_r(gd_t *id, ulong dest_addr) */
mov r0, r9 /* gd_t */
ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
/* call board_init_r */
//#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
// ldr lr, =board_init_r /* this is auto-relocated! */
// bx lr
//#else
ldr pc, =board_init_r /* this is auto-relocated! */ /* 一去不复返 */
//#endif
/* we should not return here. */
//#endif
ENDPROC(_main)
注:在上述代码中,不会执行的代码已使用'//'注释掉。