简体   繁体   English

寻找硬故障的源头-C嵌入式ARM Cortex-M4 32b

[英]Finding the source of a Hard Fault - C embedded ARM Cortex-M4 32b

I am new in C embedded. 我是C嵌入式的新手。 Debugging an embedded system for image camera tracking I get the following HardFaultHandler: 调试嵌入式系统以跟踪摄像机,我得到以下HardFaultHandler:

The Atollic Debug stops it at this point without apparently indications of specific errors. 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"
 );

I dont have bunch of memory locations, however, how can I make conclusions on which line of code caused the issue according to these locations? 我没有大量的内存位置,但是,如何根据这些位置得出哪一行代码导致了问题呢? This is part of the code, please help me: 这是代码的一部分,请帮助我:

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;

By the code you have posted I can't see a source of your hardfault. 通过您发布的代码,我看不到您的硬件故障源。 But the source of the hardfault can be found by inspecting the stack. 但是,可以通过检查堆栈来找到硬故障的来源。 The Cortex-M4 should push the old register values onto the stack when entering a hard fault. 进入硬故障时,Cortex-M4应该将旧的寄存器值压入堆栈。 On the stack it should look like this: 在堆栈上,它应如下所示:

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 

But be aware if you made some funny things the PC may point to the wrong place or to nothing especially if your hardfault was not caused by your program but by DMA, MPU or something like that. 但是请注意,如果您做了一些有趣的事情,PC可能会指向错误的地方或什么都没有,特别是如果您的硬件故障不是由程序引起的,而是由DMA,MPU或类似的东西引起的。

EDIT: Forget to mention: You should first look into the SCB->CSFR to understand what happened. 编辑:忘记提及:您应该首先查看SCB-> CSFR以了解发生了什么。 Look in the handbook what the bits mean. 在手册中查看这些位的含义。

The first step is to determine what is the PC value when it faults. 第一步是确定故障时的PC值是多少。 In your "DefaultHardFaultHandle", notice: 在您的“ DefaultHardFaultHandle”中,注意:

" mrseq r0,msp \\n" " mrsne r0,psp \\n" " mov r1,lr \\n" " ldr ,=HardwareFaultHandler_GetSP \\n" " bx r2" " mrseq r0,msp \\n" " mrsne r0,psp \\n" " mov r1,lr \\n" " ldr ,=HardwareFaultHandler_GetSP \\n" " bx r2"

The first two instructions get the proper SP (stack pointer) to R0. 前两个指令将正确的SP(堆栈指针)指向R0。 There are two SPs and the one in used depends on the CPU mode (thread or handler mode) the CPU is in when it faults. 有两个SP,使用的SP取决于发生故障时CPU所处的CPU模式(线程或处理程序模式)。 The last two instructions jump to a new routine HardwareFaultHandler_GetSP. 最后两条指令跳转到新的例程HardwareFaultHandler_GetSP。 In other word, if you were to write a C signature for HardwareFaultHandler_GetSP, it would look like this: 换句话说,如果您要为HardwareFaultHandler_GetSP编写一个C签名,它将看起来像这样:

void HardwareFaultHandler_GetSP(uint32_t *sp); void HardwareFaultHandler_GetSP(uint32_t * sp);

You should be able to drill down using the debugger to find the faulting PC. 您应该能够使用调试器进行深入分析,以找到发生故障的PC。 eg stepping through DefaultHardFaultHandle, once it obtains the SP into R0, then look at the R0's value. 例如,单步执行DefaultHardFaultHandle,一旦它获得SP到R0中,然后查看R0的值。 Let's say it is 0x20004000. 假设它是0x20004000。 Then use a memory window, look at the address 0x20004000+0x18, or 0x20004018. 然后使用内存窗口,查看地址0x20004000 + 0x18或0x20004018。 That contains the PC where it faults. 包含发生故障的PC。

If you do this a lot, using the function signature as I have written, you can modify HardwareFaultHandler_GetSP to display "SP[6]" to get the PC. 如果您经常这样做,请使用我编写的函数签名,可以修改HardwareFaultHandler_GetSP以显示“ SP [6]”以获取PC。

NOTE the PC may be off by one or two instructions due to caching. 注意由于缓存的原因,PC可能会被一条或两条指令关闭。 The IMPRECISERR bit (bit 2) in the BusFault Status Register (or BFSR, which is byte accessible at address 0xE000ED29) controls this behavior. 总线故障状态寄存器(或BFSR,可通过地址0xE000ED29进行字节访问)中的IMPRECISERR位(位2)控制此行为。 If it is on, you can turn it off in the debugger (eg when you break at main()) or programmatically. 如果打开,则可以在调试器中将其关闭(例如,在main()处中断)或以编程方式将其关闭。 This makes your program runs slower, but would show the exact PC when it faults. 这会使您的程序运行速度变慢,但在出现故障时会显示确切的PC。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM