STM32 启动流程

我用最容易理解 的方式,把 STM32 从上电 → 运行 main () 的全过程讲清楚,Cortex‑M 内核通用(STM32F1/F4/H7/L4 全都一样)。


一、一句话总结启动流程

上电 → 从 Flash 读取栈顶地址 → 加载复位中断函数地址 → 跳转到复位函数 → 初始化硬件 → 跳转到 main () → 死循环


二、详细 7 步启动流程(必须掌握)

第 1 步:上电 / 复位

  • 电源接通,或复位键按下
  • CPU 进入复位状态

第 2 步:从 0x08000000 读取 栈顶地址 (SP)

  • STM32 启动时,强制从 Flash 起始地址 0x0800_0000 取第一个字
  • 这个字是 栈顶指针(Stack Pointer)
  • 作用:给程序运行准备堆栈空间

第 3 步:读取 复位中断服务函数地址

  • Flash 第 2 个地址:0x0800_0004
  • 这里存放的是 复位函数 Reset_Handler 的入口地址

**如上三步都是CPU 硬件行为,和任何代码、startup.s 无关,**Cortex‑M 内核硬件强制做两件事:

  1. 从 0x0800 0000 读取 4 字节 → 赋值给 SP 栈指针
  2. 从 0x0800 0004 读取 4 字节 → 赋值给 PC 程序计数器

第 4 步:跳转到 Reset_Handler 复位函数

这是程序真正执行的第一行代码,由启动文件(startup_stm32xx.s)提供。

第 5 步:初始化数据段(.data)

  • 将 初始化变量 从 Flash 复制到 RAM
  • 例如:int a = 10;

第 6 步:清零未初始化数据段(.bss)

  • 把 int b; 这类未赋值变量全部清 0
  • 防止随机值导致程序异常

第 7 步:跳转到 C 语言的 main () 函数

复制代码
main();

三、启动文件(startup_stm32xx.s)到底干了什么?

它是汇编文件,是 MCU 上电后第一个执行的代码。

主要做 4 件事:

  1. 设置栈顶 SP
  2. 设置中断向量表(复位、异常、中断入口)
  3. 初始化 RAM 数据
  4. 调用 main ()

四、最关键:中断向量表(启动核心)

Flash 开头固定放中断向量表:

复制代码
0x08000000:   栈顶地址      (第一个指令)
0x08000004:   复位函数地址  (第二个指令)
0x08000008:   硬fault地址
0x0800000C:   存储器管理fault
...

复位函数地址 = 程序真正的入口


五、超简洁流程图(秒懂)

复制代码
上电
  ↓
读栈顶地址(SP)
  ↓
读复位函数地址
  ↓
执行 Reset_Handler
  ↓
初始化 .data 和 .bss
  ↓
进入 main()
  ↓
while(1) 死循环

六、最核心的 3 个知识点(面试必考)

  1. STM32 程序入口不是 main (),而是 Reset_Handler ()
  2. 中断向量表放在 Flash 起始位置
  3. 启动文件负责初始化堆栈和 RAM,再跳转到 main

七、一句话终极总结

STM32 上电先找栈,再找复位函数,初始化 RAM 后才进入 main ()。

**问题:**启动文件中的Reset_Handler函数具体做了哪些初始化操作?

Reset_Handler 一共只做 5 件核心初始化事

这 5 件事做完,才会跳去 main()。


1. 初始化栈指针(硬件自动完成,但属于复位流程)

  • 从 0x08000000 取出栈顶地址
  • 赋值给 SP(栈指针)
  • 让程序有栈可用,不崩溃

2. 复制 .data 段(初始化全局变量)

作用:把已经赋初值的全局变量 / 静态变量 从 Flash 搬到 RAM。

例如:

复制代码
int a = 100;

这些数据存在 Flash,运行时必须放 RAM。


3. 清零 .bss 段(未初始化全局变量)

作用:把未赋值的全局变量 全部设为 0。

例如:

复制代码
int b;

如果不清零,值是随机乱码,程序会飞。


4. 调用 SystemInit(系统核心初始化)

这是 ST 官方提供的 C 函数,做:

  • 打开外部时钟 / 配置 PLL
  • 设置系统主频(如 72MHz、108MHz、200MHz)
  • 关闭看门狗
  • 配置 Flash 等待周期
  • 配置中断分组基础

一句话:让系统从默认低速 → 跑到最高性能。


5. 调用 C 库初始化(__libc_init_array)

作用:

  • 初始化 C++ 全局构造函数
  • 初始化标准库
  • 初始化浮点运算单元(如果有)

普通 C 项目也会执行,保证 C 环境完整。


最后一步:跳转到 main ()

复制代码
bl main

如果 main 退出,就进死循环:

复制代码
LoopForever:
  b LoopForever

终极极简总结(背这个)

Reset_Handler 只做 5 件事:

  1. 设置栈指针 SP
  2. 拷贝 .data 段(初始化全局变量)
  3. 清零 .bss 段(未初始化变量)
  4. 执行 SystemInit(时钟 / 系统配置)
  5. 初始化 C 库环境
  6. 进入 main ()

一句话面试标准答案

Reset_Handler 是上电后第一个执行的函数,负责初始化堆栈、搬运数据、配置系统时钟,最后跳转到 main 函数运行用户程序。

相关推荐
深圳市恒锐丰科技杨生13 分钟前
# HT3310|集成锂电池充电 + 三档电机驱动控制芯片 SOT23‑6
嵌入式硬件·硬件工程
北京盛世宏博22 分钟前
异地机房采集踩坑笔记:以太网温湿度记录仪跨网段通信调试实战
开发语言·笔记·单片机·php·传感器·温湿度
FakeOccupational1 小时前
【电路笔记 STM32】Cortex-M7 UART DMA模式(DMA&空闲中断&普通模式+DMA&半满/全满中断&循环模式)
笔记·stm32·嵌入式硬件
sramdram1 小时前
国产32位CH32V系列RISC-V单片机
单片机·嵌入式硬件·risc-v·国产32位单片机·risc-v单片机
万物智能信息科技2 小时前
人体感应芯片PIR模块驱动开发—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
驱动开发·嵌入式硬件·华为·开源·harmonyos
youcans_2 小时前
【STM32C5教程】(4)GPIO 外部中断实验
stm32·单片机·嵌入式硬件·mcu·stm32c5
深圳市恒锐丰科技杨生3 小时前
# CSM9118|芯晞微电 7.5V/1.5A 单通道 H 桥电机 / 线圈驱动
嵌入式硬件·硬件工程
硅基手札3 小时前
【I2C 技术系列 09】I2C 传输模式:轮询 / 中断 / DMA
驱动开发·stm32·单片机·嵌入式硬件·mcu·计算机外设
Zw-awa4 小时前
让机器回答“我在哪”:激光雷达与 SLAM
stm32
启友玩AI4 小时前
微安级唤醒、毫安级识别:基于 CI3422 的 AI 眼镜语音交互开发实战
c语言·人工智能·科技·嵌入式硬件·ai·ar·语音识别