STM32F4 OTA 升级双 App 方案设计与实现

1. 引言

在嵌入式产品实际部署中,固件升级是保障设备功能迭代与缺陷修复的关键能力。对于 STM32F4 系列 MCU,OTA(Over-The-Air)升级通常需要结合 Bootloader 与 App 分区设计。本文围绕「双 App」架构展开,说明如何通过两个独立 App 分区实现升级失败回滚、断电保护与版本切换,提升升级过程的可靠性与安全性。

2. 双 App 方案概述

双 App 方案的核心思想是:在 Flash 中划分两个独立的 App 分区(App A 与 App B),Bootloader 根据标志位或版本信息决定启动哪一个 App。升级时,将新固件写入当前未运行的 App 分区,校验通过后切换启动标志,从而在升级失败时仍可回退到旧版本运行。

该方案相比单 App 方案的优势在于:

  • 升级失败可回滚:新固件写入备用分区后先校验,校验失败不切换标志,继续运行旧固件。
  • 断电保护:写入过程中断电,未完成的分区不参与启动,系统仍可正常启动。
  • 版本切换灵活:支持 A/B 分区交替升级,便于灰度发布与版本回退。

3. Flash 分区规划

以 STM32F407 为例,其 Flash 大小为 1MB,起始地址 0x08000000。典型分区规划如下:

分区名称 起始地址 大小 说明
Bootloader 0x08000000 64KB 引导程序,负责校验与跳转
App A 0x08010000 448KB 当前运行固件
App B 0x08080000 448KB 备用固件分区
Flag 区 0x080FF000 4KB 存储启动标志与版本信息

分区大小可根据实际固件体积调整,但需保证 Bootloader 与两个 App 分区互不重叠,且各分区起始地址按 Flash 扇区边界对齐。

4. Bootloader 设计

Bootloader 是双 App 方案的核心,负责完成以下工作:

  1. 读取启动标志:从 Flag 区读取当前应启动的 App 分区编号。
  2. 校验 App 有效性:对目标 App 分区进行 CRC 或 SHA 校验,确认固件完整。
  3. 跳转执行:设置 MSP 与 PC 指针,跳转到 App 的复位向量。

若目标 App 校验失败,Bootloader 自动切换到另一分区启动,实现故障回退。以下为 Bootloader 跳转核心代码示例:

c 复制代码
typedef void (*pFunction)(void);

void jump_to_app(uint32_t app_addr)
{
    uint32_t msp = *(volatile uint32_t *)app_addr;
    pFunction jump = (pFunction)(*(volatile uint32_t *)(app_addr + 4));

    if ((msp & 0xFFF00000) != 0x20000000) {
        return;  /* MSP 非法,拒绝跳转 */
    }

    __set_MSP(msp);
    jump();
}

5. App 端设计要点

App 端需要配合 Bootloader 完成升级流程,主要包括以下设计要点:

  • 中断向量表重定位:App 编译时需将中断向量表偏移到自身分区起始地址,运行时通过 SCB->VTOR 设置偏移。
  • 固件接收与写入:通过串口、Wi-Fi 或以太网接收升级包,按扇区擦写备用分区。
  • 升级标志写入:固件写入并校验完成后,更新 Flag 区中的启动标志,通知 Bootloader 下次启动新分区。
  • 版本上报:App 启动后向服务器上报当前版本号,便于后台管理升级状态。

中断向量表重定位示例:

c 复制代码
SCB->VTOR = APP_A_ADDR;  /* 或 APP_B_ADDR */

6. 升级流程设计

完整的双 App 升级流程如下:

  1. 设备运行在 App A,服务器下发新固件包。
  2. App A 接收固件,写入 App B 分区,并计算校验值。
  3. 写入完成后,App A 将启动标志切换为 App B,并复位重启。
  4. Bootloader 校验 App B 固件有效,跳转执行 App B。
  5. App B 启动后上报新版本号,升级完成。

若步骤 2 或步骤 3 失败,启动标志未切换,设备继续运行 App A,升级失败不影响当前功能。

7. 升级失败回滚机制

双 App 方案天然支持失败回滚,具体机制如下:

  • 写入失败:新固件写入备用分区过程中出错,备用分区标记为无效,Bootloader 继续启动原分区。
  • 校验失败:新固件写入完成但 CRC 校验不通过,不切换启动标志。
  • 运行失败:新固件启动后运行异常,可通过看门狗或心跳超时触发回滚标志,Bootloader 下次启动旧分区。

运行失败回滚需要 App 在启动早期设置「运行成功」标志,若超时未设置,Bootloader 判定启动失败并回退。

8. 注意事项与工程实践

在实际工程落地时,需要注意以下几点:

  • Flash 扇区对齐:STM32F4 扇区大小不一,分区边界必须落在扇区起始地址,避免擦写越界。
  • 编译链接脚本:App A 与 App B 使用不同的链接脚本,分别指定 Flash 起始地址与中断向量表偏移。
  • 固件包格式:建议在固件包头加入魔数、版本号、长度与 CRC,便于 Bootloader 校验。
  • 升级包加密:对固件进行加密传输,防止固件被逆向或篡改。
  • 双备份策略:Flag 区可存储两份标志,防止标志写入过程中断电导致状态丢失。

9. 总结

双 App 方案为 STM32F4 OTA 升级提供了可靠的容错机制,通过分区隔离、启动标志切换与校验回滚,有效解决了升级失败、断电中断等常见问题。该方案适用于对可靠性要求较高的量产设备,是嵌入式 OTA 设计中值得优先考虑的架构之一。

相关推荐
HRTOS1 小时前
HRTOS 4.0 内核资源配置优化:减少资源对象与消息队列数量
经验分享·单片机·系统架构·51单片机
陈年老古董1 小时前
Hive 分区表学习笔记:语法、操作、二级分区与动态分区
hive·笔记·学习
商业白皮书2 小时前
2026年上海豆包DeepSeekKimi百度AI通义千问GEO服务商选择
人工智能·笔记
存在morning2 小时前
【OLAP 学习笔记】Doris:数据湖之上的分析查询引擎
笔记·学习
2401_888859713 小时前
STM32H733 MPU、AXI、FMC学习
java·开发语言·stm32·spring
深圳老胡3 小时前
STM32F4 OTA升级:单App与双App方案优缺点对比
笔记·stm32·单片机·代码规范
mftang4 小时前
CAN总线控制段:位级结构、DLC编码、代际扩展与错误处理的系统性分析
单片机·嵌入式硬件·can总线·控制段·数据长度代码
yi01112 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
志尊宝13 小时前
Vue3 零基础每日笔记(073):keep-alive 页面缓存实战——列表页返回不丢状态
vue.js·笔记·缓存·#vue #前端 #前端开发·#javascript·#vue.js