1案例背景
最近有個(gè)客戶使用S32K146的產(chǎn)品在量產(chǎn)之后出現(xiàn)了三個(gè)售后件,ABBA測(cè)試之后的結(jié)果表明失效現(xiàn)象跟著S32K146走;同時(shí)客戶反饋說(shuō)試著將其中一個(gè)售后件重新燒錄程序,S32K146又正常工作了。結(jié)合這兩種情況,S32K146應(yīng)該是沒(méi)有損壞的,那就需要從軟件程序方面排查了。
然后和客戶的軟件工程師交流了一下,使用Attaching to Running Target的方式發(fā)現(xiàn)程序卡死在HardFault。因?yàn)槭橇慨a(chǎn)產(chǎn)品出問(wèn)題,客戶強(qiáng)烈要求去現(xiàn)場(chǎng)處理問(wèn)題,特地記錄下這次處理S32K146的hard fault問(wèn)題的過(guò)程,希望對(duì)讀者有幫助。
2方案準(zhǔn)備
在這之前,筆者還沒(méi)有處理過(guò)S32K1系列發(fā)生HardFault的問(wèn)題,所以需要先對(duì)S32K1系列發(fā)生HardFault的原因進(jìn)行了解。推薦如下這篇文章,講得非常細(xì)致。
結(jié)合上面這篇文章以及ARM官方的M4內(nèi)核文檔Cortex -M4 Devices Generic User Guide ^[1]^ ,筆者簡(jiǎn)要整理了下S32K1發(fā)生HardFault的可能原因以及排查方式,如下文所述。
2.1 HardFault(硬件錯(cuò)誤異常)
- HardFault的可能原因
- 停止調(diào)試關(guān)閉時(shí)發(fā)生了調(diào)試事件;
- UsageFault、BusFault、MemManage Fault未使能(Coretex-M4F內(nèi)核默認(rèn)狀態(tài))時(shí)發(fā)生了相應(yīng)的錯(cuò)誤導(dǎo)致錯(cuò)誤升級(jí)到HardFault;
- 異常處理過(guò)程中取內(nèi)核中斷向量表讀操作錯(cuò)誤。
- HardFault的原因排查 造成HardFault的原因,可通過(guò)SCB模塊的硬件錯(cuò)誤狀態(tài)寄存器(HFSR)進(jìn)行排查,如下所示:
- 原因1引起的,DEBUGEVT bit置1;
- 原因2引起的,F(xiàn)ORCED bit置1;
- 原因3引起的,VECTTBL bit置1。

HFSR寄存器
2.2 UsageFault(用法錯(cuò)誤異常)
- UsageFault的可能原因
- 執(zhí)行未定義指令,即非法指令;
- 指令執(zhí)行狀態(tài)錯(cuò)誤;
- 異常返回錯(cuò)誤;
- 嘗試訪問(wèn)關(guān)閉或者不可用的協(xié)處理器;
- 非對(duì)齊地址訪問(wèn)(需要先通過(guò)SCB模塊的CCR寄存器進(jìn)行使能);
- 除零操作(需要先通過(guò)SCB模塊的CCR寄存器進(jìn)行使能)。
- UsageFault的原因排查 造成UsageFault的原因,可通過(guò)SCB模塊的用法錯(cuò)誤狀態(tài)寄存器(UFSR)進(jìn)行排查,如下所示:
- 原因1引起的,UNDEFINSTR bit置1;
- 原因2引起的,INVSTATE bit置1;
- 原因3引起的,INVPC bit置1;
- 原因4引起的,NOCP bit置1;
- 原因5引起的,UNALIGNED bit置1;
- 原因6引起的,DIVBYZERO bit置1。

UFSR寄存器
2.3 BusFault(總線錯(cuò)誤異常)
BusFault的可能原因
- a. 異常/中斷入口壓棧;
- b. 異常/中斷返回出棧;
- c. 預(yù)取指;
- d. FPU lazy state現(xiàn)場(chǎng)保護(hù);
BusFault的原因排查 造成BusFault的原因,可通過(guò)SCB模塊的總線錯(cuò)誤狀態(tài)寄存器(BFSR)進(jìn)行排查,如下所示:
- 原因1.a引起的,STKERR bit置1;
- 原因1.b引起的,UNSTKERR bit置1;
- 原因1.c引起的,IBUSERR bit置1;
- 原因1.d引起的,LSPERR bit置1;
- 原因2引起的,PRECISERR bit置1;
- 原因3引起的,IMPRECISERR bit置1。

BFSR寄存器
2.4 MemManage Fault(存儲(chǔ)器管理錯(cuò)誤異常)
- MemManage Fault的可能原因
- 嘗試加載和儲(chǔ)存內(nèi)核MPU保護(hù)的地址;
- 從內(nèi)核MPU保護(hù)的地址取指;
- 由MPU違規(guī)引起的壓棧和出棧(函數(shù)調(diào)用或者中斷/異常處理)錯(cuò)誤;
- 硬件FPU lazy state保護(hù)觸發(fā)的MPU存儲(chǔ)器保護(hù)違規(guī)。
- MemManage Fault的原因排查 造成MemManage Fault的原因,可通過(guò)SCB模塊的存儲(chǔ)器管理錯(cuò)誤狀態(tài)寄存器(MMFSR)進(jìn)行排查,如下所示:
- 原因1引起的,DACCVIOL bit置1;
- 原因2引起的,IACCVIOL bit置1;
- 原因3引起的,MSTKERR或MUNSTKERR bit置1;
- 原因4引起的,MLSPERR bit置1;

MMFSR寄存器
UFSR、BFSR、MMFSR寄存器都是SCB模塊中CFSR寄存器的子寄存器,包含關(guān)系如下,實(shí)際調(diào)試時(shí)查看CFSR寄存器即可。
CFSR寄存器如果要訪問(wèn)UFSR、BFSR、MMFSR這些子寄存器,可以按照如下的地址進(jìn)行訪問(wèn):
CFSR子寄存器地址
3現(xiàn)場(chǎng)支持
了解了引起HardFault的可能原因以及排查方式之后,就是按照該方法協(xié)助客戶進(jìn)行原因排查。
3.1 現(xiàn)場(chǎng)環(huán)境
客戶的現(xiàn)場(chǎng)環(huán)境如下:
3.2 排查過(guò)程
- 打開和異常件對(duì)應(yīng)的軟件工程,使用Attach方式連接上第一個(gè)異常件的主控S32K146,如下圖所示:

- 進(jìn)入仿真界面后,暫停之后發(fā)現(xiàn)程序卡死在hard fault。
- 查看S32的SCB模塊,HFSR寄存器的FORCED bit置1,說(shuō)明是其它錯(cuò)誤上升到hard fault,需要查看CFSR寄存器了解更多信息。

- CFSR寄存器的BFARVALID bit 和PRECISERR bit都置1,說(shuō)明是精確總線錯(cuò)誤造成bus fault并且捕捉保存了精確總線錯(cuò)誤發(fā)生時(shí)的數(shù)據(jù)訪問(wèn)地址;再去查看BFAR寄存器,發(fā)生錯(cuò)誤時(shí)數(shù)據(jù)訪問(wèn)的地址是0x100010E8。

- 使用同樣的方法排查第二個(gè)異常件的主控MCU,也是精確總線錯(cuò)誤造成的bus fault,發(fā)生錯(cuò)誤時(shí)數(shù)據(jù)訪問(wèn)的地址是0x10001128。

- 接著通過(guò)IAR查看下S32K146的memory,從地址0x10001128起始的8個(gè)字節(jié)長(zhǎng)度的flash區(qū)域數(shù)據(jù)無(wú)法查看。

- 翻閱S32K1的memory相關(guān)的應(yīng)用筆記AN11983: Using the S32K1xx EEPROM Functionality – Application Note ^[2]^ ,發(fā)生錯(cuò)誤的地址屬于D-Flash,如下圖所示:

S32K1xx Memory Map
- 查閱軟件代碼中讀寫DFlash中這塊地址的函數(shù),發(fā)現(xiàn)在寫DFLASH之前雖然進(jìn)行了擦寫操作,但是并沒(méi)有設(shè)置擦寫成功之后才能寫DFlash的條件,有概率出現(xiàn)擦寫不完全的情況下寫D-Flash。同時(shí),客戶查看了其他組未出問(wèn)題的產(chǎn)品的軟件代碼,在寫D-Flash之前添加了比較多的條件判斷,包含對(duì)擦寫狀態(tài)的判斷。至此,該問(wèn)題初步得到解決,剩下的就是優(yōu)化代碼并跟進(jìn)后續(xù)產(chǎn)品的表現(xiàn)了。
4異常模擬
客戶的問(wèn)題雖然解決了,但是筆者還是不確定連續(xù)兩次對(duì)同一塊區(qū)域的Flash寫不同的值,中間沒(méi)有擦除動(dòng)作,是否會(huì)讓MCU卡在HardFault,所以使用手上的S32K144開發(fā)板進(jìn)行了該情況的模擬。
4.1 測(cè)試環(huán)境
- 開發(fā)環(huán)境:S32 Design Studio for ARM 2.2
- SDK:RTM 3.0.0
- 開發(fā)板:S32K144EVB-Q100
4.2 測(cè)試過(guò)程
- 打開S32DS 2.2,選擇自帶的例程 flash_partitioning_s32k144 。

- 將初始化模擬EEPROM的部分注釋掉,避免D-Flash被用作模擬EEPROM的備份區(qū)從而無(wú)法進(jìn)行讀寫測(cè)試。

- 定義一套新數(shù)組并儲(chǔ)存新的數(shù)據(jù)用于測(cè)試。

- 在正常的D-Flash寫之后增加寫入不同數(shù)據(jù)的操作。

- 編譯之后進(jìn)行debug,單步調(diào)試發(fā)現(xiàn)如果只進(jìn)行寫不同數(shù)據(jù)進(jìn)入D-Flash,S32K144不會(huì)進(jìn)入HardFault,需要再執(zhí)行讀D-Flash的操作,才會(huì)進(jìn)入HardFault。

如果想要了解讀取Flash地址的數(shù)據(jù)才會(huì)發(fā)生HardFault的原因。
- S32DS之所以能在控制臺(tái)顯示比較多的MCU異常信息,是因?yàn)樵谡{(diào)試器界面使能了異常捕捉功能,這部分功能依賴的是DEMCR寄存器,如下圖所示。

異常捕捉配置

DEMCR寄存器
-
ARM
+關(guān)注
關(guān)注
135文章
9498瀏覽量
388430 -
寄存器
+關(guān)注
關(guān)注
31文章
5588瀏覽量
128995 -
內(nèi)核
+關(guān)注
關(guān)注
4文章
1436瀏覽量
42470 -
軟件
+關(guān)注
關(guān)注
69文章
5295瀏覽量
90821 -
燒錄程序
+關(guān)注
關(guān)注
0文章
20瀏覽量
9610
發(fā)布評(píng)論請(qǐng)先 登錄
如何在S32K146中實(shí)現(xiàn)以下功能?
s32k146如何初始化RAM?
S32K146 UART DMA使用問(wèn)題求解
S32K146微控制器的啟動(dòng)時(shí)鐘配置在哪個(gè)文件中?
使用S32K146時(shí)想添加SCST內(nèi)核自檢代碼進(jìn)行內(nèi)核檢測(cè),要怎么實(shí)現(xiàn)?
請(qǐng)問(wèn)S32K146使用的SDK可以集成FreeRTOS10.5.1嗎?
將處理器類型從S32K144更改為S32K146,無(wú)法更改SDK是為什么?
s32k146如何識(shí)別硬故障源?
如何使用S32K146定期對(duì)單個(gè)ADC通道進(jìn)行采樣?
S32K146如何用中斷喚醒VLPS模式?
記錄一次hard fault on handler的解決過(guò)程
【S32K146 RT-thread】之 SPI驅(qū)動(dòng)適配
【S32K146 RT-Thread】之 使用SFUD組件驅(qū)動(dòng)spi flash

S32K146的hard fault問(wèn)題解決方案


評(píng)論