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

STM32F103C8从Bootloader跳转至应用触发HardFault故障求助

问题分析与解决方案

先拆解HardFault寄存器的关键信息:

  • HFSR = 0x40000000:位30(FORCED)置位,说明总线故障未被捕获,升级为HardFault。
  • BFSR = 0x00000082:对应IBUSERR(指令总线错误)和PRECISERR(精确数据总线错误),证明取指令或数据访问时触发了无效内存访问。
  • BFAR = 0x20005000:该地址是你的RAM末尾(0x20000000 + 20K = 0x20005000),也就是应用定义的栈顶_estack,说明错误和栈初始化或指令取指直接相关。

核心问题:跳转函数的地址错误

你的flash_jump_to_app函数里的汇编代码存在致命漏洞:

movw r0,#0xD000  \n
ldr   sp , [r0]  \n

movw r0, #0xD000仅设置r0的低16位为0xD000,高16位会被清零,最终r0的值是0x0000D000,而非应用向量表的实际地址0x800D000。

这会导致:

  1. 从无效地址0x0000D000读取栈顶值,触发总线错误;
  2. 即便侥幸读到应用的栈顶0x20005000,后续取复位向量时仍会访问错误地址,最终触发HardFault。

修复步骤

1. 修正跳转函数

替换错误的汇编指令,改用直接加载完整应用地址的方式,推荐用C代码实现更易维护:

#define APP_START_ADDR 0x800D000

void flash_jump_to_app(void)
{
    HAL_RCC_DeInit();
    HAL_DeInit();
    __disable_irq();
    
    // 设置向量表偏移到应用起始地址
    SCB->VTOR = APP_START_ADDR;
    
    // 定义函数指针类型
    typedef void (*pFunction)(void);
    pFunction app_reset_handler;
    
    // 从应用向量表读取栈顶并设置
    __set_MSP(*(uint32_t *)APP_START_ADDR);
    // 读取应用的Reset_Handler地址
    app_reset_handler = (pFunction)*(uint32_t *)(APP_START_ADDR + 4);
    // 跳转到应用
    app_reset_handler();
}

如果坚持用汇编,需改为加载完整地址:

asm("ldr r0, =0x800D000  \n"); // 加载完整应用向量表地址
asm("ldr sp, [r0]        \n");
asm("ldr r0, [r0, #4]    \n");
asm("bx r0               \n");

2. 验证应用向量表位置

检查应用的.map文件,确认__Vectors(向量表起始符号)的地址是0x800D000,Reset_Handler的地址正确对应向量表+4的位置。你的应用链接脚本已设置FLASH起始为0x800D000,这部分是正确的,但需确认编译器未偏移向量表。

3. 确认Flash空间无重叠

Bootloader的Flash范围是0x8000000 - 0x80077FF(30K),应用是0x800D000 - 0x80157FF(33K),两者无重叠,这部分无需调整。

4. 检查RAM初始化

跳转前Bootloader已执行HAL_DeInit()和HAL_RCC_DeInit(),外设会被重置,RAM数据会被应用覆盖,这部分通常不会引发问题,若应用有特殊RAM初始化需求,需单独处理。

总结

最关键的错误是跳转时未正确加载应用的完整向量表地址,导致访问无效内存。修正跳转逻辑后,HardFault问题即可解决。

内容的提问来源于stack exchange,提问作者Abdelrhman Kaamal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 15:40:22