STM32F103从Flash启动触发HardFault问题排查求助
嘿,我之前碰到过几乎一模一样的情况,你的问题核心大概率是Cortex-M3的Thumb模式强制要求没满足——STM32F103只支持Thumb/Thumb-2指令集,复位向量中的Reset_Handler地址必须将最低位设为1,才能告诉CPU以Thumb模式执行代码,否则会直接触发HardFault。
问题根源
看你提供的汇编代码,向量表中Reset_Handler的条目是:
.word Reset_Handler
Cortex-M3复位后,会直接把这个地址加载到PC寄存器。如果Reset_Handler的地址最低位是0(对应ARM模式),CPU会尝试执行ARM指令,但STM32F103完全不支持ARM模式,立刻就会触发异常。
为什么通过Bootloader跳转就正常?因为Bootloader在跳转时肯定手动处理了Thumb位(比如用blx指令,它会自动把目标地址的最低位设为1),而直接从Flash启动时,CPU是直接从向量表取地址加载PC,没有做这个转换。
修复方案
1. 修改向量表中的Reset_Handler地址
把向量表中对应的条目改成:
.word Reset_Handler | 1
这样强制设置地址最低位为1,明确告诉CPU进入Thumb模式执行代码。
2. 验证栈地址_estack的正确性
确保_estack设置在RAM的正确末尾位置,比如对于STM32F103C8T6(64KB RAM),_estack应该是0x20001000(RAM起始地址0x20000000加上64KB)。如果栈地址配置错误,复位后也可能触发异常。
3. 可选:提前配置Flash等待周期
如果你的系统时钟超过24MHz,默认的Flash等待周期(0)会导致Flash访问出错,进而触发HardFault。可以在Reset_Handler开头先配置Flash等待周期:
Reset_Handler: ; 配置Flash等待周期(示例对应72MHz系统时钟,设置2个等待周期) ldr r0, =0x40022000 ; FLASH_BASE地址 ldr r1, [r0, #0x00] ; 读取Flash控制寄存器ACR orr r1, r1, #0x02 ; 设置LATENCY位为2 str r1, [r0, #0x00] ; 将配置写回ACR ; 你的原有代码 mov r0, #0 mov r1, #0 mov r2, #0 b Reset_Handler
额外验证步骤
用GNU工具链的objdump检查生成的ELF文件,确认Reset_Handler的地址最低位是1:
arm-none-eabi-objdump -d your_program.elf | grep Reset_Handler
如果输出的地址最后一位是1(比如08000041),说明配置正确;如果是0(比如08000040),那就是问题所在。
内容的提问来源于stack exchange,提问作者Sergey




