STM32F042C4T6应用跳转Bootloader失败求助
问题背景
我有一块搭载STM32F042C4T6的自定义电路板,用USART2加载固件,但连接器只引出了RX、TX、GND引脚。通过USART刷固件需要把BOOT0引脚置高,但这个引脚现在通过下拉电阻保持低电平;手动拉BOOT0高的时候固件加载正常,但后续没法接触PCB,没法手动操作BOOT0。于是尝试通过应用程序跳转至系统存储器Bootloader(地址0x1FFFC400),但调用自定义函数后,用CubeProgrammer连接时提示“检查连接或BOOT引脚状态”,求解决办法。
当前使用的跳转函数
/* 从用户应用跳转至系统存储器Bootloader的函数 * * 需要跳转时调用此函数 */ void JumpToBootloader(void) { void (*SysMemBootJump)(void); /** * 步骤1:设置系统存储器地址 * * 对于STM32F429,系统存储器地址是0x1FFF 0000 * 其他系列请参考AN2606文档表110中的存储器地址说明 */ volatile uint32_t addr = 0x1FFFC400; /** * 步骤2:禁用RCC,恢复默认复位配置 * 使用内部时钟,关闭PLL等 */ #if defined(USE_HAL_DRIVER) HAL_RCC_DeInit(); #endif /* defined(USE_HAL_DRIVER) */ #if defined(USE_STDPERIPH_DRIVER) RCC_DeInit(); #endif /* defined(USE_STDPERIPH_DRIVER) */ /** * 步骤3:禁用SysTick定时器并恢复默认值 */ SysTick->CTRL = 0; SysTick->LOAD = 0; SysTick->VAL = 0; /** * 步骤4:禁用所有中断 */ __disable_irq(); /** * 步骤5:将系统存储器重映射到地址空间0x0000 0000 * 不同系列寄存器可能不同,请参考对应参考手册 * * STM32F4xx使用SYSCFG的MEMRMP寄存器(位[1:0]) * STM32F0xx使用SYSCFG的CFGR1寄存器(位[1:0]) * 其他系列请参考对应参考手册 */ //手动重映射... { #if defined(STM32F0) SYSCFG->CFGR1 = 0x01; #endif //} ...或者使用HAL驱动的宏 //__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); //调用HAL宏完成重映射 /** * 步骤6:设置系统存储器的跳转地址 * 使用偏移4字节的地址,该地址指定程序启动位置 */ SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4))); /** * 步骤7:设置主堆栈指针 * 此步骤必须最后执行,否则函数中的局部变量会因为堆栈指针位置变化而失效 * * 设置SRAM中指定的堆栈指针地址 */ __set_MSP(*(uint32_t *)addr); /** * 步骤8:调用跳转函数,启动系统存储器执行 */ SysMemBootJump(); /** * 步骤9:连接USB<->UART转换器到指定USART引脚,测试Bootloader * 使用STM32 Flash Loader Demonstrator软件测试 */ }
排查与修复建议
必须开启SYSCFG时钟:STM32F0系列中,修改SYSCFG寄存器前要先开时钟,代码里直接改
SYSCFG->CFGR1但没开时钟会导致重映射失效。添加以下代码在修改SYSCFG之前:// 开启SYSCFG时钟(HAL库方式) __HAL_RCC_SYSCFG_CLK_ENABLE(); // 或者寄存器方式 // RCC->APB2ENR |= RCC_APB2ENR_SYSCFGCOMPEN;彻底关闭USART2外设:跳转前要完全关闭USART2,包括禁用中断、清除挂起标志、关闭时钟,避免残留配置干扰Bootloader通信:
// 禁用USART2所有控制位 USART2->CR1 = 0; USART2->CR2 = 0; USART2->CR3 = 0; // 清除挂起中断 NVIC_ClearPendingIRQ(USART2_IRQn); // 禁用USART2中断 NVIC_DisableIRQ(USART2_IRQn); // 关闭USART2时钟(F042的USART2挂在APB1) RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN;确保RCC初始化后时钟稳定:调用
HAL_RCC_DeInit()后,系统切换到HSI内部时钟,需要等待HSI就绪再继续:#if defined(USE_HAL_DRIVER) HAL_RCC_DeInit(); // 等待HSI振荡器就绪 while(!(RCC->CR & RCC_CR_HSION)); #endif关闭所有外设时钟:跳转前关闭APB1、APB2上的所有外设时钟,避免残留信号干扰:
RCC->APB1ENR = 0; RCC->APB2ENR = 0;验证CubeProgrammer串口配置:Bootloader默认USART2参数是115200波特率、8位数据位、1位停止位、无校验,确保CubeProgrammer配置完全匹配,且串口转换器是TTL电平。
确认系统存储器地址正确:STM32F042的系统存储器起点确实是
0x1FFFC400,这部分代码没问题,但可以再核对AN2606文档确认。
内容的提问来源于stack exchange,提问作者Nik_01

