8.1 start.S 修改
发现启动初始化的过程需要屏蔽看门狗和中断。
如果看门狗不禁用,会导致系统反复重启,因此需要在初始化的时候禁用看门狗;中断屏蔽保证启动过程中不出现异常现象
时钟不需要初始化,直接由外部晶振提供初始化,在第二阶段 C 部分再进行初始化。
代码主要在 start.S 中进行修改,主要是时钟代码的删除:

这一块代码删除掉。
8.2 _main --- C环境
执行完一系列初始化后,开始跳转到 _main 中执行进行C环境初始化和第二阶段的代码
crt0.S (arch\arm\lib)
_main 执行过程如下:
- 建立调用 board_init_f() 的环境,此环境只是提供一个用来保存全局变量 GD 结构体的栈和空间,栈和空间都位于 SRAM 中。在调用board_init_f()前,GD 需要被清 0。
- 调用 board_init_f(),该函数从系统RAM(DRAM,DDR ...)准备将要执行的硬件。由于系统RAM可能还不可用,因此board_init_f()必须使用当前的GD来存储必须传递到后面阶段的任何数据。 这些数据包括重定位目标,未来堆栈和未来的GD位置。
- 设置中间环境,其中堆栈和GD是由系统RAM中的board_init_f()分配的,但BSS和初始化的 non-const 数据仍然不可用。
- 对于U-Boot本身(不是SPL),调用relocate_code()。 该函数将U-Boot从其当前位置重定位到由board_init_f()计算的重定位地址。
- 设置调用board_init_r()的最终环境。 这个环境具有BSS(初始化为0),初始化的 non-const 数据(初始化为其预期值),和系统RAM中的堆栈(用于SPL将堆栈和GD移入RAM是可选的 - 参见CONFIG_SPL_STACK_R)。 GD保留由board_init_f()设置的值。
- 对于U-Boot(不是SPL),有些CPU在内存方面还有一些工作要做,所以调用c_runtime_cpu_setup。
- 最后 跳到 board_init_r() 去执行
8.2.1 设置栈并初始化GD 和全局数据
1 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 2 ldr sp, =(CONFIG_SPL_STACK) 3 #else 4 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /** CONFIG_SYS_INIT_SP_ADDR = 0x3000 0f40 */ 5 #endif /** end defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) */ 6 #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ 7 mov r3, sp 8 bic r3, r3, #7 9 mov sp, r3 10 #else 11 bic sp, sp, #7 /* 8 字节对齐,将 sp 的低三位清零,还是 0x3000 0f40 */ 12 #endif /** end defined(CONFIG_CPU_V7M) */ 13 mov r0, sp 14 bl board_init_f_alloc_reserve /** 预留 GD 的空间 */ 15 mov sp, r0 16 /* set up gd here, outside any C code */ 17 mov r9, r0 18 bl board_init_f_init_reserve /** 对 GD 做了次初始化,栈指针不动 */ 19 20 mov r0, #0 21 bl board_init_f /** 进入 relocate 前的初始化 */
8.2.2 board_init_f_alloc_reserve
1 ulong board_init_f_alloc_reserve(ulong top) 2 { 3 /* Reserve early malloc arena */ 4 #if defined(CONFIG_SYS_MALLOC_F) 5 /** 从顶部向下分配一块 CONFIG_SYS_MALLOC_F_LEN 大小的空间给 early malloc 使用, 6 这块内存是用于在relocation前用于给malloc函数提供内存池 7 0x3000 0f40 - 0x400 = 0x3000 0b40*/ 8 top -= CONFIG_SYS_MALLOC_F_LEN; 9 #endif 10 /** 分配 sizeof(struct global_data) 大小的内存给 global_data 使用,向下 16byte 对齐 11 global_data 的长度会根据我们的配置变化长度,这里没办法计算分配后的地址所在 */ 12 top = rounddown(top-sizeof(struct global_data), 16); 13 14 return top; 15 }
8.2.4 board_init_f_init_reserve
1 void board_init_f_init_reserve(ulong base) 2 { 3 struct global_data *gd_ptr; 4 #ifndef _USE_MEMCPY 5 int *ptr; 6 #endif 7 8 /* 9 * clear GD entirely and set it up. 10 * Use gd_ptr, as gd may not be properly set yet. 11 */ 12 /** gd_ptr 地址等于当前栈所在的地址 */ 13 gd_ptr = (struct global_data *)base; 14 /* zero the area */ 15 #ifdef _USE_MEMCPY 16 /** 初始化 */ 17 memset(gd_ptr, '\0', sizeof(*gd)); 18 #else 19 for (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); ) 20 *ptr++ = 0; 21 #endif 22 /* set GD unless architecture did it already */ 23 #if !defined(CONFIG_ARM) 24 arch_setup_gd(gd_ptr); 25 #endif 26 /* next alloc will be higher by one GD plus 16-byte alignment */ 27 /** 分配空间,并向上 16 字节对齐,这里又指向了 0x3000 0b40 处 */ 28 base += roundup(sizeof(struct global_data), 16); 29 30 /* 31 * record early malloc arena start. 32 * Use gd as it is now properly set for all architectures. 33 */ 34 35 #if defined(CONFIG_SYS_MALLOC_F) 36 /* go down one 'early malloc arena' */ 37 gd->malloc_base = base; 38 /* next alloc will be higher by one 'early malloc arena' size, 39 base 重新回到 0x3000 0f40*/ 40 base += CONFIG_SYS_MALLOC_F_LEN; 41 #endif 42 }
8.2.5 global_data内存分布

