我正在使用Keil uVision调试硬故障陷阱,这在STM32F205 Cortex-M3处理器上是一个精确的数据总线错误。由于冗长的调试和谷歌搜索过程,我发现导致陷阱的汇编指令。现在我正在寻找一种方法来避免下次发生陷阱时这个漫长的过程。
在Keil的应用说明209中,它说:
PRECISEERR:精确的数据总线错误: 0 =没有精确的数据总线错误 1 =发生了数据总线错误,并且为异常返回堆叠的PC值指向导致故障的指令。当处理器设置该位时,它将故障地址写入SCB-> BFAR
还有这个:
异常保存寄存器R0-R3,R12,PC&的状态。 LR是主堆栈还是进程堆栈(取决于发生异常时正在使用的堆栈)。
我正在解释的最后一句话应该有7个寄存器加上相应的堆栈。当我在内存中查找我的SP地址时,我看到导致错误的地址的地址比堆栈指针地址高10个字。
我的问题是:
导致陷阱的指令地址是否始终比当前堆栈指针高10个字?你能否指出一份文件,我可以在哪里阅读这是怎么以及为什么?
是否还有另一个包含此地址的寄存器?
答案 0 :(得分:2)
正如您所说,ARM Cortex-M3上的异常(或中断)将自动堆栈一些寄存器,即:
- 程序计数器(PC)
- 处理器状态寄存器(xPSR)
- R0-R3
- R12
- 链接注册(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
。
答案 1 :(得分:1)
返回地址的精确堆栈位置取决于中断处理程序需要多少堆栈。如果你看一下HardFault_Handler的反汇编,你应该能够看到堆栈中存储了多少数据/推送了多少寄存器,以及硬件中断机器推送的寄存器(R0-R3,R12,PC, LR& PSR)
我发现this对于如何调试硬故障非常好,尽管它需要一些内联汇编。