STM32 启动流程解析:上电后第一条代码是如何执行的
一、前言绝大多数 STM32 开发者日常基于标准库、HAL 库开发业务代码从main()函数开始编写久而久之形成一个错误认知单片机上电直接执行main函数。实际上main只是整套上电初始化链路的最终业务入口芯片从上电上电电压爬升、硬件复位、BOOT 引脚采样到汇编底层初始化、内存段搬运、时钟配置中间一整套严谨的固化流程全部执行完毕后才会跳转到 C 语言主函数。平时遇到的上电不运行、全局变量上电数值随机、IAP 程序跳转死机、偶尔启动异常、中断跳转失效等问题根源几乎都是对底层启动机制不了解。本文按照硬件→内核→汇编启动文件→内存映射→代码落地→故障排查线性逻辑梳理剔除重复内容附带流程图、核心汇编源码、内存分区详解全部为工程可落地干货。二、前置基础STM32 三块启动存储介质STM32 内核上电第一步是根据引脚电平选择程序运行载体芯片内部三块物理存储区域功能完全不同Main Flash 主闪存掉电非易失存储用户编译生成的固件默认烧录于此产品正式运行的标准启动区域地址基地址0x08000000。System Memory 系统存储区ST 出厂固化的 ISP Bootloader用户无法擦写修改仅用于串口 / USB DFU 下载程序也就是常说的 “下载模式”。SRAM 静态内存掉电数据丢失正常运行存放变量、堆栈、堆内存仅用于调试、RAM 内运行代码、IAP 调试基地址0x20000000。三、硬件上电第一动作BOOT 引脚选择启动模式3.1 BOOT 引脚采样规则电源上电、复位电平稳定后芯片硬件自动锁存BOOT0、BOOT1引脚电平决定程序从哪一块存储器启动三种模式唯一对应关系表格BOOT0BOOT1启动存储区域使用场景低电平任意Main Flash产品正常运行常规接法 BOOT0 下拉 GND高电平低电平System Memory串口 ISP 下载固件高电平高电平SRAM代码调试、RAM 运行程序3.2 硬件上电完整时序纯硬件行为无软件参与电源电压缓慢爬升达到芯片最小工作电压阈值内部上电复位电路生效CPU 强制保持复位状态硬件锁存 BOOT0/BOOT1 引脚电平确定启动基地址内部 RC 或外部晶振起振等待时钟稳定复位信号释放Cortex-M 内核正式开始取指执行指令。关键点上电前期所有动作都是硬件自动完成还没有任何一行用户代码被执行。四、Cortex-M 内核强制启动规则真正第一条指令在哪里4.1 内核固定取址机制Cortex-M3/M4/M0 内核复位释放后会强制从选定启动区域的固定偏移地址读取两个关键值以最常用 Flash 启动为例地址0x0800 0000存放主堆栈指针 MSP 初始值地址0x0800 0004存放复位中断服务函数 Reset_Handler 入口地址CPU 先把 0 地址数据载入 MSP 寄存器完成堆栈初始化再把 0x04 地址赋值给程序计数器 PC直接跳转到复位中断函数。4.2 核心结论上电执行的第一条有效代码是启动文件中的汇编指令main()函数是汇编完成所有底层初始化后间接跳转进入中断向量表前两项固定为栈顶地址 复位入口由编译器自动填充。五、编译后程序内存分段原理启动文件搬运的底层依据在讲解启动文件汇编逻辑前必须理解固件编译后的四大内存段整个启动文件一大半工作都是在处理这些段的拷贝与清零Code 代码段存放所有函数指令、常量字符串const修饰数据固化在 Flash 中只读不可改写。Data 数据段存放已初始化全局变量例int g_val 100;。编译时存储在 Flash上电必须拷贝到可读写的 SRAM 中才能修改。BSS 零初始化段存放未初始化全局变量、static 静态局部变量例int g_buf[100];。不占用 Flash 空间上电在 SRAM 中将整片内存清零这就是全局变量默认值为 0 的根本原因。Heap Stack 堆与栈全部位于 SRAM栈用于函数调用、局部变量、中断现场压栈堆用于malloc动态内存申请大小在启动文件中宏定义配置。六、启动文件 startup.s 完整执行流程 核心汇编源码启动文件如startup_stm32f10x_md.s是整个启动流程的核心载体纯汇编编写优先级高于所有 C 代码。复位后进入Reset_Handler按固定 6 步完成初始化下面附带精简可看懂的汇编代码。6.1 Reset_Handler 完整执行步骤步骤 1初始化主堆栈指针 MSP向量表首地址取出栈顶地址写入 MSPC 语言函数调用、中断嵌套、局部变量全部依赖堆栈堆栈未初始化 CPU 无法运行 C 代码。 启动文件头部宏定义堆栈大小示例asmStack_Size EQU 0x00000400 ; 1KB栈空间 Heap_Size EQU 0x00000200 ; 512B堆空间步骤 2Data 段从 Flash 拷贝到 SRAM将已初始化全局变量从只读 Flash 搬运到可读写内存对应汇编拷贝逻辑汇编代码Reset_Handler PROC ; 1. Data段拷贝Flash - SRAM LDR R0, _sidata ; Flash中data段起始 LDR R1, _sdata ; SRAM中data段起始 LDR R2, _edata ; SRAM中data段结束 Copy_Data_Loop CMP R1, R2 LDRCC R3, [R0], #4 STRCC R3, [R1], #4 BCC Copy_Data_Loop步骤 3BSS 段内存清零对未初始化全局变量所在内存区域全部置 0避免上电随机脏数据汇编代码; 2. BSS段清零 LDR R1, _sbss LDR R2, _ebss MOV R3, #0 Zero_BSS_Loop CMP R1, R2 STRCC R3, [R1], #4 BCC Zero_BSS_Loop步骤 4调用 SystemInit () 系统初始化函数汇编跳转进入 C 语言SystemInit函数完成三件关键工作配置系统时钟源HSI/HSE/PLL 倍频设置主频配置 AHB、APB 总线分频系数给外设分配时钟重定向中断向量表基地址SCB-VTOR。工程干货做 IAP 固件升级时二级 APP 必须重新执行向量表偏移否则全部中断失效。步骤 5跳转进入 main 函数底层全部初始化完成后使用汇编无条件跳转指令进入用户 C 语言入口汇编代码; 3. 调用系统时钟初始化 BL SystemInit ; 跳转到主函数正式交付业务代码 B main ENDP6.2 整套启动线性流程图可直接画成框图plaintext硬件上电 → 电源稳定 → 复位锁定 → BOOT引脚电平采样 → 释放复位 → 内核读取MSP栈地址与复位入口地址 → 进入Reset_Handler汇编函数 → Data段Flash拷贝至SRAM → BSS段内存清零 → SystemInit时钟向量表配置 → 汇编跳转main() → HAL库初始化 → 外设初始化 → 主循环运行七、启动流程对应工程高频故障排查把理论对应到实际问题快速定位启动异常原因程序可下载但上电不运行BOOT0 引脚未下拉芯片停留在 ISP 下载模式复位电路 RC 参数不合理长期处于复位状态。全局变量上电数值随机、数组数据错乱启动文件被错误修改Data 段拷贝或 BSS 段清零逻辑被删除编译器分散加载文件.sct 配置异常。IAP 跳转 APP 后死机、中断不触发跳转前未关闭中断、未重新设置 MSP 栈指针、APP 内部未重新偏移中断向量表。上电偶尔启动、低温启动失败外部晶振负载电容不匹配起振时间过长电源上电斜率太慢复位释放过早。外部中断、定时器中断偶尔进不去SystemInit 中向量表偏移未配置或跳转后向量表地址冲突。八、常见认知误区纠正 工程启动优化技巧8.1 五大经典误区误区main 是上电第一行代码正解main 是初始化完成后的入口真正首行为复位汇编指令。误区全局变量自动归零是 C 语言语法特性正解完全由启动文件 BSS 段汇编清零实现删除清零代码变量全是随机值。误区BOOT 引脚只有下载时有用正解启动模式由它唯一决定是启动故障首要排查点。误区变量初始化由编译器完成正解编译器仅分配地址映射上电动态搬运靠启动文件执行。误区SRAM 启动模式产品可以随便用正解掉电丢失仅用于调试量产必须 Flash 启动。8.2 上电启动速度优化实操方案针对需要快速开机的产品基于启动流程做轻量化优化优先使用内部高速 HSI 时钟规避外部晶振起振延时在SystemInit中关闭所有未使用外设时钟SPI、I2C、DAC 等减少超大全局数组、结构体降低 Data 段拷贝耗时精简启动文件中未使用的中断向量减小查表耗时主函数开头减少阻塞式延时外设采用延后初始化。九、全文总结STM32 上电启动分为三层硬件层 BOOT 模式选择→内核层固定地址取指→汇编层内存与系统初始化上电第一条执行代码为启动文件Reset_Handler汇编指令main只是业务层入口Data 段拷贝、BSS 段清零、堆栈初始化、时钟配置、向量表重定向是 C 语言程序运行的五大底层必要条件理解这套启动机制不仅可以解决各类启动死机、变量异常、IAP 升级 BUG更能吃透 Flash 与 SRAM 的程序映射关系是嵌入式底层能力、面试考核、产品稳定量产的核心知识点。

相关新闻

一个API调遍所有真大模型

一个API调遍所有真大模型

前言:被中转站"挂羊头卖狗肉"坑过之后,我对模型接入的底线就一条——调的是什么模型,必须清清楚楚、有据可查。 被坑过之后的执念 上次说到我们被中转站骗了——付Claude的钱,跑的是GLM。此后我对多模型接入产生了一种…

2026/10/20 16:44:30 阅读更多 →
FfDL部署常见问题与解决方案:从安装到训练的 troubleshooting 手册

FfDL部署常见问题与解决方案:从安装到训练的 troubleshooting 手册

FfDL部署常见问题与解决方案:从安装到训练的 troubleshooting 手册 【免费下载链接】FfDL Fabric for Deep Learning (FfDL, pronounced fiddle) is a Deep Learning Platform offering TensorFlow, Caffe, PyTorch etc. as a Service on Kubernetes 项目地址: ht…

2026/10/17 14:41:32 阅读更多 →
TVBoxOSC:如何将闲置电视盒子变成家庭Wi-Fi热点中心

TVBoxOSC:如何将闲置电视盒子变成家庭Wi-Fi热点中心

TVBoxOSC:如何将闲置电视盒子变成家庭Wi-Fi热点中心 【免费下载链接】TVBoxOSC TVBoxOSC - 一个基于第三方项目的代码库,用于电视盒子的控制和管理。 项目地址: https://gitcode.com/GitHub_Trending/tv/TVBoxOSC 还在为家中Wi-Fi信号死角而烦恼吗…

2026/10/19 23:59:54 阅读更多 →

最新新闻

5分钟粒度时间序列预测:ARIMA全流程实战与坑点解析

5分钟粒度时间序列预测:ARIMA全流程实战与坑点解析

数据准备:5分钟数据的“脏活累活” 2.1 采集与落库,先解决有没有的问题 2.2 缺失值处理,别让“空洞”骗了模型 2.3 异常值甄别,业务噪声与真实波动的边界 2.4 重采样与对齐,把时间轴捋直了 数据是一切时序建模的地…

2026/10/20 16:43:46 阅读更多 →
降AIGC软件横评:9类工具原理、避坑与实操流程

降AIGC软件横评:9类工具原理、避坑与实操流程

最近这段时间,被问得最多的问题就是“到底有没有靠谱的降AIGC软件”。经常是头像一换,那边甩过一张截图,问“这种标红要怎么办”。尤其专科生群体,课程报告、实训总结、毕业设计说明一摊开,全是AI生成常见句式&#xf…

2026/10/20 16:43:46 阅读更多 →
Apache Pulsar 2.9.1 部署实战:从解压到集群调优的完整指南

Apache Pulsar 2.9.1 部署实战:从解压到集群调优的完整指南

简介:Apache Pulsar 2.9.1 的二进制发行包,面向需要搭建高吞吐消息队列与实时流处理管道的后端开发、架构师和云原生运维人员,解决分布式消息中间件选型与自建集群时的环境前置问题。压缩包约 321.53MB,为 tar.gz 格式&#xff0c…

2026/10/20 16:43:46 阅读更多 →
AI Agent任务规划、状态管理与长任务恢复:从原理到最小实现

AI Agent任务规划、状态管理与长任务恢复:从原理到最小实现

1. 从“能聊天”到“能干活”:任务规划到底在解决什么问题 很多人第一次接触 AI Agent,脑子里想的还是“更聪明的聊天机器人”。但真正做过 Agent 项目的人都知道,聊天只是最表层的能力,真正决定一个 Agent 能不能落地干活的&…

2026/10/20 16:43:46 阅读更多 →
Python AI编程入门指南:机器学习、深度学习、NLP与强化学习实战

Python AI编程入门指南:机器学习、深度学习、NLP与强化学习实战

1. 从零到一:为什么我建议你用Python切入AI编程很多人第一次接触AI编程,脑子里冒出来的第一个问题不是“怎么学”,而是“从哪开始”。我见过太多人抱着厚厚的数学书啃了三个月,结果连一行能跑的代码都没写出来,最后热情…

2026/10/20 16:43:46 阅读更多 →
医学图像处理代码实战:从DICOM读取到三维重建与分割

医学图像处理代码实战:从DICOM读取到三维重建与分割

前一阵有个刚转行做医学影像算法的朋友来找我,说他从某医院那边拿到了一批脱敏后的CT数据,文件夹里装着一堆后缀为 .dcm 的文件。他第一反应是像处理普通照片一样用 OpenCV 直接读,结果 cv2.imread 返回一大片乱码。这个场景我太熟悉了&#…

2026/10/20 16:42:44 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →