Cortex-M启动全流程解析:从复位向量到main()的完整旅程
上电流程
基于地址从低到高(从上到下)的内存分布模型,Cortex-M MCU 的启动过程可以分为三个关键阶段:
- 硬件自动加载阶段、
- 软件环境准备阶段、
- 跳转进入用户代码阶段。
第一阶段:硬件自动加载(物理层触发)
当 MCU 上电,复位引脚(Reset Pin)释放的一瞬间,CPU 处于管态(内核态),由于此时还没有时钟配置,它会以内部低速振荡器频率执行以下动作:
-
获取栈顶地址(MSP 初值):
- 位置:Flash 的第 0-3 字节(
0x0800 0000)。 - 动作:CPU 自动读取这个地址的值,直接加载进 SP (Stack Pointer) 寄存器。
- 对应模型:这个值通常指向 RAM 的最底部(最高地址)。
- 意义:即使一行代码还没跑,CPU 已经为后续函数调用准备好了“垃圾桶”(栈)。
- 位置:Flash 的第 0-3 字节(
-
获取复位向量(Reset Vector):
- 位置:Flash 的第 4-7 字节(
0x0800 0004)。 - 动作:CPU 读取这个地址的值(即
Reset_Handler函数的入口地址),加载进 PC (Program Counter) 寄存器。 - 对应模型:PC 现在指向了 Flash 中的
.text段。
- 位置:Flash 的第 4-7 字节(
第二阶段:软件环境准备(由 Reset_Handler 执行)
此时 PC 指针开始移动,开始执行 startup_xxxx.s 中的汇编指令。
-
系统初始化(SystemInit):
- 调用
SystemInit函数。 - 动作:配置时钟树(例如将 8MHz 晶振倍频至 168MHz)。
- 意义:让后续的内存搬运工作跑得更快。
- 调用
-
数据段搬运(Data Copy) —— 最关键的跨区动作:
- 源头:Flash 中的
.data 段 (初始值备份)。 - 目的地:RAM 中的
.data 段 (已初始化变量)。 - 动作:通过一个简单的循环,将 Flash 中的数据逐字拷贝到 RAM 中。
- 对应模型:实现了我们在图中画的——将“断电不丢失的初始值”激活为“运行中可修改的变量”。
- 源头:Flash 中的
-
BSS 段清零(BSS Zeroing):
- 位置:RAM 中的
.bss 段。 - 动作:读取
.bss段的起始地址和结束地址,将这块 RAM 区域全部填充为0。 - 对应模型:这保证了你在 C 语言里写的
static int my_value;即使不赋初值,启动后也一定是 0。
- 位置:RAM 中的
第三阶段:进入 C 语言世界
此时内存模型已经完全“激活”,Flash 里有指令,RAM 里有变量。
- 跳转到
main:- 执行汇编指令
bl main。 - 堆栈变化:进入
main后,SP指针开始从 RAM 的最高地址 向 低地址 移动(向下增长),用于存放main函数的局部变量。 - 堆空间:如果
main中调用了malloc,堆管理程序会从.bss结束的地址 向 高地址 移动(向上增长)。
- 执行汇编指令
结合模型的全景总结
| 启动步骤 | 涉及的段(Section) | 发生的物理区域 | 结果 |
|---|---|---|---|
| 1. 取 SP | Vector Table (Index 0) | Flash -> SP 寄存器 | 栈指针指向 RAM 顶部 (高地址) |
| 2. 取 PC | Vector Table (Index 1) | Flash -> PC 寄存器 | 程序开始从 Flash 运行 |
| 3. 时钟配置 | .text (SystemInit) | Flash | CPU 提速 |
| 4. 搬运 Data | .data (Load Address) | Flash 拷贝到 RAM | 全局变量 int a = 10; 准备就绪 |
| 5. 清零 BSS | .bss | RAM | 全局变量 int b = 0; 准备就绪 |
| 6. 进入 main | .text (main) | Flash | 用户代码正式开始执行 |
为什么这个模型对 RTOS 适配很重要?
当你增加一个 RTOS (如 FreeRTOS) 时,RTOS 的初始化逻辑会在 main 之后发生:
- 任务创建:RTOS 会在 Heap (堆) 上为每个任务切出一块块空间。
- 任务切换:RTOS 会强行修改
SP寄存器,让它不再指向 RAM 最底部的“系统栈”,而是指向 Heap 内部某块区域伪造的“任务栈”。
理解了这个启动过程和分布模型,你就能清楚地知道:如果程序还没跑进 main 就挂了,那一定是栈设置错了(向量表第一项无效)或者 Flash 拷贝到 RAM 的逻辑出错了。
浙公网安备 33010602011771号