找出哪条指令导致了 Cortex M3 的陷阱

Find which instruction caused a trap on Cortex M3

我目前正在使用 Keil uVision 调试硬故障陷阱,结果证明这是 STM32F205 Cortex-M3 处理器上的精确数据总线错误。由于漫长的调试和谷歌搜索过程,我找到了导致陷阱的汇编指令。现在我正在寻找一种方法来避免下次出现陷阱时这个冗长的过程。

在 Keil 的应用笔记 209 中说:

PRECISEERR: Precise data bus error: 0 = no precise data bus error 1 = a data bus error has occurred, and the PC value stacked for the exception return points to the instruction that caused the fault. When the processor sets this bit it writes the faulting address to SCB->BFAR

还有这个:

An exception saves the state of registers R0-R3, R12, PC & LR either the Main Stack or the Process Stack (depends on the stack in use when the exception occurred).

我解释的最后一句话是应该有 7 个寄存器加上相应的堆栈。当我在内存中查找我的 SP 地址时,我看到导致错误的地址比堆栈指针地址高 10 个字。

我的问题是:

return 地址的精确堆栈位置取决于中断处理程序需要多少堆栈。如果你查看你的 HardFault_Handler 的反汇编,你应该能够看到除了硬件中断机制(R0-R3,R0-R3, R12、PC、LR 和 PSR)

我发现 this 是一个关于如何调试硬故障的好主意,尽管它需要一些内联汇编。

如你所说,ARM Cortex-M3上的异常(或中断)会自动入栈一些寄存器,即:

  • Program Counter (PC)
  • Processor Status Register (xPSR)
  • r0-r3
  • r12
  • Link Register (LR).

共8个寄存器(参考:Cortex™-M3 Technical Reference Manual, Chapter 5.5.1)。

现在,如果您使用汇编以外的语言编写异常处理程序,编译器可能会堆叠额外的寄存器,您无法确定有多少。

一个简单的解决方案是在真正的处理程序之前添加一小段代码,以传递自动堆栈寄存器的地址:

void myRealHandler( void * stack );

void handler(void) {
    asm volatile("mov r0, sp");
    asm volatile("b myRealHandler");
}

寄存器BFAR专门针对总线故障。它将包含错误地址,而不是错误指令的地址。例如,如果在地址 0x30005632 读取整数时出错,BFAR 将设置为 0x30005632