记录一下代码启动的过程:
研究具体代码之前,先了解其中的几个概念
概念一,gd结构体 global_data
为什么要有gd结构体及其作用。
概念二,u-boot代码的分段
主要是分为两段,前段和后段,这个对具体的代码行为会有不同的影响。
对于stm32来说,程序镜像都会存放在起始地址为0x08000000
的flash中,其中地址0x08000000
存放的是sp指针指向的内存值,0x08000004
和之后的一段内存存放的中断向量表,对于Cortex-M7内核来说,中断一共支持256个。
在源码 arch\arm\lib\vectors_m.S
中有相关的程序设置。
.section .vectors
ENTRY(_start)
.long CONFIG_SYS_INIT_SP_ADDR @ 0 - Reset stack pointer
.long reset @ 1 - Reset
.long __invalid_entry @ 2 - NMI
.long __hard_fault_entry @ 3 - HardFault
.long __mm_fault_entry @ 4 - MemManage
.long __bus_fault_entry @ 5 - BusFault
.long __usage_fault_entry @ 6 - UsageFault
.long __invalid_entry @ 7 - Reserved
.long __invalid_entry @ 8 - Reserved
.long __invalid_entry @ 9 - Reserved
.long __invalid_entry @ 10 - Reserved
.long __invalid_entry @ 11 - SVCall
.long __invalid_entry @ 12 - Debug Monitor
.long __invalid_entry @ 13 - Reserved
.long __invalid_entry @ 14 - PendSV
.long __invalid_entry @ 15 - SysTick
.rept 255 - 16
.long __invalid_entry @ 16..255 - External Interrupts
.endr
代码开头的 .section .vectors
表明了这一段程序位于 .vectors
段,在链接脚本中,该段被放在程序镜像的初始位置,上电复位的时候会先初始化sp,产生复位中断,执行复位中断函数reset
,函数代码在文件 arm\cpu\armv7m\start.S
中
.globl reset
.type reset, %function
reset:
W(b) _main
连接脚本中 start.S 中的数据段在向量段之后,可以看出复位中断函数比较简单,直接跳转到了_main 函数, _main 函数做了什么事情呢?
_main 函数在文件 arch\arm\lib\crt0.S
中定义,这里做了整个u-boot的初始化工作,下面重点研究该部分。
#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
/ * 前面代码对sp指针做8字节对齐操作* /
bl board_init_f_alloc_reserve
mov sp, r0
/* set up gd here, outside any C code */