|

楼主 |
发表于 2025-2-20 14:24:12
|
显示全部楼层
本帖最后由 坚持再坚持 于 2025-2-20 14:32 编辑
之前发帖的疑问点是没有考虑到:在进入硬件异常中断时,如果在中断函数里面定义了局部变量,则会更新 MSP 的指针,因为局部存储在栈里面。
针对2楼管理员建议的方法,我做了注释说明:(在打印出 PC 和 LR 的值后,可以利用 addr2line.exe 定位具体的代码位置,管理员介绍过:addr2line.exe的使用方法)
__asm void HardFault_Handler(void) /* __asm放在函数返回类型之前,说明函数体内部是汇编代码,asm是assembly的简写 */
{
TST LR, #4 /* 这条指令用于测试 LR 寄存器中的第三位(即值4对应的位),通过按位与操作来确定这一位置的值 */
ITE EQ /* ITE是 If-The-Else指令。EQ 表示如果上一个指令的结果是零(也就是 TST LR #4 的结果为零,即 LR 的第2位为0),那么执行MRSEQ */
MRSEQ R0, MSP /* 如果 LR 的第2位为0(即 EQ 条件成立),表示使用的是 MSP,则将 MSP 的值加载到 R0 */
MRSNE R0, PSP /* 如果 LR 的第2位为1(即 EQ 条件不成立),表示使用的是 PSP,则将PSP的值加载到R0 */
MOV R1, LR /* 将 LR 寄存器的值复制到 R1 寄存器 */
B __cpp(HardFault_Handler_C) /* B是Branch指令,表示调转到指定的地址;__cpp()是Keil编译器的语法,表示调转到C语言函数。调转时将将 R0 和 R1 的值作为参数传递给HardFault_Handler_C */
}
void HardFault_Handler_C(unsigned long * hardfault_args, unsigned int lr_value)
{
unsigned long stacked_r0;
unsigned long stacked_r1;
unsigned long stacked_r2;
unsigned long stacked_r3;
unsigned long stacked_r12;
unsigned long stacked_lr;
unsigned long stacked_pc;
unsigned long stacked_psr;
unsigned long cfsr;
unsigned long bus_fault_address;
unsigned long memmanage_fault_address;
uint32_t i = 0;
bus_fault_address = SCB->BFAR;
memmanage_fault_address = SCB->MMFAR;
cfsr = SCB->CFSR;
stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
DEBUG_TRACE(255, "[HardFault]\n");
DEBUG_TRACE(255, "- Stack frame:\n");
DEBUG_TRACE (255, " R0 = %x\n", stacked_r0);
DEBUG_TRACE (255, " R1 = %x\n", stacked_r1);
DEBUG_TRACE (255, " R2 = %x\n", stacked_r2);
DEBUG_TRACE (255, " R3 = %x\n", stacked_r3);
DEBUG_TRACE (255, " R12 = %x\n", stacked_r12);
DEBUG_TRACE (255, " LR = %x\n", stacked_lr);
DEBUG_TRACE (255, " PC = %x\n", stacked_pc);
DEBUG_TRACE (255, " PSR = %x\n", stacked_psr);
DEBUG_TRACE (255, "- FSR/FAR:\n");
DEBUG_TRACE (255, " CFSR = %x\n", cfsr);
DEBUG_TRACE (255, " HFSR = %x\n", SCB->HFSR);
DEBUG_TRACE (255, " DFSR = %x\n", SCB->DFSR);
DEBUG_TRACE (255, " AFSR = %x\n", SCB->AFSR);
if (cfsr & 0x0080) DEBUG_TRACE (255, " MMFAR = %x\n", memmanage_fault_address);
if (cfsr & 0x8000) DEBUG_TRACE (255, " BFAR = %x\n", bus_fault_address);
DEBUG_TRACE (255, "- Misc\n");
DEBUG_TRACE (255, " LR/EXC_RETURN= %x\n", lr_value);
while(1);
}
|
|