【STM32芯片启动流程】——结合具体启动文件和hex文件分析
一、前言
最近想把MCU相关的知识梳理一遍,希望加深自己对相关知识的理解,同时也作为备忘录提醒自己。首先是STM32的启动过程,理解这个过程是学习IAP和OTA功能以及深入stm32内核的基础。
二、总体流程介绍
- 由boot引脚(boot0,boot1)选择启动模式;
- 给SP、PC指针赋值;
- 进入复位中断程序;
- 进入main函数。
三、各个过程深入分析
1. 由boot引脚选择启动模式
stm32复位(上电复位、硬件复位、软件复位),会将复位后的起始地址和中断向量表重映射到其他地址,具体映射到哪个地址由boot0和boot1决定。具体映射关系如下图所示。
启动模式对应映射地址
其中最常用的启动模式就是映射到内部FLASH启动,这也是接下来重点介绍的模式。
映射到内部SRAM启动的使用场景比较少,代码在SRAM的执行速度较快,可运用在一些调试需频繁更新代码的场合。
映射到系统存储器一般是用于bootloader引导程序升级时使用,在程序本地升级和OTA升级时都会用。
2. 给SP、PC指针赋值
选择内部FLASH启动后,程序会将栈指针SP指向0x08000000,这个地址保存的是__initial_sp的地址,也就是程序栈顶地址,还会将程序计数器指针指向0x08000004,这个地址保存的是Reset_Handler的地址,这里结合具体的启动文件,map文件和hex文件来证实这一点。
启动文件的中断向量表
map文件和hex文件对比
这里从map文件中选取__initial_sp和Reset_Handler的地址与hex文件中最开始执行的指令比较,发现两者相等,即证明了程序的执行确实如上所述。这里有两个需要注意的点,stm32是小端模式,因此hex文件中的指令是按照字节的高位在地址高位,字节的低位在地址低位的规则。Reset_Handler的地址最后一位为啥是1,stm32的指令不都是16位和32位的嘛,其实这里涉及到指令集的问题,ARM cortexM3执行的是Thumb-2指令集,同时兼容16位的ARM指令和32位的Thumb的指令,为了区分两个指令集,规定指令最低位为1就是Thumb指令,为0就是ARM指令。
初始化SP、PC指针的示意图
3. 进入复位中断程序
上一步中PC指针指向了Reset_Handler函数,这也是程序复位后执行的第一条指令。
可以看到在Reset_Handler函数里主要执行了 SystemInit 和 __main 这两个函数,其中SystemInit函数是库函数,它的主要作用是初始化系统时钟(通过调用SetSysClock)。
__main 函数是标准的C库函数,当编译器发现了主程序中有main函数,就会自动创建__main函数。它的主要作用是初始化RW段和ZI段(通过调用__scatterload),初始化堆栈以及跳转到主程序的main函数(通过调用__rt_entry)。
4. 进入main函数
执行main函数中的while死循环,当中断到来时从中断向量表中找到对应的中断服务函数并执行。
#通信硬件知识分享#