目录
说明:本文以正点原子的μVision FreeRTOS工程作为实例
1. 存储设备布局
STM32F407的存储设备布局如下图所示,此处使用了MCU内部的iROM & iRAM
2. 链接器脚本
2.1 链接器脚本生成
① 使用μVision IDE时,链接器脚本由IDE根据所选MCU型号自动生成
② 自动生成的链接器脚本在工程的Objects目录,文件名后缀为.sct
说明:MCU型号对链接器脚本最大的影响就体现在所用存储介质的地址与范围
2.2 链接器脚本分析
2.2.1 分散加载文件
① 分散加载文件(scatter file)用来指定ARM链接器在生成镜像时如何分配RO / RW / ZI等数据的存放地址
2.2.2 加载区 & 运行区
运行区:包含应用程序运行时的代码和数据,应用程序启动过程中,从每个加载区可创建一个或多个运行区
说明1:镜像中的所有代码和数据必须准确地指定到一个加载区和一个运行区
示例中的LR_IROM1是1个加载区,其中包含2个运行区(ER_IROM1和RW_IRAM1)
2.2.3 ER_IROM1运行区分析
部署在IROM最前端的为RO数据中的RESET section,这个section包含了MSP的初始值以及Reset_Handler(在异常向量表中),是Cortex-M3 MCU启动的起点
库函数__main中有InRoot$$Sections段,主要作用是将RW区复制到IRAM中,并且在RW区之后创建ZI区
2.2.4 RW_IRAM1运行区分析
3. 启动文件分析
3.1 MSP初始值
① __initial_sp为异常向量表的第1个成员,内容为MSP的初始值
② __initial_sp被链接在RW区,大小为1KB(0x00000400)
AREA STACK段的起始地址是栈的低地址端,__initial_sp是栈的高地址端。由于Cortex-M3默认使用满减栈,所以MSP初始值为__inital_sp,也就是高地址端
我们在Reset_Handler中添加LDR R0, =__initial_sp语句,查看MSP初始值,可见结果与预期相同
3.2 链接器内存堆
如之前的笔记分析,此处的内存堆是供编译器提供的malloc & free使用的,通过__heap_base & __heap_limit标号,可标识内存堆范围
3.3 异常向量表
说明:启动文件中提供了WEAK定义的中断Handler,用户可自定义Handler进行覆盖
3.4 Reset_Handler
Reset_Handler为Cortex-M3/4系列MCU启动的起点
Reset_Handler的主体先后调用SystemInit和__main函数,从而进入用户定义的main函数
SystemInit函数会设置内置Flash、PLL以及外置DDR(如果有的话),需要注意下该函数对异常向量表地址的重置,即将SCB->VTOR寄存器值设置为FLASH_BASE(0x08000000) | VECT_TAB_OFFSET(0x00000000),也就是IROM1的起始地址