news 2026/4/18 4:01:22

Keil5烧录STM32F103的Flash地址配置详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Keil5烧录STM32F103的Flash地址配置详解

Keil5烧录STM32F103:Flash地址配置的实战全解析

你有没有遇到过这样的情况?代码编译通过,Keil也显示“Download Success”,但单片机一上电就卡死、进不了main函数,甚至直接HardFault?调试器连上去一看,堆栈指针MSP指向一个莫名其妙的地址——别急,这很可能不是硬件坏了,而是Flash地址没配对

在STM32开发中,尤其是涉及Bootloader、IAP(在应用编程)或多段固件部署时,程序放在哪、从哪开始执行、中断向量表在哪,这些看似基础的问题一旦出错,就会导致系统启动失败。而这一切的核心,就是我们今天要深挖的主题:Keil5环境下,如何正确配置STM32F103的Flash地址

本文不讲空话,只聚焦实战。我们将从芯片启动机制出发,一步步拆解Keil的链接过程、内存映射原理,并手把手教你配置多级启动系统,最终实现一个稳定可靠的跳转逻辑。无论你是刚入门的新手,还是正在调试IAP的老兵,这篇文章都能帮你绕开那些“看不见的坑”。


为什么0x08000000这么重要?

先说结论:STM32F103的用户程序必须从0x08000000开始存放,否则极大概率无法正常启动。

但这背后到底发生了什么?

启动那一刻发生了什么?

STM32上电后,CPU并不会直接执行你的main()函数。它做的第一件事是:

从地址0x0000_0000读取第一个字作为主堆栈指针(MSP),第二个字作为复位向量(Reset Handler)

听起来很简单,但关键在于:物理Flash并不在0x0000_0000。真正的Flash起始地址是0x0800_0000

那CPU怎么找到程序的?答案是——重映射(Remap)

通过BOOT0和BOOT1引脚的电平组合,STM32会将不同的存储区域“映射”到0x0000_0000这个逻辑地址上。最常见的配置是:

  • BOOT0 = 0 → 主Flash被映射到0x0000_0000
  • 此时,0x0000_0000 实际指向 0x0800_0000

所以,当你把程序烧录到0x0800_0000时,CPU上电后就能通过重映射机制,在0x0000_0000处读到正确的MSP和Reset Handler,从而顺利启动。

🔥 如果你把程序烧到了0x0800_8000,但没有做任何处理,那么0x0000_0000处仍然是空白或旧数据——结果就是堆栈指针乱飞,HardFault不可避免。


Keil5是怎么决定程序烧到哪里的?

很多人以为,只要点了“Download”按钮,Keil就会自动把程序放到正确位置。其实不然。程序烧录到哪个地址,是由链接器(linker)决定的,而链接器的行为,又由两个地方控制:

  1. Target选项中的IROM设置
  2. 分散加载文件(.sct)

方法一:图形界面配置(适合简单项目)

打开Keil5 → Project → Options for Target → Target 选项卡:

参数典型值说明
IROM1 Start0x08000000程序烧录起始地址
IROM1 Size0x20000(128KB)可用Flash大小
IRAM1 Start0x20000000SRAM起始地址
IRAM1 Size0x5000(20KB)可用SRAM大小

这是最简单的配置方式,适用于标准应用程序。Keil会自动生成默认的分散加载脚本,把代码段(RO)放在这段Flash里。

但如果你要做IAP、双Bank切换或者自定义分区,就必须上手写.sct文件了。

方法二:自定义.sct文件(高级玩法必备)

假设你现在要做一个带Bootloader的系统:

  • Bootloader:0x0800_0000 ~ 0x0800_7FFF (32KB)
  • 用户App:从 0x0800_8000 开始

这时候,你得为App工程单独创建一个链接脚本app.sct

LR_APP 0x08008000 { ; 加载域起始地址 ER_APP 0x08008000 FIXED { ; 执行域固定在此 *.o (RESET, +First) ; 复位向量必须放最前面 *(InRoot$$Sections) .ANY (+RO) ; 其他只读代码 } RW_RAM 0x20000000 { ; 可读写段放SRAM .ANY (+RW +ZI) } }

然后在 Keil 中关闭“Use Memory Layout from Target Dialog”,并指定这个.sct文件路径。

✅ 关键点解释:
-FIXED表示不允许链接器随意移动该区域,确保地址绝对准确。
-(RESET, +First)强制将包含复位向量的目标文件放在最前面。
-.ANY (+RO)收集所有只读代码段(函数、常量等)。

这样编译出来的.hex.bin文件,代码就会从0x08008000开始生成,不会覆盖Bootloader。


烧录时别选错了Flash算法!

你以为写了正确的.sct就万事大吉?还有一个致命陷阱:Flash Algorithm选错

Keil在烧录时依赖一个叫“Flash Programming Algorithm”的驱动文件(.flm),它封装了针对特定MCU的擦除和写入操作。STM32F1系列根据Flash容量分为几种类型:

  • Low-density: ≤ 32KB
  • Medium-density: ≤ 128KB
  • High-density: > 128KB(如ZET6有512KB)

如果你的芯片是STM32F103ZET6(512KB Flash),却选了“Medium-density”算法,可能只能烧前128KB,后面全写不进去!

🔧 正确做法:

Project → Options for Target → Debug → Settings → Flash Download

→ 点击“Add” → 选择匹配的算法,例如:

STM32F10x High-density Flash

Keil通常能自动识别芯片并推荐合适的算法,但如果手动改过目标型号,记得回来检查一遍。


从Bootloader跳转到App:不只是函数指针那么简单

现在App已经烧到了0x08008000,接下来怎么跳过去?

很多初学者会这么写:

((void (*)(void))(*((uint32_t*)0x08008004)))();

看起来没错:取App的复位向量地址(MSP+4),强转成函数指针调用。但实际上,这样做风险极高。

跳转前必须做三件事

1. 设置主堆栈指针(MSP)

每个程序都有自己的栈空间定义。如果不先设置MSP,一旦发生中断或局部变量压栈,就会访问非法内存。

uint32_t *app_msp = (uint32_t *)0x08008000; __set_MSP(*app_msp);
2. 更新中断向量表偏移(VTOR)

Cortex-M3有一个寄存器叫SCB->VTOR,用来告诉CPU:“我的中断向量表不在默认位置,而在某个偏移处”。

如果你不更新VTOR,当中断触发时,CPU还会去0x0800_0000找ISR,而不是你App里的新向量表。

SCB->VTOR = 0x08008000;

别忘了加内存屏障,确保指令同步完成:

__DSB(); __ISB();
3. 关闭所有中断

跳转瞬间如果来了中断,而此时中断向量还没准备好,后果不堪设想。

__disable_irq();

完整跳转函数如下:

#define APP_START_ADDR 0x08008000 typedef void (*pFunc)(void); void jump_to_app(void) { pFunc app_reset = (pFunc)*(uint32_t*)(APP_START_ADDR + 4); // 复位向量 uint32_t app_stack = *(uint32_t*)APP_START_ADDR; // MSP // 停止所有外设、关闭中断 __disable_irq(); __set_MSP(app_stack); // 切换堆栈 SCB->VTOR = APP_START_ADDR;// 重定向向量表 __DSB(); __ISB(); app_reset(); // 跳! }

⚠️ 注意:这段代码执行后不会再回来。相当于“重启”进入新程序。


常见问题与避坑指南

❌ 现象:程序下载成功,但运行就HardFault

原因:堆栈指针MSP无效
排查:用调试器查看_initial_sp是否落在合法SRAM范围内(0x20000000~0x20005000)
解决:确认链接脚本中SRAM范围正确,且App的startup文件未被修改

❌ 现象:中断不响应,NVIC配置都对了

原因:VTOR没更新
解决:在跳转后立即设置SCB->VTOR = APP_START_ADDR;

❌ 现象:烧录时报“Flash Timeout”

原因:Flash算法不匹配 or 供电不足
解决
- 检查所选.flm是否对应芯片密度
- 测量VDD是否 ≥ 2.7V(Flash操作要求)
- 检查SWD接线是否松动

❌ 现象:升级后App跑不起来,但重新烧录可以

原因:跳转前未关闭定时器、串口等外设中断
解决:在跳转前禁用所有可能产生中断的模块


实战架构参考:三级启动系统设计

一个典型的可靠嵌入式系统软件架构可能是这样的:

[0x08000000] ┌─────────────────┐ │ Bootloader │ ← 出厂固化,负责基本初始化和升级判断 [0x08004000] ├─────────────────┤ │ IAP模块 │ ← 接收新固件,执行擦写,支持回滚 [0x08008000] ├─────────────────┤ │ 用户App │ ← 实现业务逻辑,可通过命令触发升级 └─────────────────┘

每一段都有自己独立的.sct配置,彼此互不干扰。升级时,IAP模块将新固件写入预留区域(比如0x0801_0000),验证无误后再替换当前App。

这种设计不仅提高了系统的可维护性,也为远程OTA升级打下基础。


写在最后:地址配置的本质是信任链

Flash地址配置看似是个技术细节,实则是整个系统可信执行起点的建立过程。

从CPU上电第一条指令,到Bootloader验证固件完整性,再到跳转时正确移交控制权——每一个环节的地址都必须精确无误。任何一处偏差,都会让整个系统的稳定性崩塌。

掌握Keil5下的内存布局控制,不仅仅是学会改几个参数,更是建立起一种底层思维:你知道代码最终落在哪块硅片上,也知道处理器如何一步步走到main函数。

下次当你点击“Download”时,不妨多问一句:我写的程序,真的会被正确加载吗?

如果你在实际项目中遇到更复杂的多核、加密启动或安全固件验证场景,欢迎在评论区交流讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 17:50:07

G-Helper实战指南:精通华硕笔记本性能调优的完整方案

G-Helper实战指南:精通华硕笔记本性能调优的完整方案 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops. Control tool for ROG Zephyrus G14, G15, G16, M16, Flow X13, Flow X16, TUF, Strix, Scar and other models 项目地址…

作者头像 李华
网站建设 2026/4/9 5:05:14

Ryujinx模拟器完整使用手册:3天掌握Switch游戏流畅运行技巧

Ryujinx模拟器完整使用手册:3天掌握Switch游戏流畅运行技巧 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 想要在个人电脑上体验任天堂Switch游戏的精髓吗?Ryu…

作者头像 李华
网站建设 2026/4/18 4:00:14

Ryujinx VP9软件解码器:从零构建高性能视频处理引擎

Ryujinx VP9软件解码器:从零构建高性能视频处理引擎 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 在数字媒体技术飞速发展的今天,视频解码器作为连接压缩数据…

作者头像 李华
网站建设 2026/4/7 20:33:59

Ryujinx Switch模拟器终极配置指南:快速获得完美游戏体验

Ryujinx Switch模拟器终极配置指南:快速获得完美游戏体验 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 想要在电脑上畅玩Switch游戏却不知从何开始?Ryujinx作…

作者头像 李华
网站建设 2026/4/16 10:37:56

基于STM32的JLink烧录器使用教程:Keil环境配置核心要点

从零搞定STM32烧录:J-Link Keil 配置实战全解析 你有没有遇到过这样的场景? 代码写得飞快,编译通过无误,信心满满点下“Download”,结果弹窗蹦出一句 “Cannot access target” ——瞬间心态崩了。反复插拔、换线…

作者头像 李华
网站建设 2026/4/16 13:02:55

猫抓Cat-Catch入门指南:5个步骤掌握网页资源嗅探

猫抓Cat-Catch入门指南:5个步骤掌握网页资源嗅探 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 还在为网页视频无法保存而烦恼吗?猫抓Cat-Catch这款智能浏览器扩展能够自动检…

作者头像 李华