You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F051R8T6 Bootloader IAP跳转APP触发硬故障求助

STM32F051 USART IAP Bootloader跳转APP硬故障排查

问题背景

为STM32F051_Disco开发USART IAP Bootloader,跳转至用户APP时触发硬故障。已通过STM32 Programmer验证Flash烧录内容与文件一致,尝试Stack Overflow及ST社区方案后仍未解决,故障地址为0x8003000。此前使用标准外设库可正常实现功能,切换HAL库后出现问题。

Bootloader相关代码

跳转函数

void bootloader_start_app(void) {

__disable_irq();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;

__set_PRIMASK(1);
// 设置主栈指针(MSP)为Flash指定地址的值
__set_MSP(*(uint32_t*) FLASH_USER_START_ADDR);

// 将复位处理函数地址赋值给函数指针
app_reset_handler = (void*) *(volatile uint32_t*) reset_handler_address;

// 调用用户应用的复位处理函数启动应用
app_reset_handler();
}

也曾使用以下跳转函数:

void flash_jump_to_app(void);

void flash_jump_to_app(void) {
 if (((*(__IO uint32_t*)FLASH_USER_START_ADDR) & 0x2FFE0000 ) == 0x20000000)
 {
 // 跳转至用户应用
 JumpAddress = *(__IO uint32_t*) (FLASH_USER_START_ADDR + 4);
 Jump_To_Application = (pFunction) JumpAddress;

 // 初始化用户应用的栈指针
 __set_MSP(*(__IO uint32_t*) FLASH_USER_START_ADDR);

 // 跳转至应用
 Jump_To_Application();
 }
 }

Flash地址定义

//#define FLASH_PAGE_SIZE         ((uint32_t)0x00000400)
#define FLASH_USER_START_ADDR   ((uint32_t)0x08003000)
#define FLASH_USER_END_ADDR     ((uint32_t)0x0800FC00)
#define USER_FLASH_LAST_PAGE_ADDRESS       0x0800FC00

链接脚本配置

MEMORY
{
    RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 8K
    FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 15K
}

已将Bootloader的Reset_Handler重命名为Boot_Reset_Handler,并同步修改Startup.s文件。

用户APP相关代码

向量表重映射配置

#define APPLICATION_ADDRESS (uint32_t)0x08003000
#define VECTOR_TABLE_BYTES 48

/* STM32F0 OTA必备配置 */
// 向量表配置
#if (defined(__CC_ARM))
__IO uint32_t VectorTable[48] __attribute__((at(0x20000000))); //0x20000000
#elif (defined(__ICCARM__))
#pragma location = 0x20000000
__no_init __IO uint32_t VectorTable[48];
#elif defined(__GNUC__)
__IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));
#endif

主函数初始化代码

/* 复位所有外设,初始化Flash接口和SysTick */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* 配置系统时钟 */
SystemClock_Config();

/* USER CODE BEGIN SysInit */
for (uint32_t i = 0; i < VECTOR_TABLE_BYTES; i++) {
    VectorTable[i] = *(__IO uint32_t*) (APPLICATION_ADDRESS + (i << 2));
}
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_SYSCFG_REMAPMEMORY_SRAM();
/* USER CODE END SysInit */

链接脚本配置

MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 8K-1024
  FLASH    (rx)    : ORIGIN = 0x8003000,   LENGTH = 64K-15k
}

已在链接脚本末尾添加段配置:

.RAMVectorTable : {*(.RAMVectorTable)} >VTRAM AT> FLASH /*Added for STM32-IAP*/

排查建议

  • 清理Bootloader外设状态:跳转前需复位所有Bootloader使用过的外设(如USART、GPIO)并禁用其中断,HAL库会保留外设寄存器状态,残留配置可能导致APP启动时触发异常。例如:

    HAL_UART_DeInit(&huart1);
    __HAL_RCC_USART1_FORCE_RESET();
    __HAL_RCC_USART1_RELEASE_RESET();
    
  • 修正APP向量表映射时机:当前APP在SystemClock_Config后才重映射向量表,但HAL_Init会调用SystemInit,而默认SystemInit会将SCB->VTOR设置为Flash起始地址(0x08000000),导致复位后向量表指向Bootloader区域。需在HAL_Init前完成向量表复制与重映射,或修改SystemInit函数中的VTOR配置。

  • 确保RAM区域无重叠:APP链接脚本中需明确划分向量表占用的RAM区域,避免与其他变量重叠。例如修改MEMORY定义:

    MEMORY
    {
      VTRAM   (xrw)    : ORIGIN = 0x20000000,   LENGTH = 192 /* 48个向量×4字节 */
      RAM     (xrw)    : ORIGIN = 0x200000C0,   LENGTH = 8K-1024-192
      FLASH   (rx)     : ORIGIN = 0x08003000,   LENGTH = 64K-15K
    }
    

    同时确保.RAMVectorTable段指向VTRAM。

  • 验证MSP有效性:检查APP起始地址0x08003000的第一个字(MSP值)是否在STM32F051的RAM范围内(0x20000000~0x20001FFF),若MSP值超出范围会直接触发硬故障。

  • 分析硬故障寄存器:通过调试读取SCB->HFSR、SCB->CFSR寄存器值,定位故障类型(如预取错误、数据访问错误),缩小排查范围。

  • 修改APP复位处理流程:在Startup.s的Reset_Handler中,先设置向量表偏移(或SRAM重映射),再调用SystemInit和HAL_Init,确保向量表在初始化前已正确配置。

内容的提问来源于stack exchange,提问作者Bhavesh Moradiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:14:52