一、什麼是Hard Fault
1、在嵌入式系統中,Hard Fault是指執行一條非法的或無效的指令所導致發生的硬件異常錯誤。
2、出現Hard Fault的原因可能是內存訪問異常、指針出現問題、堆棧溢出、NVIC中斷分組錯誤等。
3、雖然無法避免Hard Fault的發生,但是我們可以通過Hard Fault Handler來處理它,並在程序運行時提供一定的監控和定位功能。
二、STM32中的Hard Fault Handler
1、STM32中提供了硬件中斷向量表(Interrupt Vector Table,簡稱IVT),其中包含了一些保留的中斷向量,其中就有一個用於處理Hard Fault的向量。
2、當CPU遇到Hard Fault時,會自動跳轉到IVT中的Hard Fault向量,此時Hard Fault Handler便開始執行。
void HardFault_Handler(void) { __asm("ldr r0, =0xE000ED2C"); __asm("ldr r1, [r0]"); __asm("ldr r2, [r1]"); __asm("ldr r3, [r2]"); __asm("bkpt #0"); }
3、上述代碼便是STM32默認的Hard Fault Handler實現,其中使用了彙編指令讀取SCB寄存器中的CFSR(Configurable Fault Status Register)寄存器,並通過軟件中斷指令(BKPT指令)實現了停在代碼中斷處的效果。此時我們可以通過調試工具讀取CFSR寄存器的值來進行故障定位。
三、如何優化Hard Fault Handler
1、默認的Hard Fault Handler只提供了一個基本的調試信息輸出,我們可以根據實際需求進行優化。
2、比如,可以通過斷言等手段檢查相關寄存器的值,並將該信息輸出到串口中,以實現遠程監控和故障定位。
void HardFault_Handler(void) { uint32_t* sp = (uint32_t*)__get_MSP(); // 獲取堆棧指針 uint32_t pc = (uint32_t)__get_IPSR(); // 獲取出現錯誤時的指令地址 uint32_t cfsr = SCB->CFSR; // 獲取CFSR寄存器的值 uint32_t hfsr = SCB->HFSR; // 獲取HFSR寄存器的值 uint32_t mmfar = SCB->MMFAR; // 獲取MMFAR寄存器的值 uint32_t bfar = SCB->BFAR; // 獲取BFAR寄存器的值 // 將相關信息輸出到串口 printf("\n==================================== Hard Fault ====================================\n"); printf(" SP:%08X\n PC:%08X\n CFSR:%08X\n HFSR:%08X\nMMFAR:%08X\n BFAR:%08X\n", (uint32_t)sp, pc, cfsr, hfsr, mmfar, bfar); printf("=====================================================================================\n"); while(1); }
3、上述代碼演示了如何使用printf函數將相關寄存器的值輸出到串口中。通過調用這個自定義的Hard Fault Handler,我們可以獲得更多有關故障的信息。
四、如何調用Hard Fault Handler
1、由於Hard Fault是一種特殊的異常情況,因此程序無法通過普通的錯誤處理機制來捕獲它。我們需要手動地在程序中加入一些處理代碼,來調用Hard Fault Handler。
2、針對不同版本的GCC編譯器和不同型號的STM32芯片,這些代碼可能有所不同。一些最基本的方法包括:
(1)在main函數前加入以下代碼,即可使用默認的Hard Fault Handler:
int main() { NVIC_SetPriority(HardFault_IRQn, 0); uint32_t *p = NULL; *p = 0x00; return 0; }
(2)使用CMSIS庫提供的NVIC_SystemReset函數來重置系統,並在其後調用Hard Fault Handler:
#include "stm32f4xx.h" int main() { NVIC_SetPriority(HardFault_IRQn, 0); uint32_t *p = NULL; *p = 0x00; NVIC_SystemReset(); while(1); } void HardFault_Handler(void) { printf("Hard Fault...\n"); while(1); }
3、需要注意的是,因為重置系統會導致所有寄存器的值被清除,所以可能會對調試造成困擾。
五、總結
1、在嵌入式系統中,Hard Fault是一種嚴重的異常情況。
2、STM32中提供了默認的Hard Fault Handler,可以用於基本的故障定位和調試。
3、Hard Fault Handler可以根據實際需求進行優化,以提供更詳細的故障信息。
4、在程序中手動調用Hard Fault Handler,需要根據具體情況選擇適當的方法。
原創文章,作者:IVXQ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/143290.html