HardFault_Handler(void)处理的部分办法

📅 2026/7/18 4:34:44
HardFault_Handler(void)处理的部分办法
void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } }一般导致出现该状况的原因1.数组越界2.野指针3.栈溢出4.中断内处理出现错误等分析此函数进入此函数后里面的while(1),将故障强制停留在这儿避免进一步破坏堆栈给后续排查带来危害排查故障的办法int main(void) { RCC_GetClocksFreq(rcc_clocks); while(1) { test_main ; test_hardfault(); } } void test_hardfault(void) { uint8_t test_buf[1] {0}; for(uint32_t i 0; i 10; i)//数组越界 { test_buf[i] 1; } return; }上述问题是一个数组越界的问题程序跑起来之后会停在程序跑起来之后会停在这儿之后进行下一步分析其中的寄存器R13叫做堆栈指针寄存器内核通常有MSP与PSP两种,但是同时只能有一个在使用其一般存放代码运行时产生的临时变量函数栈帧中断切换时的上下文等如果是裸机则使用MSP如果移植了rtos,运行任务时使用PSP寄存器R14j叫做连接寄存器等程序运行时调用了一个子程序R14存放的就是其返回地址寄存器R15叫做程序计数器当程序发生异常与中断时内核会将xPSR,PC,LR,R12,R3,R2,R1,R0依次压入堆栈到了这儿之后程序就停止了然后根据现有的内容分析问题首先根据黄框的部分分析若 LR 是0xFFFFFFF9/E9说明错误出现在普通程序代码非中断中若 LR 是0xFFFFFFF1/E1说明错误是在中断 / 异常的处理过程中被打断即发生了中断嵌套。如果是0xFFFFFFFD/EDPSP 进程栈表示在rtos的任务中出现了错误根据最开始的部分分析得知是普通程序发生了错误及应该读取MSP寄存器内的值0x20000658,将其内存中的数据读取出来接下来的操作步骤会出现以下界面可以明显的看出来内存的摆放是按照小端的方式摆放的。按照上述以四字节摆放的方式看最后一个红框内的内容为LR内的值即为报错前存放的该返回的地址之后在这儿右击选中以下红框的选项把LR的地址给输入进去可以跳转到出问题的代码部分其中的汇编我也不是很懂但是可以看一下代码来找到对应的函数重点分析这个部分就行了---------------------------------------------------------------------------------------------------------------------------------中断中的处理函数void bsp_test_hardfault(void) { uint8_t test_buf[1] {0}; for(uint32_t i 0; i 10; i) { test_buf[i] 1; } return; } /** * function: 定时器15中断服务函数(用于时间片的切换) * para: 无 * return 无 */ void TMR15_GLOBAL_IRQHandler(void) { if(TMR_GetINTStatus(TMR15, TMR_INT_Overflow) ! RESET) { TMR_ClearITPendingBit(TMR15, TMR_INT_Overflow); bsp_test_hardfault(); } return; }如果是在中断中的函数这个时候会出现这个样子目前还不知道下一步该怎么处理不过可以大概判断处是中断中的问题有大佬知道的可以告知我一下。新补充freertos中的任务内hardfault:void test_task(void *pvParameters) { while(1) { uint8_t* test_ptr; *test_ptr 0; // uint8_t test_buf[1000] {0}; // for(uint16_t i 0; i 1000; i) // { // test_buf[i] 1; // } vTaskDelay(1000); } }上述是一个明显的野指针可以想象到最后停留的位置为按照上文中的概述进行一下步骤上述是简单的任务内导致的hardfault,,关于任务栈溢出的情况void test_task(void *pvParameters) { while(1) { // uint8_t* test_ptr; // *test_ptr 0; uint8_t test_buf[1000] {0}; for(uint16_t i 0; i 1000; i) { test_buf[i] 1; } vTaskDelay(1000); } }最终的结果也是这儿不同的的是上述函数中是任务切换的入栈与出栈的操作。上述是大致的描述当然rtos中也有关于栈任务检测的函数。