文章目录
- 固件起始地址存储了主栈指针和向量表内容
- 启动文件分析
- 程序启动流程
- Code,RO Data,RW Data, ZI Data
- 启动流程
- Regin$$Table
固件起始地址存储了主栈指针和向量表内容
《ARM Cortex-M3与Cortex-M4权威指南》中的4.8章节复位和复位流程中有下面这段的描述:
在复位后以及处理器开始执行程序前,Cortex-M处理器会从存储器中读出头两个字,如图4.30所示。向量表位于存储器的开头部分,它的头两个字为主栈指针(MSP)的初始值,以及代表复位处理起始地址的复位向量(参考本书图4.26和4.5.3节)。处理器读出这两个字后,就会将这些数值赋给MSP和程序计数器(PC)
当异常时间产生且被处理器内核接受后,响应的异常处理就会执行。要确定异常处理的起始地址,处理器利用了一种向量表机制。向量表为系统存储器内的字数据数组,每个元素都代表一个异常类型的起始地址,如图4.26所示。
《Cortex-M3处理器技术参考手册》中5.9复位章节中的表5-7显示了复位的行为:
基于上述描述我们可以知道固件的起始地址存储了主栈指针的初始值,后续存储了向量表的内容。
从上面的map文件中我们可以看出程序的栈顶地址就是0x200069b0,从下面的固件中我们可以看出起始地址存放的就是栈顶指针的值。
…
基于map文件找出后续程序地址对应的数据内容,和上面向量表对应的内容也完全一致
细心的你可以能已经发现了,这里固件中存储的向量表的地址和map文件中对应的函数地址不完全一致,差了1,这是因为向量表的LSB位必须置1以表示Thumb状态(Cortex-M处理器不支持ARM状态)
《ARM Cortex-M3与Cortex-M4权威指南》7.5章节:
启动代码使用的向量表还包含主栈指针(MSP)的初始值,这种设计是很有必要的,因为NMI等异常可能会紧接着复位产生,而此时还没有进行任何初始化操作。
启动文件分析
启动文件主要做了以下工作:
- 初始化栈指针 MSP= _initial_sp
- 初始化PC指针 PC=Reset_Handler
- 初始化中断向量表
- 配置系统时钟
- 调用C库函数__main初始化用户堆栈,从而最终调用main函数
复位函数是系统上电后第一个执行的程序。
程序启动流程
下面图片来自正点原子IAP教程章节
Code,RO Data,RW Data, ZI Data
Code : 代码段
RO Data : 只读数据段
RW Data : 读写数据段,定义的时候被初始化的变量
ZI Data:未初始化的数据段
启动流程
Regin$$Table
map文件中的Regin$$Table的位置如下:
对应固件中的地址位置的数据如下:
值 | 描述 |
---|---|
08030500 | RW Data在加载域中的起始位置 |
20000000 | RW Data复制到执行域中的起始位置 |
00000478 | 需要复制RW Data数据的长度 |
080257A | 分散加载复制函数的入口地址 |
080305E8 | RW Data在加载域中的结束位置 |
20000478 | ZI Data在执行域中的起始位置 |
00006538 | ZI Data数据段的大小 |
0802F73A | 分散加载ZI段初始化函数的入口地址 |