如何合理退出Cortex-M4的HardFault Handler以实现UART通信?
Cortex-M4 Hard Fault中UART输出的非标志位退出方案
针对你遇到的问题,这里提供几种无需置位标志返回main的直接解决方案,都是在Hard Fault上下文里完成UART输出,不用依赖主线程:
1. 临时切换UART为轮询模式输出
既然中断驱动的UART不能在ISR里调用,直接绕开中断,改用轮询发送:
- 先保存当前UART的中断配置(比如
USART_CR1里的发送中断使能位) - 关闭UART相关中断,强制用轮询方式发数据:每发一个字节就等
USART_SR的TXE位置位,确认发送完成再发下一个 - 输出完寄存器信息后,直接复位系统(毕竟Hard Fault后系统已经不稳定,没必要恢复UART配置)
- 示例代码片段:
void HardFault_Handler(void) { // 保存UART当前中断配置 uint32_t uart_backup = USART1->CR1; // 关闭UART发送中断 USART1->CR1 &= ~(USART_CR1_TXEIE | USART_CR1_TCIE); // 轮询发送故障信息 const uint8_t msg[] = "Hard Fault Triggered!\r\nRegisters:\r\n"; for(uint32_t i=0; i<sizeof(msg)-1; i++) { while(!(USART1->SR & USART_SR_TXE)); USART1->DR = msg[i]; } // 发送R0-R12、LR、PC等寄存器值的逻辑 // ... // 直接复位系统 NVIC_SystemReset(); }
这种方式最可靠,不需要修改系统任何核心配置,完全在Hard Fault Handler里完成输出。
2. 切换到线程模式执行UART驱动
Cortex-M4支持手动切换异常模式到线程模式,这样就能正常调用依赖中断的UART驱动:
- 用汇编裸函数先获取当前栈帧信息,再跳转到C处理函数
- 在C函数里修改
CONTROL寄存器切换到线程模式,同时设置专用的栈空间(避免和原栈冲突) - 此时已经处于线程模式,UART的中断可以正常触发,直接调用原有驱动函数即可
- 示例核心逻辑:
// 裸函数处理栈帧跳转 __attribute__((naked)) void HardFault_Handler(void) { __asm volatile ( "MOV R0, LR \n" // 拿LR判断用的是MSP还是PSP "TST R0, #4 \n" "ITE EQ \n" "MRSEQ R0, MSP \n" "MRSNE R0, PSP \n" "BL hard_fault_c_handler \n" // 跳转到C处理逻辑 "B . \n" // 防止返回异常上下文 ); } // 专用栈空间,大小按需调整 #define HARD_FAULT_STACK_SIZE 256 uint32_t hard_fault_stack[HARD_FAULT_STACK_SIZE] __attribute__((aligned(8))); void hard_fault_c_handler(uint32_t* stack_frame) { // 切换到特权级线程模式 __set_CONTROL(__get_CONTROL() | 0x01); // 设置专用栈指针 __set_PSP((uint32_t)&hard_fault_stack[HARD_FAULT_STACK_SIZE]); // 现在可以正常调用中断驱动的UART函数 uart_send_string("Hard Fault Detected\r\n"); uart_dump_registers(stack_frame); // 复位系统 NVIC_SystemReset(); }
这种方式适合必须用原有UART驱动的场景,专用栈能避免栈溢出风险。
3. 临时调整UART中断优先级(不推荐)
可以把UART中断优先级设为和Hard Fault相同,允许在Hard Fault中响应UART中断:
- 进入Hard Fault Handler后先关全局中断,修改UART中断优先级为最高级(和Hard Fault一致)
- 开全局中断,此时UART中断可以触发(同优先级不会嵌套,会先处理UART中断再回到Hard Fault)
- 输出完成后恢复优先级再复位
- 注意:这种方式风险高,可能导致其他紧急异常无法响应,仅适合临时调试。
核心提醒
Hard Fault触发后系统处于不稳定状态,无论用哪种方式,输出完信息后直接复位是最安全的选择,不要尝试恢复系统正常运行。
内容的提问来源于stack exchange,提问作者RDF
相关产品推荐
相关产品推荐

