1案例背景
最近有個客戶使用S32K146的產品在量產之后出現了三個售后件,ABBA測試之后的結果表明失效現象跟著S32K146走;同時客戶反饋說試著將其中一個售后件重新燒錄程序,S32K146又正常工作了。結合這兩種情況,S32K146應該是沒有損壞的,那就需要從軟件程序方面排查了。
然后和客戶的軟件工程師交流了一下,使用Attaching to Running Target的方式發現程序卡死在HardFault。因為是量產產品出問題,客戶強烈要求去現場處理問題,特地記錄下這次處理S32K146的hard fault問題的過程,希望對讀者有幫助。
2方案準備
在這之前,筆者還沒有處理過S32K1系列發生HardFault的問題,所以需要先對S32K1系列發生HardFault的原因進行了解。推薦如下這篇文章,講得非常細致。
結合上面這篇文章以及ARM官方的M4內核文檔Cortex -M4 Devices Generic User Guide ^[1]^ ,筆者簡要整理了下S32K1發生HardFault的可能原因以及排查方式,如下文所述。
2.1 HardFault(硬件錯誤異常)
- HardFault的可能原因
- 停止調試關閉時發生了調試事件;
- UsageFault、BusFault、MemManage Fault未使能(Coretex-M4F內核默認狀態)時發生了相應的錯誤導致錯誤升級到HardFault;
- 異常處理過程中取內核中斷向量表讀操作錯誤。
- HardFault的原因排查 造成HardFault的原因,可通過SCB模塊的硬件錯誤狀態寄存器(HFSR)進行排查,如下所示:
- 原因1引起的,DEBUGEVT bit置1;
- 原因2引起的,FORCED bit置1;
- 原因3引起的,VECTTBL bit置1。
HFSR寄存器
2.2 UsageFault(用法錯誤異常)
- UsageFault的可能原因
- 執行未定義指令,即非法指令;
- 指令執行狀態錯誤;
- 異常返回錯誤;
- 嘗試訪問關閉或者不可用的協處理器;
- 非對齊地址訪問(需要先通過SCB模塊的CCR寄存器進行使能);
- 除零操作(需要先通過SCB模塊的CCR寄存器進行使能)。
- UsageFault的原因排查 造成UsageFault的原因,可通過SCB模塊的用法錯誤狀態寄存器(UFSR)進行排查,如下所示:
- 原因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(總線錯誤異常)
BusFault的可能原因
- a. 異常/中斷入口壓棧;
- b. 異常/中斷返回出棧;
- c. 預取指;
- d. FPU lazy state現場保護;
BusFault的原因排查 造成BusFault的原因,可通過SCB模塊的總線錯誤狀態寄存器(BFSR)進行排查,如下所示:
- 原因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(存儲器管理錯誤異常)
- MemManage Fault的可能原因
- 嘗試加載和儲存內核MPU保護的地址;
- 從內核MPU保護的地址取指;
- 由MPU違規引起的壓棧和出棧(函數調用或者中斷/異常處理)錯誤;
- 硬件FPU lazy state保護觸發的MPU存儲器保護違規。
- MemManage Fault的原因排查 造成MemManage Fault的原因,可通過SCB模塊的存儲器管理錯誤狀態寄存器(MMFSR)進行排查,如下所示:
- 原因1引起的,DACCVIOL bit置1;
- 原因2引起的,IACCVIOL bit置1;
- 原因3引起的,MSTKERR或MUNSTKERR bit置1;
- 原因4引起的,MLSPERR bit置1;
MMFSR寄存器
UFSR、BFSR、MMFSR寄存器都是SCB模塊中CFSR寄存器的子寄存器,包含關系如下,實際調試時查看CFSR寄存器即可。
CFSR寄存器如果要訪問UFSR、BFSR、MMFSR這些子寄存器,可以按照如下的地址進行訪問:
CFSR子寄存器地址
3現場支持
了解了引起HardFault的可能原因以及排查方式之后,就是按照該方法協助客戶進行原因排查。
3.1 現場環境
客戶的現場環境如下:
3.2 排查過程
- 打開和異常件對應的軟件工程,使用Attach方式連接上第一個異常件的主控S32K146,如下圖所示:
- 進入仿真界面后,暫停之后發現程序卡死在hard fault。
- 查看S32的SCB模塊,HFSR寄存器的FORCED bit置1,說明是其它錯誤上升到hard fault,需要查看CFSR寄存器了解更多信息。
- CFSR寄存器的BFARVALID bit 和PRECISERR bit都置1,說明是精確總線錯誤造成bus fault并且捕捉保存了精確總線錯誤發生時的數據訪問地址;再去查看BFAR寄存器,發生錯誤時數據訪問的地址是0x100010E8。
- 使用同樣的方法排查第二個異常件的主控MCU,也是精確總線錯誤造成的bus fault,發生錯誤時數據訪問的地址是0x10001128。
- 接著通過IAR查看下S32K146的memory,從地址0x10001128起始的8個字節長度的flash區域數據無法查看。
- 翻閱S32K1的memory相關的應用筆記AN11983: Using the S32K1xx EEPROM Functionality – Application Note ^[2]^ ,發生錯誤的地址屬于D-Flash,如下圖所示:
S32K1xx Memory Map
- 查閱軟件代碼中讀寫DFlash中這塊地址的函數,發現在寫DFLASH之前雖然進行了擦寫操作,但是并沒有設置擦寫成功之后才能寫DFlash的條件,有概率出現擦寫不完全的情況下寫D-Flash。同時,客戶查看了其他組未出問題的產品的軟件代碼,在寫D-Flash之前添加了比較多的條件判斷,包含對擦寫狀態的判斷。至此,該問題初步得到解決,剩下的就是優化代碼并跟進后續產品的表現了。
4異常模擬
客戶的問題雖然解決了,但是筆者還是不確定連續兩次對同一塊區域的Flash寫不同的值,中間沒有擦除動作,是否會讓MCU卡在HardFault,所以使用手上的S32K144開發板進行了該情況的模擬。
4.1 測試環境
- 開發環境:S32 Design Studio for ARM 2.2
- SDK:RTM 3.0.0
- 開發板:S32K144EVB-Q100
4.2 測試過程
- 打開S32DS 2.2,選擇自帶的例程 flash_partitioning_s32k144 。
- 將初始化模擬EEPROM的部分注釋掉,避免D-Flash被用作模擬EEPROM的備份區從而無法進行讀寫測試。
- 定義一套新數組并儲存新的數據用于測試。
- 在正常的D-Flash寫之后增加寫入不同數據的操作。
- 編譯之后進行debug,單步調試發現如果只進行寫不同數據進入D-Flash,S32K144不會進入HardFault,需要再執行讀D-Flash的操作,才會進入HardFault。
如果想要了解讀取Flash地址的數據才會發生HardFault的原因。
- S32DS之所以能在控制臺顯示比較多的MCU異常信息,是因為在調試器界面使能了異常捕捉功能,這部分功能依賴的是DEMCR寄存器,如下圖所示。
異常捕捉配置
DEMCR寄存器
-
ARM
+關注
關注
134文章
9259瀏覽量
372939 -
寄存器
+關注
關注
31文章
5396瀏覽量
122529 -
內核
+關注
關注
3文章
1402瀏覽量
40882 -
軟件
+關注
關注
69文章
5082瀏覽量
88708 -
燒錄程序
+關注
關注
0文章
20瀏覽量
9428
發布評論請先 登錄
相關推薦
如何在S32K146中實現以下功能?
s32k146如何初始化RAM?
S32K146 UART DMA使用問題求解
使用S32K146時想添加SCST內核自檢代碼進行內核檢測,要怎么實現?
請問S32K146使用的SDK可以集成FreeRTOS10.5.1嗎?
將處理器類型從S32K144更改為S32K146,無法更改SDK是為什么?
s32k146如何識別硬故障源?
如何使用S32K146定期對單個ADC通道進行采樣?
S32K146如何用中斷喚醒VLPS模式?
記錄一次hard fault on handler的解決過程

評論