当前位置: 首页 > news >正文

STM32-bootloader引导程序跳转机制笔记 - 教程

STM32-bootloader引导程序跳转机制笔记 - 教程

STM32F103C8T6 引导程序跳转机制笔记

适用场景:自定义 Bootloader 位于 Flash 起始 8KB( 0x08000000–0x08001FFF ),应用程序(APP)从 0x08002000 开始,芯片为 STM32F103C8T6(Flash 64KB、SRAM 20KB)。

关键内存与向量表

Memory Map 总览

如果有不懂的地方可以参考我的另一篇博客***STM32内存分配与堆栈***

地址高 ───────────────────────────────────────────────────────────
0xE000E000  System Control Space(NVIC、SCB、SysTick 等)└─ 核心控制寄存器区,软件不可搬移
0x40000000  外设寄存器空间(AHB/APB)└─ GPIO、USART、TIM、RCC、FLASH 控制器等
0x20000000  SRAM(20KB:0x20000000–0x20004FFF)├─ 堆(heap)通常自低地址向上增长└─ 栈(stack)通常自高地址向下增长(由 MSP/PSP 指向)
0x08000000  主 Flash(64KB:0x08000000–0x0800FFFF)├─ Bootloader(8KB):0x08000000–0x08001FFF└─ APP(56KB):     0x08002000–0x0800FFFF
(系统内置 Bootloader 位于“System Memory”专有区域,不在主 Flash 范围)
地址低 ───────────────────────────────────────────────────────────

点击keil的小魔术棒也可以看到如何进行内存分配
在这里插入图片描述
关注下面的ROM和RAM起始位置和区域大小

为什么要检查“栈指针必须落在 SRAM”

  • ARM Cortex-M 的固件格式规定:镜像开头的第一个 32 位值就是该固件的初始栈指针(MSP)
  • 栈需要在可读写的 RAM 中工作,因此这个值必须落在芯片的 SRAM 地址范围(F103C8 为 0x20000000–0x20004FFF )
    F103C8的RAM是20kB所以一般肯定是会指向栈顶0x20004FFF,因为栈是向低地址生长,这样也会更安全
  • 如果把 MSP 设为 0x20000000 (RAM 起点的低地址),第一次入栈就会越界到更低的地址(不在 SRAM),立刻触发错误(通常 HardFault)
  • 检查意义:快速判断指定地址上是否真的烧写了“像样的”APP
    • 合法示例: 0x20001234
    • 非法示例: 0x00000000 、 0xFFFFFFFF (通常是空闪存)或落在 Flash 的地址(不可作为栈)
      示例检查(两种写法,任选其一):
uint32_t msp = *(uint32_t*)APP_ADDRESS;
// 掩码法:判断起始段是否为 0x2000...
bool sp_ok = ((msp & 0x2FFE0000) == 0x20000000);
// 或范围法:判断落在 20KB SRAM 区间
bool sp_ok2 = (msp >= 0x20000000U && msp < 0x20005000U);

跳转前为何要做这么多“清场”操作

从 Bootloader 切换到 APP,本质上是一次“小型上下文切换”。目标是让 APP 进入时的环境与“芯片刚复位”尽可能一致,避免把 Bootloader 的状态“泄露”给 APP。

  • 关闭全局中断 __disable_irq() 防止在切换过程中,Bootloader 的中断(如 SysTick)突然触发,引发混乱。
  • 停用与清理 SysTick HAL_DeInit() 后, SysTick->CTRL/LOAD/VAL = 0 Bootloader 和 APP 都会配置各自的 SysTick;先关闭 Bootloader 的,避免互相干扰。
  • 清除 NVIC 状态(使能位与挂起位) 遍历 NVIC->ICER[i] = 0xFFFFFFFF; NVIC->ICPR[i] = 0xFFFFFFFF; 确保没有残留的中断在 APP 进入后意外触发。
  • 重定位向量表 SCB->VTOR = APP_ADDRESS 让所有中断从 APP 的向量表进入,而不是仍指向 Bootloader 的表。
  • 切换主栈指针 __set_MSP((uint32_t)APP_ADDRESS) 按 APP 向量表指定的初始栈指针重置 MSP。
  • 获取复位入口并跳转 reset = (uint32_t)(APP_ADDRESS + 4); 转为函数指针并调用。
  • 重新打开中断 __enable_irq() 让 APP 初始化后的 SysTick、中断能正常工作;这是解决 HAL_Delay() 卡住的关键。
    这些步骤缺一不可;省略任一步都可能导致不可预测的问题(如 HardFault、延时卡死、外设异常等)。

跳转代码示例

typedef void (* pFunction)(void);
void JumptoApplicaitoin(void){
uint32_t app_sp = *(__IO uint32_t*)APP_ADDRESS;
if((app_sp & 0x2FFE0000) == 0x20000000){
//关闭现有中断
__disable_irq();
//停用 HAL 和系统节拍
HAL_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL  = 0;
//清除 NVIC 状态
for (uint32_t i = 0; i < 8; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
//重定位中断向量
SCB->VTOR = APP_ADDRESS;
//取 APP 的复位入口
pFunction app_reset_handler = (pFunction)(*(__IO uint32_t*)(APP_ADDRESS + 4));
//设置主栈指针: __set_MSP(*(uint32_t*)APP_ADDRESS) ,按 APP 的向量表重置栈。
__set_MSP(app_sp);
//再打开中断
__enable_irq();
//调用复位入口
app_reset_handler();
}
}

要点:

  • APP_ADDRESS 对齐到 0x200 (如 0x08002000 )
  • __enable_irq() 放在跳转前,保证 APP 的 SysTick/中断可用

APP 工程链接设置(Keil/MDK 示例)

  • IROM1 Start: 0x08002000

  • IROM1 Size: 0x0000E000 (= 64KB - 8KB)

  • IRAM1 Start: 0x20000000

  • IRAM1 Size: 0x00005000 (20KB)
    校验方法(强烈建议):

  • 查看 .map 文件或 .htm / .axf 导出信息,确认

    • 向量表地址: 0x08002000
    • [0] MSP 在 0x20000000–0x20004FFF
    • [1] 复位入口在 0x08002000 之后的 Thumb 地址(最低位为 1)

常见坑点与后果

烧录与启动流程推荐

  1. 使用调试器烧录 Bootloader 到 0x08000000 (8KB 内)。
  2. 将 APP 烧录到 0x08002000 (通过 Keil 的 IROM1 设置或自定义 scatter)。
  3. 复位芯片:Bootloader 自检后直接跳到 APP 运行;无 APP 则闪灯。

调试建议

IAP(在线升级)扩展思路

  • 层次化设计:Bootloader 负责通信与写 Flash,APP 专注业务逻辑
  • 只擦/写 APP 区(1KB 页擦除),保护 Bootloader 区
  • 在 Bootloader 中做固件校验(CRC/签名)与回滚策略
  • 合理的接口与协议(UART/CAN/USB/SD 等),避免断电砖机

结论

应用程序app的分区跳转和升级app可以为你的小创意或者毕设增加亮点,想要stm32f103c8t6的bootloader模板工程可以点赞加收藏下方评论。

http://www.gsyq.cn/news/81958.html

相关文章:

  • Debian 13安装rime中文输入法
  • 中介者模式
  • [LabVIEW随笔-10] -基础知识3
  • linux进线程
  • Claude使用体验
  • 适合 Linux 强者的方式 freertos学习
  • 真相:大量硬件场景 根本跑不了 Linux
  • 2025最新玻璃胶推荐!国内优质玻璃胶品牌权威榜单发布,资质与性能双优助力高效密封 - 全局中转站
  • AshPostgres 政策绕过漏洞:空原子更新操作可能触发副作用
  • Supabase 实战指南:从零开始搭建数据库、配置 Auth 并接入 Resend 邮件服务
  • 2025 最新水泥基渗透结晶型防水涂料厂家 TOP5 评测!技术创新 + 工程实证专业榜单发布,构筑混凝土长效防护屏障 - 全局中转站
  • python: 用os库判断进程是否在运行中?
  • 2025.12.10总结
  • Enhance European/American Repairs with OTOFIX D1 Plus 1-Year Update Subscription
  • [Git] [GitHub] 如何在将本地代码推送到github
  • 2025最新AWHFVC防腐厂家TOP5评测!混凝土防腐品牌年度榜单,技术创新+长效防护,守护工业基建安全防线 - 全局中转站
  • keil5下载安装教程详细步骤(附安装包)Keil MDK v5.40下载安装详细教程
  • One Year AUTEL MK808S Update Service: Enhance Diagnostics Repairs for EU/American Vehicles
  • 散修带你入门鸿蒙应用开发基础第五节:函数的定义与使用 - 鸿蒙
  • Unity 场景切换
  • 2025氢力守护!富氢水灌装水处理设备TOP5:高浓稳定促灌装 - 极欧测评
  • 2025最新防腐涂料及工程厂家TOP5评测!技术创新+工程实证权威榜单发布,守护工业设施长效安全 - 全局中转站
  • 移动端_设计师值得收藏的10个Mobile端UI组件库10个WEB端UI框架[转]
  • 用 ssldump 跟踪 tls 障碍
  • 12-10午夜盘思
  • 实用指南:Python + uiautomator2 手机自动化控制教程
  • Alientech KESS3 Slave 12-Month Subscription: Professional Diagnostics Tuning for Euro/American Cars
  • 2025透析安全屏障!血液透析中心水处理设备TOP5:无菌高纯护生命 - 极欧测评
  • 100 平新房装修不踩坑!苏州这 6 家高性价比公司闭眼入 - 品牌测评鉴赏家
  • 跑酷基础训练1安全