# 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快速配置,并充分测试异常场景。