簡體   English   中英

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

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

我是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;

通過您發布的代碼,我看不到您的硬件故障源。 但是,可以通過檢查堆棧來找到硬故障的來源。 進入硬故障時,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以了解發生了什么。 在手冊中查看這些位的含義。

第一步是確定故障時的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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM