0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ES32F36xx芯片發(fā)生HardFault異常時(shí)的函數(shù)調(diào)用關(guān)系及問(wèn)題定位

jf_pJlTbmA9 ? 來(lái)源:東軟載波微電子 ? 作者:東軟載波微電子 ? 2023-11-06 17:13 ? 次閱讀

1、引言

Cortex-M3微控制器因其功能強(qiáng)大、性價(jià)比高以及易用性好,在嵌入式體系結(jié)構(gòu)中得到了廣泛應(yīng)用。然而,在實(shí)際開(kāi)發(fā)過(guò)程中,如果程序很大或運(yùn)行很久后可能會(huì)遇到HardFault異常。為了快速有效地解決HardFault異常,本文將討論定位HardFault問(wèn)題的方法。

2、常見(jiàn)引發(fā)HardFault原因

1)訪問(wèn)非法內(nèi)存地址:編程中處理指針時(shí)可能導(dǎo)致訪問(wèn)未定義的內(nèi)存地址,特別是在數(shù)組越界、非法指針解引用等情況下。

2)疊棧溢出:程序運(yùn)行過(guò)程中如果棧溢出,會(huì)導(dǎo)致棧上數(shù)據(jù)錯(cuò)誤,從而引發(fā)異常。

3)寄存器未正確初始化:寄存器配置和使用不正確,可能導(dǎo)致硬件異常。

4)除0運(yùn)算:當(dāng)程序試圖執(zhí)行除0運(yùn)算時(shí),可能發(fā)生硬件故障異常。

5)總線錯(cuò)誤:外設(shè)總線通信發(fā)生錯(cuò)誤,可能引起硬件故障。

3、軟件觸發(fā)HardFault異常

ES32F36xx是Cortex-M3內(nèi)核,當(dāng)被除數(shù)為0時(shí),硬件將觸發(fā)一個(gè)異常,導(dǎo)致系統(tǒng)進(jìn)入Hard Fault異常狀態(tài)。這種情況下,處理器不能正常運(yùn)行,并且不能恢復(fù),直到硬件或軟件采取措施使得系統(tǒng)回到正常狀態(tài)。在ES32_SDK中,ES32F36xx 的KEY_LED_ADC例程中增加如下程序:

//B函數(shù)
voidB_Function(void)
{
printf_e("EnterBfunctionrn");
C_Function(0);
printf_e("ExitBfunctionrn");
}
//A函數(shù)
voidA_Function(void)
{
printf_e("EnterAfunctionrn");
B_Function();
printf_e("ExitAfunctionrn");
}
//C函數(shù)
intC_Function(intval)
{
return100/val;
}
//D函數(shù)
voidD_Function(void)
{
printf_e("EnterDfunctionrn");
C_Function(1);
printf_e("ExitDfunctionrn");
}
//TestDebug函數(shù)
voidTestDebug(void)
{
//使能除0異常
volatileint*CCR=(volatileint*)0xE000ED14;
*CCR|=(1<

如圖 1所示,工程文件中,User選項(xiàng)中增加“fromelf -a -c --output=all.dis .objout.axf“,生成匯編文件。

wKgaomUDxBeAK4_TAAEfG65R5WU979.png

圖1 MDK工程生成匯編文件配置

4、HardFault異常函數(shù)調(diào)用關(guān)系及問(wèn)題定位

上述程序運(yùn)行過(guò)程中會(huì)發(fā)生hardfault異常,發(fā)生hardfault異常瞬間,程序立刻中止運(yùn)行,硬件自動(dòng)保存“調(diào)用者保存寄存器“的值到棧,同時(shí)跳轉(zhuǎn)到異常向量表執(zhí)行異常處理函數(shù)。如圖 2所示為發(fā)生異常瞬間,硬件自動(dòng)保存xPSR、ReturnAddress、LR、R12、R3、R2、R1及R0寄存器。

wKgZomUDxBiAGc5uAACAI7BbLss327.png

圖2 處理器進(jìn)入異常時(shí)的棧幀

硬件僅保存了部分寄存器,為了保存發(fā)生異常瞬間所有寄存器值,程序跳轉(zhuǎn)到中斷向量處需要執(zhí)行如下的匯編代碼:

;getcurrentcontext
TSTlr,#0x04;if(!EXC_RETURN[2])
ITEEQ
;[2]=0==>Z=1,getfaultcontextfromhandler
MRSEQr0,msp
;[2]=1==>Z=0,getfaultcontextfromthread
MRSNEr0,psp

STMFDr0!,{r4-r11};pushr4-r11register
STMFDr0!,{lr};將EXC_RETURN值壓棧

TSTlr,#0x04;if(!EXC_RETURN[2])
ITEEQ
;R0為棧值,作為hw_hardfault_exception函數(shù)首個(gè)參數(shù)
MSREQmsp,r0
;[2]=1==>Z=0,getfaultcontextfromthread
MSRNEpsp,r0

;再次將EXC_RETURN值壓棧
PUSH{lr}
;跳轉(zhuǎn)至hw_hardfault_exception函數(shù)
BLhw_hardfault_exception
POP{lr}
ORRlr,lr,#0x04
BXlr
ENDP

上述匯編代碼的主要功能是獲取棧(SP)地址,并將R4 ~ R11壓棧,跳轉(zhuǎn)執(zhí)行hw_hardfault_exception函數(shù)。壓棧后棧中的數(shù)據(jù)情況如圖 3所示:

wKgaomUDxBmAcZlKAAAQVJsR_nw292.png

圖3 hardfault異常瞬間棧中完整寄存器

Return Address是發(fā)生異常指令點(diǎn),LR是發(fā)生異常指令所在函數(shù)的下一條指令地址。在hw_hardfault_exception函數(shù)中將棧中的寄存器值都通過(guò)串口打印出來(lái)。

voidhw_hardfault_exception(structexception_info*exception_info)
{
uint32_t*app_sp=NULL;
inti=0;
/*sp指向發(fā)生hardfault前棧地址*/
app_sp=(uint32_t*)(exception_info+1);/*context+16*4*/

printf_e("psr:0x%08xrn",exception_info->psr);
printf_e("r00:0x%08xrn",exception_info->r0);
printf_e("r01:0x%08xrn",exception_info->r1);
printf_e("r02:0x%08xrn",exception_info->r2);
printf_e("r03:0x%08xrn",exception_info->r3);
printf_e("r04:0x%08xrn",exception_info->r4);
printf_e("r05:0x%08xrn",exception_info->r5);
printf_e("r06:0x%08xrn",exception_info->r6);
printf_e("r07:0x%08xrn",exception_info->r7);
printf_e("r08:0x%08xrn",exception_info->r8);
printf_e("r09:0x%08xrn",exception_info->r9);
printf_e("r10:0x%08xrn",exception_info->r10);
printf_e("r11:0x%08xrn",exception_info->r11);
printf_e("r12:0x%08xrn",exception_info->r12);
printf_e("lr:0x%08xrn",exception_info->lr);
printf_e("pc:0x%08xrn",exception_info->pc);

printf_e("stacks:rn");

for(i=0;i

在hw_hardfault_handler函數(shù)中打印出了所有相關(guān)寄存器,如圖 4所示:

wKgZomUDxByABKeUAAGrKbriSUo660.png

圖4 發(fā)生異常時(shí)棧數(shù)據(jù)

從打出來(lái)的返回地址值(PC)為0x00000644,在生成的all.dis匯編文件搜索該地址,如圖 5所示,該地址是C_Function函數(shù)中的一個(gè)除法指令,R0寄存器值除以R1寄存器值,并將結(jié)果存放R0中。R0為0x64,確認(rèn)R1寄存器值即可。

wKgaomUDxB2AeAsNAABnyZlmSdg999.png

圖5 發(fā)生hardfault異常瞬間執(zhí)行的指令

圖 4中,LR的值為0x0000060f,all.dis無(wú)法搜索到該地址。由于Cortex-M3使用的是Thumb指令集,bit0置位指示該地址地址指令是Thumb指令。bit0復(fù)位,搜索0x0000060e,如圖 6所示,該地址在B_Function函數(shù)中。B_Function函數(shù)調(diào)用了C_Function函數(shù),R0為傳遞的參數(shù)0。由此可知,圖 5中,R1的除數(shù)值0,故程序會(huì)發(fā)生hardfault異常。

wKgZomUDxB-AdZjCAADELUA_Ks8798.png

圖6 B_Function函數(shù)的匯編代碼

圖 6中,調(diào)用C_Function函數(shù)前,R4和LR寄存器被壓入了棧中。即圖 7中,LR的值為0x000005D1,R4的值為0xe000ed14。

wKgaomUDxCCAR4KWAADcafAHGSY602.png

圖 7 B_Function函數(shù)壓棧值

如圖 8所示,在all.dis文件搜索0x000005D0地址在A_Function函數(shù)中,在執(zhí)行A_Function函數(shù)前,對(duì)R4和LR進(jìn)行了壓棧。A_Function函數(shù)調(diào)用了B_Function函數(shù)。

wKgZomUDxCGAUMNiAAC3dEkj5O4879.png

圖 8 A_Function函數(shù)匯編代碼

如圖 9所示,A_Function函數(shù)壓入的R4值為0xe000ed14,LR值為0x000006a1。

wKgaomUDxCKAV_lzAAEG1TGFmCY233.png

圖 9 A_Function函數(shù)壓棧值

如圖 10,在all.dis文件中,搜索0x000006a0,發(fā)現(xiàn)該地址在TestDebug函數(shù)中,且該函數(shù)將R4和LR壓入棧中。

wKgZomUDxCWAeGnWAACnRuXnAWk374.png

圖 10 TestDebug函數(shù)匯編代碼

如圖 11所示,A_Function函數(shù)壓入的R4值為0xe0001c18,LR值為0x00001ab9。

wKgZomUDxCaAKLWLAADHbLwMPJ4442.png

圖 11 TestDebug函數(shù)壓棧值

如圖 12所示,在all.dis文件中,搜索0x00001ab8,該地址在main函數(shù)中。

wKgZomUDxCiAZCblAABe4kBCRpI591.png

圖 12 main函數(shù)的匯編代碼

至此,如圖 13所示為發(fā)生hardfault異常時(shí)函數(shù)的調(diào)用關(guān)系,在C_Function函數(shù)中,被除數(shù)為0是導(dǎo)致進(jìn)入hardfault異常的原因。

wKgaomUDxCmADZmHAAALmSLOJcA155.png

圖 13 發(fā)生hardfault時(shí)的函數(shù)調(diào)用關(guān)系

來(lái)源:東軟載波微電子

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 微控制器
    +關(guān)注

    關(guān)注

    48

    文章

    7394

    瀏覽量

    150629
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5268

    瀏覽量

    119646
  • 程序
    +關(guān)注

    關(guān)注

    115

    文章

    3743

    瀏覽量

    80661
  • Cortex-M3
    +關(guān)注

    關(guān)注

    9

    文章

    269

    瀏覽量

    59379
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【轉(zhuǎn)載】快速追蹤和定位產(chǎn)生HardFault原因的方法

    AN0028—快速追蹤和定位產(chǎn)生HardFault原因的方法概述在使用ARM Cortex-M 系列 MCU時(shí)(如AT32 MCU),有時(shí)會(huì)出現(xiàn)程序運(yùn)行異常。當(dāng)通過(guò)編譯器在debug模式查原因
    發(fā)表于 08-17 09:44

    靈動(dòng)微課堂 (第173講) | HardFault定位方法和步驟

    根據(jù)上述的定位手段可以查找是哪一種情況造成的異常,在編程過(guò)程中需要避免出現(xiàn)上述異常情況,但是在惡劣復(fù)雜的環(huán)境下,可能會(huì)小概率觸發(fā)HardFault中斷,可以在
    發(fā)表于 07-02 15:20

    STM32F101xx和STM32F103xx固件函數(shù)庫(kù)

    STM32F101xx和STM32F103xx固件函數(shù)庫(kù)函數(shù)使用說(shuō)明手冊(cè),開(kāi)發(fā)必備工具!
    發(fā)表于 10-29 11:10 ?58次下載

    S32K1XX調(diào)試--快速定位HardFault

    1、背景程序運(yùn)行,發(fā)現(xiàn)程序跑飛到HardFault,但不清楚為什么會(huì)跑到HardFault中斷處理函數(shù)去。2、分析要想知道為什么會(huì)跑到HardFault_Handler中去,就很有必要
    發(fā)表于 12-03 15:21 ?5次下載
    S32K1<b class='flag-5'>XX</b>調(diào)試--快速<b class='flag-5'>定位</b><b class='flag-5'>HardFault</b>

    ES32F36xx USB例程應(yīng)用筆記

    電子發(fā)燒友網(wǎng)站提供《ES32F36xx USB例程應(yīng)用筆記.pdf》資料免費(fèi)下載
    發(fā)表于 09-22 11:02 ?2次下載
    <b class='flag-5'>ES32F36xx</b> USB例程應(yīng)用筆記

    ES32F36xx Bootloader應(yīng)用筆記

    電子發(fā)燒友網(wǎng)站提供《ES32F36xx Bootloader應(yīng)用筆記.pdf》資料免費(fèi)下載
    發(fā)表于 09-22 11:01 ?0次下載
    <b class='flag-5'>ES32F36xx</b> Bootloader應(yīng)用筆記

    ES32F36xx應(yīng)用筆記

    電子發(fā)燒友網(wǎng)站提供《ES32F36xx應(yīng)用筆記.pdf》資料免費(fèi)下載
    發(fā)表于 09-22 10:59 ?1次下載
    <b class='flag-5'>ES32F36xx</b>應(yīng)用筆記

    ES022 STM32F05xx,STM32F107xx勘誤手冊(cè)

    ES022 STM32F05xx,STM32F107xx勘誤手冊(cè)
    發(fā)表于 11-23 20:31 ?0次下載
    <b class='flag-5'>ES</b>022 STM32<b class='flag-5'>F05xx</b>,STM32<b class='flag-5'>F107xx</b>勘誤手冊(cè)

    ES0022_STM32F105xx和STM32F107xx單片機(jī)的局限性

    ES0022_STM32F105xx和STM32F107xx單片機(jī)的局限性
    發(fā)表于 11-23 20:36 ?0次下載
    <b class='flag-5'>ES0022_STM32F105xx</b>和STM32<b class='flag-5'>F107xx</b>單片機(jī)的局限性

    ES0321_STM32F496xx和STM32F4A6xx單片機(jī)的局限性

    ES0321_STM32F496xx和STM32F4A6xx單片機(jī)的局限性
    發(fā)表于 11-23 20:36 ?0次下載
    <b class='flag-5'>ES0321_STM32F496xx</b>和STM32<b class='flag-5'>F4A6xx</b>單片機(jī)的局限性

    ES0321_STM32F469xx和STM32F479xx單片機(jī)的局限性

    ES0321_STM32F469xx和STM32F479xx單片機(jī)的局限性
    發(fā)表于 11-23 20:37 ?0次下載
    <b class='flag-5'>ES0321_STM32F469xx</b>和STM32<b class='flag-5'>F479xx</b>單片機(jī)的局限性

    AT32講堂009 | 基于CmBacktrace庫(kù),如何快速追蹤和定位產(chǎn)生HardFault的原因

    概述在使用ARMCortex-M系列MCU時(shí)(如AT32MCU),有時(shí)會(huì)出現(xiàn)程序運(yùn)行異常。當(dāng)通過(guò)編譯器在debug模式查原因時(shí),會(huì)發(fā)現(xiàn)程序跑到HardFault_Handler函數(shù)中,產(chǎn)生
    的頭像 發(fā)表于 06-15 10:44 ?3658次閱讀
    AT32講堂009 | 基于CmBacktrace庫(kù),如何快速追蹤和<b class='flag-5'>定位</b>產(chǎn)生<b class='flag-5'>HardFault</b>的原因

    ES32F36xx芯片發(fā)生HardFault異常時(shí)的函數(shù)調(diào)用關(guān)系及問(wèn)題定位

    Cortex-M3微控制器因其功能強(qiáng)大、性價(jià)比高以及易用性好,在嵌入式體系結(jié)構(gòu)中得到了廣泛應(yīng)用。然而,在實(shí)際開(kāi)發(fā)過(guò)程中,如果程序很大或運(yùn)行很久后可能會(huì)遇到HardFault異常。
    的頭像 發(fā)表于 06-20 09:30 ?676次閱讀
    <b class='flag-5'>ES32F36xx</b><b class='flag-5'>芯片</b><b class='flag-5'>發(fā)生</b><b class='flag-5'>HardFault</b><b class='flag-5'>異常</b>時(shí)的<b class='flag-5'>函數(shù)</b><b class='flag-5'>調(diào)用</b><b class='flag-5'>關(guān)系</b>及問(wèn)題<b class='flag-5'>定位</b>

    一個(gè)地址未對(duì)齊引起的HardFault異常

    一個(gè)地址未對(duì)齊引起的 HardFault 異常
    的頭像 發(fā)表于 09-18 10:57 ?665次閱讀
    一個(gè)地址未對(duì)齊引起的<b class='flag-5'>HardFault</b><b class='flag-5'>異常</b>

    python函數(shù)函數(shù)之間的調(diào)用

    函數(shù)函數(shù)之間的調(diào)用 3.1 第一種情況 程序代碼如下: def x ( f ): def y (): print ( 1 ) return y def
    的頭像 發(fā)表于 10-04 17:17 ?528次閱讀