仅烧录Bootloader与同时烧录Bootloader+Firmware时执行不一致问题
问题分析与解决方案
可能的原因
MPU(内存保护单元)未禁用
如果Bootloader启用了MPU并配置了内存访问权限,跳转前未禁用MPU会导致Firmware所在Flash区域无执行权限,取指令时触发MPU Fault,进而进入HardFault(你看到的bkpt指令正是默认HardFault处理函数的代码)。全局中断未关闭
Bootloader运行时若有中断处于Pending状态,跳转后会立即触发中断,此时VTOR刚更新,Firmware的中断向量表可能未被正确加载,导致异常。VTOR配置未同步
修改VTOR后未执行数据同步屏障(DSB)和指令同步屏障(ISB),导致VTOR配置未立即生效,跳转后仍使用旧向量表。调试器烧录配置问题
使用PEmicro Multilink单独烧录Bootloader时,若配置为“擦除整个Flash”而非“仅擦除Bootloader占用扇区”,会破坏Firmware区域;或误设置了Firmware区域的执行保护。Flash ECC校验错误
S32K146的P-Flash带ECC校验,若单独烧录Bootloader时调试工具未正确保留Firmware区域的ECC数据,会导致取指令时ECC错误触发HardFault。
解决方案
1. 修改跳转函数,完善上下文切换逻辑
更新JumpToAdresse函数,添加MPU禁用、中断关闭、屏障指令:
#include "S32K146.h" void JumpToAdresse(uint32_t StackPointerAdresse, uint32_t ProgramCounterAdresse) { // 1. 禁用全局中断 __disable_irq(); __DSB(); __ISB(); // 2. 禁用MPU(若Bootloader启用了MPU) if ((S32_MPU->CESR & S32_MPU_CESR_VLD_MASK) != 0) { S32_MPU->CESR &= ~S32_MPU_CESR_VLD_MASK; __DSB(); __ISB(); } // 3. 更新主栈和进程栈指针 __asm volatile("msr msp, r0"); __ISB(); __asm volatile("msr psp, r0"); // 4. 设置向量表偏移并同步 S32_SCB->VTOR = (uint32_t)FIRMWARE_A_VECTOR_TABLE_ADRESSE; __DSB(); __ISB(); // 5. 跳转到Firmware入口 __asm volatile("mov pc, r1"); }
2. 检查调试器烧录配置
- 使用PEmicro Multilink配套工具(如PROG for ARM)时,选择仅擦除Bootloader占用的Flash扇区,避免破坏Firmware区域。
- 确认未设置Firmware区域的执行保护或读保护。
3. 验证Firmware入口地址格式
确保ProgramCounterAdress的最低位为1(Cortex-M4要求Thumb模式指令地址必须为奇数),可在跳转前添加校验:
if ((ProgramCounterAdress & 0x1) == 0) { // 入口地址错误,添加错误处理 while(1); }
4. 检查Flash ECC状态
在跳转前读取FTFA_FSTAT寄存器,确认无ECC错误:
if ((FTFA->FSTAT & FTFA_FSTAT_EEERR_MASK) != 0) { // ECC错误,添加处理逻辑 FTFA->FSTAT = FTFA_FSTAT_EEERR_MASK; // 清除错误标志 }
内容的提问来源于stack exchange,提问作者Vaio
相关产品推荐
相关产品推荐

