在嵌入式开发人员看来,在Arm Cortex-M微控制器上调试最糟糕、最烦人的故障之一是硬故障。如果你幸运的话,在你犯了一些非常明显的错误之后,这个硬错误就会出现,你可以很快地撤销它。在这篇文章中,我们将详细介绍用来确定原因和纠正硬故障的过程。
不精确的错误
当发生硬故障时,嵌入式开发人员别无选择,只能深入微控制器,检查故障寄存器。深入研究的第一个寄存器是可配置故障状态寄存器(CFSR)。CFSR由三个故障寄存器组成:
l MemManage故障状态
l 总线故障状态
l 使用故障状态
这些寄存器一起可以帮助我们开始理解为什么会有故障。
不幸的是,存储在这些寄存器中的值并不总是决定性的或有用的,这取决于硬故障。例如,检查CFSR寄存器的值时,它被设置为0x400。下面的图1详细说明了CFSR中各个位的含义。值0x400是一个不精确的错误!
不精确错误是一种异步错误,是由于优先级问题、禁用错误、内存访问问题等而导致的总线错误。不精确故障的问题是,嵌入式开发人员不能相信其他故障寄存器包含任何关于故障原因的直接或有价值的信息!没错,在这一点上,你是在还原代码或猜测和随机尝试不同的创可贴来尝试和修复问题。
从不精确到精确的误差
值得庆幸的是,当你遇到一个不精确的错误导致你的硬故障时,并没有失去一切。不精确的错误可能是由于CPU使用内部缓冲区来缓存指令造成的。如果缓冲区被禁用,执行的每条指令都将线性执行。结果将是不精确的错误变成精确的错误,并且所有其它故障寄存器可以帮助识别故障。
禁用缓冲器的步骤非常简单。开发人员可以通过设置ACTLR寄存器中的DISDEFWBUF来禁用写缓冲器。执行此操作的代码如下所示:
SCN SCB-> ACTLR | = SCN SCB _ ACTLR _ DISDEFWBUF _ Msk;
除了禁用写缓冲器之外,确保在SHCSR寄存器中启用使用、总线和存储器故障也是一个好主意。嵌入式开发人员使用以下C代码片段可以启用这些故障:
// Enable Usage-/Bus-/Mem Faults
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk
| SCB_SHCSR_BUSFAULTENA_Msk
| SCB_SHCSR_MEMFAULTENA_Msk;
编译代码,然后重新运行代码。希望不精确的错误现在是一个精确的错误,它使我们能够更深入地挖掘硬故障的原因。
调试精确错误
现在我们有了精确的误差,我们可以检查CFSR寄存器中的其他位。在这种情况下,唯一设置的另一位是BFARVALID位。BFARVALID位告诉我们,存储在BFAR寄存器中的总线地址是一个有效地址,并且可以告诉我们是什么导致了我们的故障。最初,仅通过BFARVALID位置位,我们就可以推断出总线故障导致了硬故障。
本例中,BFAR寄存器(总线故障地址寄存器)保存的值为0x100000。有意思!当总线试图访问地址0x100000时,为什么处理器会出错?对微控制器存储器映射的快速调查显示,存储器地址0x100000并不存在!在这种情况下,闪存从0x0到0x100000。处理器应该在抛出错误,但是为什么编译器在内存空间之外生成指令?
结论
如果你没有使用正确的流程,排除微控制器上的硬故障可能会很困难。在这篇文章中,我们看到开发人员可以使用CFSR寄存器来识别他们的硬故障的原因。在更复杂的情况下,嵌入式开发人员可能需要禁用CPU写缓冲区来将不精确的错误变为精确的错误。一旦做到这一点,识别问题的时间就会大大缩短。希望这能帮助你快速解决你或你的团队将来可能遇到的任何困难。