STM32双Bank启动模式下OTA失败后自动回滚的硬件看门狗联动设计
👁 1 阅读 · 2026-08-27 · 嵌入式
在嵌入式OTA升级中,固件损坏或升级中断可能导致设备变砖。本文基于STM32双Bank启动模式,结合硬件独立看门狗(IWDG),设计一套自动回滚机制:升级失败时,看门狗超时复位,Bootloader检测Bank状态并回滚至旧固件,确保系统高可用性。文章详解原理、配置步骤、代码实现及注意事项,助力开发者构建健壮的OTA方案。
# STM32双Bank启动模式下OTA失败后自动回滚的硬件看门狗联动设计
## 1. 为什么需要双Bank + 看门狗联动?
传统OTA升级中,若新固件写入Flash中途断电或校验失败,设备可能无法启动,需人工干预。STM32的双Bank架构(如F7/H7系列)将Flash分为两个独立Bank,可分别存储旧版和新版固件。结合硬件看门狗(IWDG),即使新固件运行异常,看门狗超时复位后,Bootloader可检测Bank有效性并自动回滚,实现无人值守的可靠升级。
## 2. 双Bank启动原理
- **Bank结构**:以STM32H743为例,Flash共2MB,分为Bank1(0x08000000-0x080FFFFF)和Bank2(0x08100000-0x081FFFFF),每个Bank可独立擦写。
- **启动模式**:通过选项字节`nBOOT1`和`BOOT_ADD0`配置启动地址。支持`BOOT_SWAP`功能,可交换Bank映射,使复位后从指定Bank启动。
- **OTA流程**:
1. 当前运行在Bank1(旧固件),接收新固件写入Bank2。
2. 写入完成后,设置标志位(如备份寄存器),并触发软件复位。
3. Bootloader检查标志,若Bank2有效则交换Bank并跳转;若无效则回滚至Bank1。
## 3. 硬件看门狗联动设计
### 3.1 看门狗作用
- **IWDG**:独立于主时钟,由LSI(约32kHz)驱动,一旦启动无法停止,超时后产生复位。
- **联动策略**:
- 新固件启动后,必须在一定时间内“喂狗”(刷新计数器),否则复位。
- 若新固件因异常死机或卡死,看门狗超时复位,系统回到Bootloader。
- Bootloader检测到升级未完成或新固件无效,自动回滚至旧Bank。
### 3.2 系统状态机
```c
typedef enum {
STATE_BOOTLOADER = 0,
STATE_APP_OLD,
STATE_APP_NEW,
STATE_UPDATE_PENDING
} SystemState;
```
- 正常启动:Bootloader检查标志,决定进入旧或新App。
- 升级中:App写入新固件后,设置`UPDATE_PENDING`并复位。
- 回滚:若新App启动后未及时喂狗,复位后Bootloader清除标志并跳转旧App。
## 4. 配置步骤
### 4.1 硬件配置
- 使用STM32CubeMX启用IWDG,设置超时时间(如1秒)。
- 配置Flash双Bank模式(部分型号需通过选项字节设置)。
### 4.2 软件实现
**Bootloader部分(位于Bank1起始地址)**:
```c
// 检查升级标志(备份寄存器或Flash特定地址)
if (check_update_flag()) {
// 验证Bank2固件(CRC或校验和)
if (verify_bank2_firmware()) {
// 交换Bank映射
HAL_FLASHEx_OB_Program(OB_SWAP_BANK);
// 清除标志
clear_update_flag();
// 跳转到Bank2的App
jump_to_app(APP2_ADDRESS);
} else {
// 回滚:清除标志,启动旧App
clear_update_flag();
jump_to_app(APP1_ADDRESS);
}
} else {
// 正常启动,检查当前Bank有效性
if (is_current_bank_valid()) {
jump_to_app(current_app_addr);
} else {
// 尝试另一Bank
jump_to_app(other_bank_addr);
}
}
```
**App部分(旧/新固件均需包含)**:
```c
// 初始化IWDG
void IWDG_Init(void) {
// 使能LSI,设置预分频和重装载值,超时约1秒
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_64);
IWDG_SetReload(0xFFF); // 约1秒
IWDG_ReloadCounter();
IWDG_Enable();
}
// 主循环中周期性喂狗
while(1) {
// 业务逻辑
IWDG_ReloadCounter(); // 喂狗
}
```
**OTA升级函数(在旧App中)**:
```c
void OTA_Update(void) {
// 接收新固件并写入Bank2
write_firmware_to_bank2();
// 设置升级标志
set_update_flag();
// 软件复位
NVIC_SystemReset();
}
```
## 5. 完整代码示例(简化)
```c
// Bootloader main.c
int main(void) {
HAL_Init();
SystemClock_Config();
// 初始化Flash和选项字节
if (check_update_flag()) {
if (verify_bank2()) {
// 交换Bank
FLASH_OB_SwapBank();
clear_update_flag();
jump_to(APP2_ADDR);
} else {
clear_update_flag();
jump_to(APP1_ADDR);
}
} else {
// 正常启动,检查当前Bank有效性
if (is_bank1_valid()) jump_to(APP1_ADDR);
else if (is_bank2_valid()) jump_to(APP2_ADDR);
else error_handler();
}
}
// App中初始化看门狗
void App_Init(void) {
IWDG_Init();
// 其他初始化
}
// 主循环
while(1) {
// 任务处理
IWDG_ReloadCounter(); // 喂狗,确保系统存活
}
```
## 6. 注意事项
- **看门狗超时时间**:需大于新固件启动最长时间,避免误复位。建议2-5秒。
- **标志位存储**:使用备份寄存器(如RTC备份域)或Flash末尾扇区,注意掉电保持。
- **Bank交换操作**:需在无中断环境下执行,且操作后必须复位才生效。
- **固件验证**:除CRC外,建议在App启动后自检关键外设,若失败主动喂狗超时触发回滚。
- **调试时**:可暂时禁用看门狗,但发布前必须启用。
- **双Bank支持**:仅部分型号支持,如STM32F7/H7/L4+,需查阅参考手册。
## 7. 总结
通过双Bank启动与硬件看门狗联动,OTA升级失败后系统能自动回滚,极大提升可靠性。本文方案适用于对稳定性要求高的工业、医疗等场景。开发者可根据具体芯片型号调整细节,建议结合STM32CubeMX快速配置,并充分测试异常场景。