MCU OTA升级方案设计中的分区管理与回滚操作
在物联网终端中,OTA(Over-The-Air)固件升级是产品生命周期管理的核心能力。一个健壮的OTA方案必须解决两个问题:Flash分区规划避免擦写冲突,以及升级失败后自动回滚(Rollback)防止设备变砖。本文以STM32(Cortex‑M4/M7)外接SPI Flash或内置Dual-Bank Flash为例,阐述典型设计与代码框架。
一、Flash分区规划(以内置双Bank或外置Flash为例)
1.1 内置Dual-Bank情形(STM32F4/F7/H7部分型号)
Bank 起始地址 用途
Bank1 (Active A) 0x08000000 当前运行固件(Slot A)
Bank2 (Slot B) 0x08100000 待接收新固件(Slot B)
Option Bytes — 指示启动Bank + 回滚标记
1.2 外置SPI Flash + 片内单Bank情形
区域 说明
Bootloader (32KB) 固定,不OTA,校验Slot并跳转
App Slot A (≥128KB) 主运行区
App Slot B (≥128KB) 下载缓冲/备用区
OTA Meta (1扇区) 存 active_slot, update_pending, crc32, rollback_cnt
Bootloader每次启动读Meta决定跳A还是B。
二、OTA流程与状态机
[Running App]
│ 收到OTA包(分片)
▼
[写Slot B + SHA256/CRC校验]
│ 校验OK
▼
置 Meta.update_pending=1, Meta.next_slot=B
│ 软复位 → Bootloader
▼
Bootloader:
if(update_pending && crc_ok){
跳Slot(B);
清update_pending;
置active_slot=B;
启动看门狗监测App心跳;
} else {
回滚跳原Slot(A);
}
三、回滚(Rollback)实现要点
3.1 App心跳与超时检测(Bootloader侧)
// Bootloader简短主循环(或WDT ISR中计)
#define APP_ALIVE_TIMEOUT_MS 3000
static uint32_t last_alive_ms = 0;
void SysTick_Handler(void){
if (millis() - last_alive_ms > APP_ALIVE_TIMEOUT_MS) {
// App未置活 → 认为启动失败
if (meta.active_slot != meta.orig_slot) {
meta.active_slot = meta.orig_slot; // 回滚
meta.fail_cnt++;
write_meta(&meta);
}
NVIC_SystemReset(); // 重启进Bootloader再跳原Slot
}
}
App中周期性置位:
// 在App定时任务调
extern uint32_t last_alive_ms;
last_alive_ms = HAL_GetTick();
3.2 防无限回滚
限制连续失败次数(如 ≤3),超过则停留在原Slot并上报错误,不再尝试新Slot。
四、Bootloader最小跳转代码(伪码)
void boot_jump(uint32_t addr)
{
uint32_t sp = *(volatile uint32_t*)addr;
uint32_t reset = *(volatile uint32_t*)(addr + 4);
__set_MSP(sp);
SCB->VTOR = addr; // 重定位向量表
((void(*)(void))reset)(); // 跳Reset_Handler
}
int main(void)
{
read_meta(&meta);
if (meta.update_pending && meta.crc_ok) {
meta.orig_slot = meta.active_slot;
meta.active_slot = meta.next_slot;
meta.update_pending = 0;
write_meta(&meta);
boot_jump(meta.active_slot);
} else if (meta.update_pending && !meta.crc_ok) {
// 校验失败直接回滚
meta.update_pending = 0;
write_meta(&meta);
boot_jump(meta.active_slot); // 仍跳原Slot
} else {
boot_jump(meta.active_slot);
}
while(1);
}
五、安全与完整性校验
• CRC32 / SHA256:下载完Slot B后算摘要,与云端下发摘要比对
• 签名验证(可选):ECDSA P-256 验签防篡改(需安全元件或TrustZone-M)
- Anti-rollback版本号:新固件fw_ver必须 ≥ 当前fw_ver,否则拒刷
六、常见设计缺陷与规避
缺陷 后果 规避
Bootloader可OTA覆盖 变砖无救 Bootloader区域写保护(FLASH_OB_WRP)
无心跳检测 坏固件卡死不回滚 加WDT + App心跳超时判断
Meta区无备份 写Meta中途掉电→状态混乱 用双备份Meta扇区(A/B拷贝)或写-校验-提交
回滚无限循环 坏固件反复尝试 fail_cnt上限 + 停留原Slot报Error
七、结语
MCU OTA方案的健壮性建立在三点:合理的双Slot/Bank分区、Bootloader做唯一跳转与校验、失败自动回滚(带次数限制+心跳监测)。按此框架设计,即便新固件存在Bug也能安全退回上一版本,真正做到“升级不怕变砖”。





