STM32F405RG软件跳转DFU Bootloader异常求助:反复重启后进入模式
STM32F405RG软件跳转DFU Bootloader异常问题排查
问题描述
在STM32F405RG上通过软件尝试直接跳转到DFU Bootloader时,实际触发了软件复位并抛出RCC_FLAG_SFTRST标志。程序会反复执行跳转代码,数秒后才停留在Bootloader模式。禁用中断可一次性成功进入,但DFU模式需要启用中断才能完成代码上传,不清楚Bootloader跳回应用的原因。
跳转代码(在main中Init_HAL()后立即调用):
void JumpToBootloader(void) { void (*SysMemBootJump)(void); volatile uint32_t addr = 0x1FFF0000; HAL_RCC_DeInit(); HAL_DeInit(); // 关闭并重置SysTick SysTick->CTRL = 0; SysTick->LOAD = 0; SysTick->VAL = 0; // 未禁用中断,因为DFU模式需要 // __disable_irq(); // 重映射系统内存到0x00000000 __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); // 设置Bootloader跳转地址 SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4))); // 设置主栈指针 __set_MSP(*(uint32_t *)addr); // 跳转到Bootloader SysMemBootJump(); }
问题根源
核心原因是未清除所有挂起的中断请求。即使当前未开启全局中断,若之前有外设触发了中断且挂起标志未被清除,跳转至Bootloader后,Bootloader会重新开启中断,此时挂起的中断会立即触发,打乱Bootloader的执行流程,最终导致系统复位并回到应用程序。
HAL_DeInit()和HAL_RCC_DeInit()仅会重置外设和时钟,但不会清除NVIC中挂起的中断标志位,这是关键遗漏点。
修复方案
跳转前必须彻底清理中断环境,步骤如下:
- 先关闭全局中断,避免清理过程中触发新中断
- 手动清除所有NVIC挂起的中断请求
- 完成Bootloader映射、栈指针设置后,再重新开启全局中断
修改后的代码:
void JumpToBootloader(void) { void (*SysMemBootJump)(void); volatile uint32_t addr = 0x1FFF0000; // 1. 关闭全局中断,防止清理过程中触发新中断 __disable_irq(); // 2. 重置HAL和RCC外设 HAL_RCC_DeInit(); HAL_DeInit(); // 3. 关闭并重置SysTick SysTick->CTRL = 0; SysTick->LOAD = 0; SysTick->VAL = 0; // 4. 清除所有NVIC挂起的中断请求 for (uint32_t i = 0; i < (sizeof(NVIC->ICPR) / sizeof(NVIC->ICPR[0])); i++) { NVIC->ICPR[i] = 0xFFFFFFFF; } // 5. 重映射系统内存到0x00000000地址空间 __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); // 6. 获取Bootloader入口地址(栈指针后的复位向量) SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4))); // 7. 设置Bootloader的主栈指针 __set_MSP(*(uint32_t *)addr); // 8. 重新开启全局中断,满足DFU模式需求 __enable_irq(); // 9. 跳转到DFU Bootloader SysMemBootJump(); }
关键说明
- 清除NVIC挂起位是必须步骤:确保Bootloader启动后没有遗留的中断请求干扰执行
- 先关中断再清理:避免在清理过程中产生新的中断挂起
- 最后开启中断:保证DFU模式正常工作所需的中断功能
内容的提问来源于stack exchange,提问作者Rohit Josyula
相关产品推荐
相关产品推荐

