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

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

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

ARM Cortex-M異常-HardFault INVPC置1解決方法

嵌入式那些事 ? 來(lái)源:嵌入式那些事 ? 2023-10-16 09:40 ? 次閱讀

CPUSTM32F429IGT6

對(duì)于其他的stm32芯片或者其他ARM Cortex-M芯片,其實(shí)解決方法都相通。建議先完整閱讀了本文之后,再對(duì)照著你所遇到問(wèn)題的現(xiàn)象進(jìn)行調(diào)試。

1.基礎(chǔ)知識(shí)

在ARM Cortex-M系列處理器中,有若干個(gè)系統(tǒng)異常專用于 fault 處理。CM3 中的 Faults 可分為以下幾類:

(1).總線 faults;

(2).存儲(chǔ)器管理 faults;

(3).用法 faults;

(4).硬 fault;

1.1.總線 faults

當(dāng) AHB 接口上正在傳送數(shù)據(jù)時(shí),如果回復(fù)了一個(gè)錯(cuò)誤信號(hào)(error response),則會(huì)產(chǎn)生總線faults,產(chǎn)生的場(chǎng)合可以是:

(1).取指,通常被稱作“預(yù)取流產(chǎn)”(prefetch abort);

(2).數(shù)據(jù)讀/寫(xiě),通常被稱作“數(shù)據(jù)流產(chǎn)”(data abort);

在 CM3 中,執(zhí)行如下動(dòng)作時(shí),如果地址有誤,亦會(huì)觸發(fā)總線異常:

(1).中斷處理起始階段的堆棧 PUSH 動(dòng)作。此時(shí)若發(fā)生總線 fault,則稱為“入棧錯(cuò)誤”;

(2).中斷處理收尾階段的堆棧 POP 動(dòng)作。此時(shí)若發(fā)生總線 fault,則稱為“出棧錯(cuò)誤”;

(3).在處理器啟動(dòng)中斷服務(wù)序列(sequence)后讀取向量時(shí)。這是一種極度罕見(jiàn)的特殊情況,被歸類為硬 fault。

總線 fault 狀態(tài)寄存器(BFSR),地址:0xE000_ED29,BFSR的各個(gè)位的定義如下:

8a91f8fe-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_14-13-31

1.2.存儲(chǔ)器管理 faults

存儲(chǔ)器管理 faults 多與 MPU 有關(guān),其誘因常常是某次訪問(wèn)觸犯了 MPU 設(shè)置的保護(hù)規(guī)范。另外,某些非法訪問(wèn),例如,在不可執(zhí)行的存儲(chǔ)器區(qū)域試圖取指,也會(huì)觸發(fā)一個(gè) MemManage fault,而且在這種場(chǎng)合下,即使沒(méi)有 MPU 也會(huì)觸發(fā) MemMange fault。MemManage faults 的常見(jiàn)誘因如下所示:

(1).訪問(wèn)了所有 MPU regions 覆蓋范圍之外的地址;

(2).訪問(wèn)了沒(méi)有存儲(chǔ)器與之對(duì)應(yīng)的空地址;

(3).往只讀 region 寫(xiě)數(shù)據(jù);

(4).用戶級(jí)下訪問(wèn)了只允許在特權(quán)級(jí)下訪問(wèn)的地址;

存儲(chǔ)器管理 fault 狀態(tài)寄存器(MFSR),地址:0xE000_ED28,MFSR的各個(gè)位的定義如下:

8ab019ce-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_14-19-19

1.3.用法 faults

用法 faults 發(fā)生的場(chǎng)合可以是:

(1).執(zhí)行了協(xié)處理器指令。Cortex-M3 本身并不支持協(xié)處理器,但是通過(guò) fault 異常機(jī)制,可以建立一套“軟件模擬”的機(jī)制,來(lái)執(zhí)行一段程序模擬協(xié)處理器的功能,從而可以方便地在其它 Cortex 處理器間移植。

(2).執(zhí)行了未定義的指令。同上一點(diǎn)的道理,亦可以軟件模擬未定義指令的功能。

(3).嘗試進(jìn)入 ARM 狀態(tài)。因?yàn)?CM3 不支持 ARM 狀態(tài),所以用法 fault 會(huì)在切換時(shí)產(chǎn)生。軟件可以利用此機(jī)制來(lái)測(cè)試某處理器是否支持 ARM 狀態(tài)。

(4).無(wú)效的中斷返回(LR 中包含了無(wú)效/錯(cuò)誤的值);

(5).使用多重加載/存儲(chǔ)指令時(shí),地址沒(méi)有對(duì)齊。

另外,如果需要嚴(yán)格要求程序的質(zhì)量,還可以讓 CM3 在遇到除數(shù)為零的時(shí)候,以及遇到未對(duì)齊訪問(wèn)的時(shí)候也產(chǎn)生用法 fault。在 NVIC 中有兩個(gè)控制位分別與它們對(duì)應(yīng)。通過(guò)設(shè)置這兩個(gè)控制位,就可以激活它們。

用法 fault 狀態(tài)寄存器(UFSR),地址:0xE000_ED2A,UFSR的各個(gè)位的定義如下:

8ad56bac-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_14-24-49

1.4.硬 fault

硬 fault 是上文討論的總線 fault、存儲(chǔ)器管理 fault 以及用法 fault 上訪的結(jié)果。如果這些 fault 的服務(wù)例程無(wú)法執(zhí)行,它們就會(huì)成為“硬傷” ——上訪( escalation)成硬 fault。另外,在取向量(異常處理時(shí)對(duì)異常向量表的讀?。r(shí)產(chǎn)生的總線 fault 也按硬 fault 處理。在 NVIC中有一個(gè)硬 fault 狀態(tài)寄存器(HFSR),它指出產(chǎn)生硬 fault 的原因。如果不是由于取向量造成的,則硬 fault 服務(wù)例程必須檢查其它的 fault 狀態(tài)寄存器,以最終決定是誰(shuí)上訪的。

硬 fault 狀態(tài)寄存器(HFSR),地址:0xE000_ED2C,HFSR的各個(gè)位的定義如下:

8af02898-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_14-29-38

2.UsageFault INVPC置1解決過(guò)程

最近在使用RTOS增加DMA驅(qū)動(dòng)時(shí),在對(duì)內(nèi)存到設(shè)備和設(shè)備到內(nèi)存的DMA傳輸測(cè)試時(shí),出現(xiàn)了UsageFault,并且UFSR中的INVPC置1了。最開(kāi)始,單獨(dú)測(cè)試DMA發(fā)送是沒(méi)有問(wèn)題的,但是DMA發(fā)送和接收一起測(cè)試時(shí),就會(huì)出現(xiàn)UsageFault(INVPC置1)。這個(gè)異常不太好定位出現(xiàn)問(wèn)題的具體位置,因此就檢查DMA驅(qū)動(dòng),并且逐步調(diào)試吧。最終,DMA驅(qū)動(dòng)檢查和修改好了,仍然出現(xiàn)UsageFault,實(shí)在沒(méi)法了,還是從為什么會(huì)出現(xiàn)UsageFault(INVPC置1)開(kāi)始分析吧。

2.1.出現(xiàn)UsageFault(INVPC置1)的原因

如果LR中的EXC_RETURN不是合法的值(合法值見(jiàn)下圖,包括企圖返回ARM狀態(tài)),則引起用法fault。如果用法fault被除能,也上訪成硬fault。此時(shí),用法Fault狀態(tài)寄存器(UFSR,地址:0xE000_ED2A)中的INVPC位(位偏移:2),或者是INVSTATE位(位偏移:1)置位。

8b0478de-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_15-13-23

上面就是出現(xiàn)該異常的文字分析了。

2.2.UsageFault(INVPC置1)的解決過(guò)程

因?yàn)樵摦惓J钱惓m憫?yīng)期間才可能出現(xiàn)的異常(<> 9.8節(jié)介紹了下,在9.8.4節(jié)進(jìn)行文字說(shuō)明),因此,只要在異常或中斷的返回處打斷點(diǎn),執(zhí)行下一步就有可能進(jìn)入U(xiǎn)sageFault異常。(當(dāng)然了這個(gè)方法,是比較笨的,不過(guò)在縮小了異常出現(xiàn)的范圍之后,可以在每次異?;蛑袛嗟姆祷靥幋驍帱c(diǎn),然后執(zhí)行下一步,就有可能進(jìn)入U(xiǎn)sageFault異常)

我這里是每次開(kāi)始DMA測(cè)試之后,就進(jìn)入U(xiǎn)sageFault異常,并且我的系統(tǒng)中目前就打開(kāi)了SysTick,PendSV,DMA1_STREAM5,DMA1_STREAM6,NMI,HardFault,MemFault,BusFault,UsageFault這些異常和中斷。因此我在開(kāi)始DMA測(cè)試的時(shí)候打一個(gè)斷點(diǎn),在程序運(yùn)行到DMA測(cè)試開(kāi)始的斷點(diǎn)處時(shí),再在DMA1_STREAM5,DMA1_STREAM6,NMI,HardFault,MemFault,BusFault,UsageFault這些函數(shù)的入口打斷點(diǎn),在PendSV的返回處打斷點(diǎn),SysTick就暫時(shí)先不管。然后全力運(yùn)行,發(fā)現(xiàn)每次都會(huì)在PendSV的異常返回?cái)帱c(diǎn)處停留(因?yàn)槿蝿?wù)切換嘛)總共在PendSV的斷點(diǎn)處停留了大概7到8次,就進(jìn)入到了UsageFault。

有了上面步驟的鋪墊,先去除中斷和異常中的斷點(diǎn),還是先在DMA測(cè)試開(kāi)始處打斷點(diǎn),等運(yùn)行到DMA測(cè)試開(kāi)始處,再在上述的中斷和異常相關(guān)位置打斷點(diǎn)。接下來(lái)我就慢慢的調(diào)試,在開(kāi)始DMA測(cè)試之后,全速運(yùn)行,在退出PendSV異常時(shí),執(zhí)行單步運(yùn)行到下一步,重復(fù)7到8次,從PendSV就進(jìn)入了UsageFault,在這7到8次中,我看在退出PendSV時(shí),LR寄存器中的值都是0xFFFFFFFD,是合法的啊,當(dāng)時(shí)仔細(xì)一想,有可能是退出異常時(shí)硬件再將堆棧中的PC賦值給PC時(shí)出問(wèn)題,導(dǎo)致進(jìn)入了UsageFault。果不其然,在PenSV退出之前,我查看每個(gè)PSP(0xFFFFFFFD:返回線程模式,并使用線程堆棧)對(duì)應(yīng)內(nèi)存數(shù)值,能夠正常退出PendSV的寄存器和PSP堆棧內(nèi)容如下圖所示:

8b177ca4-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_16-38-20

8b23d8e6-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_16-43-28

進(jìn)入U(xiǎn)sageFault異常之前的寄存器和PSP堆棧內(nèi)容如下圖所示:

8b3b8dc4-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_16-45-35

8b4808ec-6a69-11ee-939d-92fbcf53809c.png

Snipaste_2020-12-11_16-47-17

此處堆棧中的內(nèi)容,明顯的0x20003D94堆棧中的PC值是有問(wèn)題的,我的程序是燒寫(xiě)到flash中的PC地址應(yīng)該是08xxxxxx,然而現(xiàn)在堆棧中的PC地址是0x20003DA8,這個(gè)地址是SRAM中的地址,SRAM存儲(chǔ)的數(shù)據(jù)而不是代碼,出現(xiàn)這個(gè)問(wèn)題的原因,猜想一下,應(yīng)該就是任務(wù)堆棧溢出導(dǎo)致,當(dāng)我增加任務(wù)堆棧的大小之后,哈哈,程序正常運(yùn)行,世界是如此美好。

3.調(diào)試小結(jié)

3.1.解決過(guò)程小結(jié)

其實(shí)上面的步驟2,是我自己的一個(gè)調(diào)試解決問(wèn)題的過(guò)程,這里給大家提供一個(gè)比較直接的解決方式。在開(kāi)始運(yùn)行程序之前,直接在UsageFault異常入口函數(shù)中打一個(gè)斷點(diǎn),然后全速運(yùn)行程序,等程序停止在UsageFault異常函數(shù)的斷點(diǎn)處時(shí),需要注意以下幾點(diǎn):

(1).如果LR是合法值,那么根據(jù)LR判斷退出異常時(shí)使用的堆棧,然后在Memory查看窗口中,查看堆棧中R0,R1,R2,R3,R12,LR,PC,xPSR這些寄存器的值,根據(jù)這些寄存器的值,判斷是否是堆棧溢出導(dǎo)致該異常發(fā)生;如果不是堆棧溢出導(dǎo)致該異常發(fā)生,那么就要根據(jù)PC值,在匯編窗口中跳轉(zhuǎn)到PC值對(duì)應(yīng)的代碼處,分析導(dǎo)致異常發(fā)生的原因;

(2).如果LR不是合法值,就要分析下你的代碼中,有哪些地方修改過(guò)LR的值,確保修改的值要是合法的。

3.2.關(guān)于UsageFault 如何才能讓INVPC置1

(1).在退出異?;蛑袛鄷r(shí),執(zhí)行BX LR時(shí),LR的值是非法的,此時(shí)就會(huì)觸發(fā)UsageFault異常,并且INVPC置1。

(2).在退出異?;蛑袛鄷r(shí),執(zhí)行BX LR時(shí),LR的值是合法的,但是退出異常之后要使用的堆棧中,堆棧里面的PC值是有問(wèn)題的,此時(shí)就有可能觸發(fā)UsageFault異常,并且INVPC置1。

對(duì)于上面的兩點(diǎn)的模擬其實(shí)也比較好做,在PendSV或者其他異常的退出的地方打一個(gè)斷點(diǎn),然后手動(dòng)修改LR或者堆棧中PC的值,就能觸發(fā)UsageFault異常,并且INVPC置1。這里注意一下,修改堆棧中PC的值,我這里測(cè)試時(shí)候,設(shè)置PC值為其他值可能引起其他的異常,貌似修改PC的值為RAM中數(shù)據(jù)區(qū)的地址才會(huì)出現(xiàn)該異常,不太清楚為什么會(huì)這樣,可能是數(shù)據(jù)區(qū)是沒(méi)有執(zhí)行代碼的權(quán)限,因此出異常吧,不太確定,有知道的朋友,歡迎留言講解。








審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(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)投訴
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9027

    瀏覽量

    366479
  • 存儲(chǔ)器
    +關(guān)注

    關(guān)注

    38

    文章

    7430

    瀏覽量

    163515
  • 中斷處理
    +關(guān)注

    關(guān)注

    0

    文章

    94

    瀏覽量

    10947
  • Cortex-M
    +關(guān)注

    關(guān)注

    2

    文章

    227

    瀏覽量

    29708
  • STM32芯片
    +關(guān)注

    關(guān)注

    0

    文章

    38

    瀏覽量

    4356

原文標(biāo)題:ARM Cortex-M 異常-HardFault(UsageFault) INVPC置1解決過(guò)程

文章出處:【微信號(hào):嵌入式那些事,微信公眾號(hào):嵌入式那些事】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(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)行
    發(fā)表于 08-17 09:44

    ARM Cortex-M處理器詳解 精選資料分享

    Cortex-M 系列處理器的指令集和高級(jí)中斷處理能力,以及 SoC系統(tǒng)級(jí)特性,調(diào)試和追蹤功能和性能的比較?! ?b class='flag-5'>1、簡(jiǎn)介  今天, ARM Cortex-M 處理器家族有8款處理器成員
    發(fā)表于 07-16 07:57

    ARM Cortex-M堆棧機(jī)制介紹

      大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是ARM Cortex-M堆棧機(jī)制?! 〗裉旖o大家分享的這篇依舊是2016年之前痞子衡寫(xiě)的技術(shù)文檔,花了點(diǎn)時(shí)間重新編排了一下
    發(fā)表于 12-16 06:26

    ARM Cortex-M內(nèi)核的相關(guān)資料推薦

      大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是ARM Cortex-M功能模塊,不過(guò)側(cè)重點(diǎn)是三款安全特性處理器?! ?b class='flag-5'>ARM Cortex-M處理器家族發(fā)展至今(2
    發(fā)表于 12-27 07:21

    ARM cortex-M上出現(xiàn)HardFault后如何排查呢

    ARM cortex-M上面的fault想必大家都不陌生,我相信還沒(méi)有誰(shuí)從來(lái)沒(méi)有出現(xiàn)過(guò)fault。但出現(xiàn)fault后如何排查,相信很多人都是一籌莫展。在我的項(xiàng)目中加了一些代碼,F(xiàn)ault 后可以打印
    發(fā)表于 06-27 14:35

    如何使用Ozone分析Cortex-M故障?

    錯(cuò)誤的存儲(chǔ)指令??偨Y(jié)Cortex-M處理器異常包含:(1)HardFault異常,是缺省異常,固
    發(fā)表于 09-23 11:26

    ARM Cortex-M 系列微控制器(ST)

    ARM Cortex-M 系列微控制器(ST) 意法半導(dǎo)體(ST)宣布在基于ARM Cortex-M系列處理器內(nèi)核的微控制器研發(fā)項(xiàng)目上取得突破,推出全球業(yè)內(nèi)首款采用90nm技術(shù)嵌入式
    發(fā)表于 11-02 09:29 ?941次閱讀

    ARM白皮書(shū)】ARM Cortex-M處理器入門(mén)

    ARM Cortex-M處理器家族現(xiàn)在有8款處理器成員。在本文中,會(huì)比較Cortex-M系列處理器之間的產(chǎn)品特性,重點(diǎn)講述如何根據(jù)產(chǎn)品應(yīng)用選擇正確的Cortex-M處理器。本文中會(huì)詳細(xì)
    發(fā)表于 04-20 15:34 ?39次下載

    傳統(tǒng)的單片機(jī)和ARM較量 助推MCU踏上高端Cortex-M市場(chǎng)

    據(jù)有關(guān)市場(chǎng)調(diào)研機(jī)構(gòu)稱,基于ARM Cortex-M內(nèi)核的MCU在2010年創(chuàng)紀(jì)錄地實(shí)現(xiàn)了100%的出貨量增長(zhǎng)。而整個(gè)MCU市場(chǎng)才增長(zhǎng)了37%。MCU市場(chǎng)的增長(zhǎng)也幾乎是來(lái)自于ARM Cortex
    發(fā)表于 04-28 10:00 ?1582次閱讀

    Atmel Studio 6軟件中如何調(diào)試ARM Cortex-M

    Atmel Studio 6軟件中如何調(diào)試ARM Cortex-M
    的頭像 發(fā)表于 07-04 10:49 ?4204次閱讀

    米爾科技Cortex-M Prototyping System +介紹

    ARM? Cortex?-M原型系統(tǒng) MPS2+,為Cortex-M 系列微處理器設(shè)計(jì)的原型驗(yàn)證評(píng)估系統(tǒng),包含最新的Cortex-M7 及
    的頭像 發(fā)表于 11-14 10:45 ?1825次閱讀
    米爾科技<b class='flag-5'>Cortex-M</b> Prototyping System +介紹

    Cortex-MCortex-A認(rèn)識(shí)ARM處理器

    Cortex-MCortex-A認(rèn)識(shí)ARM處理器
    的頭像 發(fā)表于 03-08 11:34 ?3395次閱讀

    AN028 Cortex-M3內(nèi)核HardFault錯(cuò)誤調(diào)試定位方法

    AN028 Cortex-M3內(nèi)核HardFault錯(cuò)誤調(diào)試定位方法
    發(fā)表于 02-27 18:32 ?0次下載
    AN028 <b class='flag-5'>Cortex-M</b>3內(nèi)核<b class='flag-5'>HardFault</b>錯(cuò)誤調(diào)試定位<b class='flag-5'>方法</b>

    分析ARM Cortex-M內(nèi)核復(fù)位啟動(dòng)過(guò)程

    ARM Cortex-M內(nèi)核的復(fù)位啟動(dòng)過(guò)程也被稱為復(fù)位序列(Reset sequence),下面就來(lái)簡(jiǎn)要總結(jié)分析下這一過(guò)程。
    的頭像 發(fā)表于 03-20 09:58 ?2215次閱讀

    Cortex-M 內(nèi)核中斷/異常系統(tǒng)、中斷優(yōu)先級(jí)/嵌套 詳解

    Cortex-M 內(nèi)核中斷/異常系統(tǒng)、中斷優(yōu)先級(jí)/嵌套 詳解
    的頭像 發(fā)表于 09-27 15:29 ?1930次閱讀
    <b class='flag-5'>Cortex-M</b> 內(nèi)核中斷/<b class='flag-5'>異常</b>系統(tǒng)、中斷優(yōu)先級(jí)/嵌套 詳解