我是C嵌入式的新手。调试嵌入式系统以跟踪摄像机,我得到以下HardFaultHandler:
Atollic调试此时将其停止,而没有明显迹象表明存在特定错误。
__weak void DefaultHardFaultHandle ( void ){
asm volatile(
" tst lr,#4 \n"
" ite eq \n"
" mrseq r0,msp \n"
" mrsne r0,psp \n"
" mov r1,lr \n"
" ldr r2,=HardwareFaultHandler_GetSP \n"
" bx r2"
);
我没有大量的内存位置,但是,如何根据这些位置得出哪一行代码导致问题的结论呢? 这是代码的一部分,请帮助我:
uint8_t CameraImageTracker(uint8_t **edgeImage){
......
for (y = xRight.yStart; (y < height) && (exit == false); y++)
{
xRight.yStart = y;
int x = 0;
for (x = 0; (x < width) && (exit == false); x++)
{
if (edgeImage[y][x] == grayScale)
{
xRight.xStart = x;
xRight.yStart = y;
CountPixelX(width, height, &xRight, edgeImage, grayScale);
if (xRight.count > WhiteLinesPixMin)
{
exit = true;
}
}
}
WhiteLinesPixMin = xRight.count;
WhiteLinesPixMax = (WhiteLinesPixMin + 5);
if (exit == true)
{
exit = false;
xLeft.xStart = xRight.xStart;
xLeft.yStart = xRight.yStart;
CountPixelXleft(width, height, &xLeft, edgeImage, WhiteLinesPixMax, grayScale);
yLeft.xStart = xLeft.xEnd;
yLeft.yStart = xLeft.yEnd;
CountPixelY(width, height, &yLeft, edgeImage, grayScale);
yRight.xStart = xRight.xEnd;
yRight.yStart = xRight.yEnd;
CountPixelY(width, height, &yRight, edgeImage, grayScale);
ellipseCenter(&xRight, &yRight, &xLeft, &yLeft);
exit = true;
}
}
return 0;
答案 0 :(得分:3)
通过您发布的代码,我看不到您的硬故障源。但是,可以通过检查堆栈来找到硬故障的来源。进入硬故障时,Cortex-M4应该将旧的寄存器值压入堆栈。在堆栈上,它应如下所示:
sp + 0x00 = R0
sp + 0x04 = R1
sp + 0x08 = R2
sp + 0x0C = R3
sp + 0x10 = R12
sp + 0x14 = LR
sp + 0x18 = PC <- That is the one you need
sp + 0x1C = xPSR
sp + 0x20 = end of the stack before hard fault
但是要注意,如果您做了一些有趣的事情,PC可能会指向错误的地方或什么都没有,特别是如果您的硬件故障不是由程序引起的,而是由DMA,MPU或类似的东西引起的。
编辑:忘记提及:您应该首先查看SCB-> CSFR以了解发生了什么。在手册中查看这些位的含义。
答案 1 :(得分:1)
第一步是确定故障PC值是多少。在您的“ DefaultHardFaultHandle”中,注意:
" mrseq r0,msp \n"
" mrsne r0,psp \n"
" mov r1,lr \n"
" ldr ,=HardwareFaultHandler_GetSP \n"
" bx r2"
前两个指令将正确的SP(堆栈指针)传递给R0。有两个SP,使用的SP取决于发生故障时CPU所处的CPU模式(线程或处理程序模式)。最后两条指令跳转到新的例程HardwareFaultHandler_GetSP。换句话说,如果您要为HardwareFaultHandler_GetSP编写一个C签名,它将看起来像这样:
void HardwareFaultHandler_GetSP(uint32_t * sp);
您应该能够使用调试器进行深入研究,以找到发生故障的PC。例如单步执行DefaultHardFaultHandle,一旦它获得SP到R0中,然后查看R0的值。假设它是0x20004000。然后使用内存窗口,查看地址0x20004000 + 0x18或0x20004018。包含发生故障的PC。
如果您经常执行此操作,请使用我写的函数签名,可以修改HardwareFaultHandler_GetSP以显示“ SP [6]”以获取PC。
注意,由于缓存,PC可能会被一条或两条指令关闭。总线故障状态寄存器(或BFSR,可通过地址0xE000ED29进行字节访问)中的IMPRECISERR位(位2)控制此行为。如果已启用,则可以在调试器中将其关闭(例如,在main()处中断)或以编程方式将其关闭。这会使您的程序运行速度变慢,但在出现故障时会显示准确的PC。