之前写过两篇关于 STM32 IAP bootloader 的博客(STM32 BootLoader升级固件、STM32 F0实现IAP升级固件),实际项目里又遇到了两个问题,记录一下最终的改进方案。
一、问题背景
APP 中原本有一个 App_reset 的功能,用来跳过 bootloader,核心做法是从 APP 里直接跳转到应用入口。实际运行中偶发卡住,怀疑与串口输入的中断状态有关。
同时,为了方便用户在 IAP 中输入 1 来确认升级,我在 bootloader 中加入了 4 秒等待。这样在正常启动时会浪费时间,尤其是当主程序被看门狗复位时,体验很差。
二、原有实现(有隐患)
从 APP 里直接跳转到应用入口的代码如下:
1 | static void Application_Reset(void) |
问题:
- APP 直接跳转到入口,有机会受外设/中断状态影响,导致偶发卡住。
- bootloader 的等待窗口固定,正常启动也会浪费时间。
三、改进方案
让 APP 主动设置“跳过 bootloader”的标志位,然后触发一次完整的硬件复位。bootloader 在上电后优先检测该标志,若存在则直接进入 APP。这样:
- APP reset 统一从 bootloader 开始,避免中断状态不一致。
- 只有 APP 明确要求跳过时才跳过,减少等待时间的浪费。
1. APP 设置标志并复位
1 | /* Safe backup-domain unlock (non-blocking) */ |
2. bootloader 读取标志并清理
bootloader 启动后首先检查 BKP0R 的标志位,如果命中则清理标志并直接跳转到 APP。
1 | /* Safe backup-domain unlock (non-blocking) */ |
四、效果
- APP 触发复位时始终走完整 reset 流程,稳定性提升。
- 正常启动不再固定等待 4 秒,体验明显改善。
- 逻辑更加清晰:APP 决定是否跳过,bootloader 只负责执行。
五、注意事项
BKP0R属于备份寄存器,需确保已开启备份域访问。- 标志位需在 bootloader 中及时清除,避免一直跳过升级窗口。
- 如果系统中还使用了备份寄存器存其他配置,需要统一分配。