首页/新闻资讯/正文详情

STM32F407 启动文件:从上电复位到 main()

发布时间:2026/9/26 7:26:53 来源:云帆数科 栏目:资讯中心
STM32F407 启动文件:从上电复位到 main()
平时编写 STM32 程序通常从main()开始。但芯片上电后需要先设置栈指针、找到程序入口、配置系统时钟并准备好 C 程序的运行环境才能执行main()。本文以STM32F407、Keil MDK 和标准外设库工程为例整理启动文件中的主要知识点。一、从上电到 main() 的完整过程在选择从内部 Flash 启动的情况下基本过程如下芯片上电或复位 ↓ CPU 通过启动地址映射读取向量表 ↓ 将向量表第一项加载到主栈指针 MSP ↓ 根据向量表第二项进入 Reset_Handler ↓ 调用 SystemInit()配置系统时钟等 ↓ 进入 C 运行库 __main准备 C 运行环境 ↓ 调用用户编写的 main()其中读取初始栈顶和复位入口是 CPU 复位硬件自动完成的。随后CPU 才开始执行Reset_Handler中的指令。二、CPU 为什么能找到启动代码启动文件经过汇编、链接后会和其他代码一起写入 Flash。CPU 运行时使用的是机器指令和数据源文件名只用于开发阶段。CPU 能找到启动代码是因为硬件与链接布局遵循同一个约定启动向量表的前两个 32 位数据分别保存初始栈顶和复位入口。假设程序从 Flash 起始地址0x08000000开始存放Flash 地址保存的内容0x08000000初始栈顶地址__initial_sp0x08000004复位入口Reset_Handler的地址后续地址其他异常和中断处理函数的地址每项占 4 字节因此第二项的地址比第一项多 4。STM32F407 从 Flash 启动时会把 Flash 映射到从0x00000000开始的启动地址空间。因此CPU 复位时读取0x00000000和0x00000004就能读到 Flash 中的这两项。地址映射不会把 Flash 内容复制一遍只是让同一块存储器可以通过另一个地址访问。一个具体例子假设编译后的内容如下地址仅用于说明存放位置内容含义0x080000000x20001000初始栈顶在 RAM 的0x200010000x080000040x08000201复位入口最低位 1 表示 Thumb 状态0x08000200启动代码的机器指令Reset_Handler的实际指令位置复位后CPU 自动完成读取第一项 → MSP 0x20001000 读取第二项 → 根据 0x08000201 设置执行状态 从 0x08000200 开始执行指令Cortex-M4 使用 Thumb 指令集因此入口地址值的最低位需要为 1。三、启动文件中的栈配置启动文件中常见以下代码Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN3 Stack_Mem SPACE Stack_Size __initial_sp这段代码描述了一块大小为 1 KB 的栈区域。写法含义EQU定义常量作用类似 C 的#defineStack_Size栈大小0x400 1024字节AREA STACK定义名为STACK的段NOINIT该区域不要求启动时初始化内容READWRITE该区域可读可写ALIGN3按2³ 8字节对齐SPACE Stack_Size在该段中保留指定字节数Stack_Mem栈区域起点的标号__initial_sp栈区域末尾的标号用作初始栈顶这些是汇编器和链接器使用的定义。链接器会根据工程配置为这块区域安排 RAM 地址。栈在 RAM 中是什么样的假设这 1 KB 栈从0x20000000开始高地址 0x20000400 ← __initial_sp初始 MSP 0x200003FF ← 栈区域最后一个字节 ... 0x20000000 ← Stack_Mem栈区域第一个字节 低地址实际保留的范围是0x20000000 0x200003FF初始栈指针指向这块区域上边界的下一个地址0x20000400。STM32F407 使用向低地址增长的栈入栈时栈指针减小出栈时栈指针增大。栈有什么用栈主要用于保存函数调用时需要保留的寄存器和返回信息。需要放入内存的局部变量。部分函数参数。中断发生时的 CPU 现场。局部变量和函数参数是否使用栈还取决于编译器。有些值可以直接保存在寄存器中。例如一次普通中断进入时CPU 的基本异常栈帧包含 8 个寄存器值共 32 字节R0、R1、R2、R3、R12、LR、PC、xPSR假设没有额外对齐填充和浮点上下文中断前MSP 0x20000400 保存 32 字节 MSP 0x20000400 - 0x20 0x200003E0 中断返回恢复现场后 MSP 0x20000400中断处理函数自身还可能继续使用栈因此一次中断的总栈开销可能超过 32 字节。栈空间不够会怎样如果函数调用层次较深、局部数组较大或者中断嵌套较多栈就可能超过预留范围覆盖其他 RAM 数据造成异常结果或 HardFault。例如void test(void) { volatile unsigned char buffer[2048]; buffer[0] 1; buffer[2047] 2; }如果编译器为这个局部数组分配栈空间它本身就需要 2 KB已经超过示例中的 1 KB 栈。HardFault 有很多原因栈溢出只是其中一种。四、中断向量表是什么中断向量表可以理解为一张“入口地址表”。CPU 根据异常或中断编号从表中找到对应的处理函数。启动文件中的部分定义如下__Vectors DCD __initial_sp DCD Reset_Handler DCD NMI_Handler DCD HardFault_HandlerDCD用于定义 32 位数据。这里保存的是地址值。需要特别注意第一项保存的是初始栈顶地址。从第二项开始保存异常或中断处理函数的入口地址。这张表通常在编译、链接时就已生成并随程序烧录到 Flash。例如向量表中有一项DCD EXTI0_IRQHandler配置并使能相应的外部中断后CPU 响应 EXTI0 中断时就会通过该项找到处理函数。void EXTI0_IRQHandler(void) { /* 判断并清除中断标志然后处理事件 */ }向量表只提供入口地址。要让中断正常发生还需要配置外设、中断线路和 NVIC。五、Reset_Handler 做了什么当前工程的复位处理代码核心如下Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, SystemInit BLX R0 LDR R0, __main BX R0 ENDP执行顺序是Reset_Handler ↓ SystemInit() ↓ __main几个关键写法的含义写法含义IMPORT声明一个在其他地方定义的符号EXPORT允许其他模块引用该符号LDR R0, SystemInit把SystemInit的地址加载到 R0BLX R0调用 R0 指向的函数并保存返回地址BX R0跳转到 R0 指向的入口[WEAK]弱定义可以被同名的强定义覆盖这里的SystemInit()返回后会继续执行跳转到__main的代码。六、SystemInit() 怎样配置系统时钟STM32F407 复位后先使用内部HSI 16 MHz时钟运行因此 CPU 可以执行启动代码和SystemInit()。在当前标准外设库工程中SystemInit()会调用SetSysClock()主要完成使能外部高速振荡器 HSE。等待外部晶振起振并稳定。配置 PLL 的分频和倍频参数。使能 PLL并等待锁定。配置总线分频、Flash 等待周期等。将系统时钟切换到 PLL 输出。25 MHz 晶振如何得到 168 MHz当前板子的外部晶振为25 MHz工程配置为#define PLL_M 25 #define PLL_N 336 #define PLL_P 2对应计算25 MHz ÷ 25 1 MHz 1 MHz × 336 336 MHz 336 MHz ÷ 2 168 MHz即系统时钟 晶振频率 ÷ PLL_M × PLL_N ÷ PLL_P 25 MHz ÷ 25 × 336 ÷ 2 168 MHz随后分配给不同总线时钟当前配置SYSCLK168 MHzAHB / HCLK168 MHzAPB1 / PCLK142 MHzAPB2 / PCLK284 MHz这里列的是总线时钟。部分外设还会使用单独的分频或倍频规则例如定时器时钟不能始终直接等同于 APB 时钟。25 MHz 是软件设置出来的吗板上晶振的标称频率由硬件决定。软件使能振荡电路并配置后续 PLL 和分频器。例如#define HSE_VALUE 25000000这个宏告诉软件外部时钟频率是多少。修改它不会改变晶振本身的振荡频率。上述 168 MHz 配置对应当前标准外设库工程。其他工程可能在不同位置配置时钟例如某些 HAL 工程会在main()中调用SystemClock_Config()。

相关推荐

SpringBoot+Vue智能无人仓库管理系统:从业务设计到部署实战
SpringBoot+Vue智能无人仓库管理系统:从业务设计到部署实战

做无人仓库管理系统这个项目的人,这几年越来越多了。SpringBoot加Vue这套组合在Java后端圈子里几乎成了标配,MySQL和MyBatis又是持久层最务实的搭配,所以像"基于SpringBootVue的智能无人仓库管理系统"这种题目,不管是课… · 2026/9/26 7:26:53

PCA+BP+PNN工业故障诊断落地实践
PCA+BP+PNN工业故障诊断落地实践

简介:本资源是一套面向机器学习初学者与算法实践者的PNN、PCA及BP神经网络综合实现代码包,聚焦于模式识别、特征降维与非线性分类任务,适用于课程设计、算法原理验证及小型数据建模项目。压缩包共49个文件,以35个MATLAB数据文件&a… · 2026/9/26 7:26:46

长程Agent上下文管理:分层记忆与主动压缩实战指南
长程Agent上下文管理:分层记忆与主动压缩实战指南

1. 长程 Agent 上下文管理为什么成了顶会硬骨头如果你最近翻过 ICLR、ICML 的投稿列表,会发现一个很明显的信号:Agent 相关的工作从“能不能跑通”全面转向了“能不能跑得久”。前两年大家还在卷 prompt 工程、卷工具调用格式,现在审稿人开口… · 2026/9/26 7:26:46

Twig `is odd` 奇偶测试:语法、源码实现与沙箱安全用法详解
Twig `is odd` 奇偶测试:语法、源码实现与沙箱安全用法详解

后端 【免费下载链接】Twig Twig, the flexible, fast, and secure template language for PHP 项目地址: https://gitcode.com/gh_mirrors/tw/Twig 点击查看 免费下载 导读 odd 是 Twig 模板语言内置的一个数值测试(test),用于… · 2026/9/26 7:59:02

Baserow 自托管无代码数据库完整教程:从建表到自动化系统只需 3 步
Baserow 自托管无代码数据库完整教程:从建表到自动化系统只需 3 步

Baserow 自托管无代码数据库完整教程:从建表到自动化系统只需 3 步 【免费下载链接】baserow Build databases, automations, apps & agents with AI — no code. Open source platform available on cloud and self-hosted. GDPR, HIPAA, SOC 2 compliant. Bes… · 2026/9/26 7:58:56

心脏病数据分析系统:Java全栈实战拆解与重难点解析
心脏病数据分析系统:Java全栈实战拆解与重难点解析

心脏病数据分析系统这类项目,本质上是一个典型的 Java 全栈实战案例,但又不完全是“增删改查脚手架”。它真正的技术含量集中在统计聚合、关联分析、可视化报表和医疗数据的处理细节上。如果你是因为找毕设参考、做技术练手、或者想转行医疗信息化方向而… · 2026/9/26 7:58:55

一次推送跑完 3 个阶段:Baserow CI/CD 流水线与 Docker 镜像构建拆解
一次推送跑完 3 个阶段:Baserow CI/CD 流水线与 Docker 镜像构建拆解

一次推送跑完 3 个阶段:Baserow CI/CD 流水线与 Docker 镜像构建拆解 【免费下载链接】baserow Build databases, automations, apps & agents with AI — no code. Open source platform available on cloud and self-hosted. GDPR, HIPAA, SOC 2 compliant. B… · 2026/9/26 7:58:55

物联网无线收发芯片选型指南:Sub-1G与2.4G方案对比及实战避坑
物联网无线收发芯片选型指南:Sub-1G与2.4G方案对比及实战避坑

1. 物联网无线收发芯片的底层逻辑与方案选型思路搞物联网硬件的人都有一个共识:有线方案再稳,也架不住场景碎片化。你不可能给每台共享单车拉根网线,也不可能给农田里的土壤传感器铺光纤。无线收发芯片就是解决“最后一百米”甚至“最后十公里… · 2026/9/26 7:58:55

Win11共享打印句柄无效(0x00000012)故障深度解析
Win11共享打印句柄无效(0x00000012)故障深度解析

1. 这不是蓝屏,但比蓝屏更让人抓狂:一句“句柄无效”如何瘫痪整个办公室打印链2026年9月某个周一上午9:17,行政部小张刚把季度报表发到共享打印机队列,屏幕右下角突然弹出红色警告框:“操作失败:句柄无效&a… · 2026/9/26 7:58:55

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

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

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码