1
votes

I am new in C embedded. Debugging an embedded system for image camera tracking I get the following HardFaultHandler:

The Atollic Debug stops it at this point without apparently indications of specific errors.

__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;
2
Why tag eclipse? - Duck Dodgers
Probably the IDE that the OP is using. - S.S. Anne
so as you commented out this code or used other debug techniques to narrow in on the offending line, what did you see? How much further does this code reduce and still break? - old_timer

2 Answers

3
votes

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. 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.

EDIT: Forget to mention: You should first look into the SCB->CSFR to understand what happened. Look in the handbook what the bits mean.

1
votes

The first step is to determine what is the PC value when it faults. In your "DefaultHardFaultHandle", notice:

" 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. 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. The last two instructions jump to a new routine HardwareFaultHandler_GetSP. In other word, if you were to write a C signature for HardwareFaultHandler_GetSP, it would look like this:

void HardwareFaultHandler_GetSP(uint32_t *sp);

You should be able to drill down using the debugger to find the faulting PC. e.g. stepping through DefaultHardFaultHandle, once it obtains the SP into R0, then look at the R0's value. Let's say it is 0x20004000. Then use a memory window, look at the address 0x20004000+0x18, or 0x20004018. That contains the PC where it faults.

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.

NOTE the PC may be off by one or two instructions due to caching. The IMPRECISERR bit (bit 2) in the BusFault Status Register (or BFSR, which is byte accessible at address 0xE000ED29) controls this behavior. If it is on, you can turn it off in the debugger (e.g. when you break at main()) or programmatically. This makes your program runs slower, but would show the exact PC when it faults.