【STM32芯片启动流程】——结合具体启动文件和hex文件分析

一、前言

最近想把MCU相关的知识梳理一遍,希望加深自己对相关知识的理解,同时也作为备忘录提醒自己。首先是STM32的启动过程,理解这个过程是学习IAP和OTA功能以及深入stm32内核的基础。

二、总体流程介绍

  1. 由boot引脚(boot0,boot1)选择启动模式;
  2. 给SP、PC指针赋值;
  3. 进入复位中断程序;
  4. 进入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死循环,当中断到来时从中断向量表中找到对应的中断服务函数并执行。

#通信硬件知识分享#
全部评论

相关推荐

不愿透露姓名的神秘牛友
今天 16:21
已编辑
嘉里敦 研究员 0 其他
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-28 10:14
已编辑
滴滴 后端 go 25k × 15 本科985
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务