单片机运行死机快速排查方式记录

问题现象

运行过程中司机,进入HardFault_Handler中断

排查记录

首先在程序中开启看门狗,如果有看门狗超时回调函数则在看门狗回调函数中打断点,如果没有则在hardfaultt 中断函数中打断点。

然后连接调试器,全速debug程序,知道程序进入上述两个断点之一,如下请添加图片描述
查看IDE中的CallStack,确定发生错误的前一刻或者说在哪里发生的HardFault,如下:请添加图片描述
逐级点击进入,查看是哪里出现了问题,当前程序是讲变量作为变量地址传入导致了内存访问越界错误
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
修改对应代码解决。

### 排查单片机程序运行一段时间后卡死的方法 #### 1. **确认复位类型** 单片机运行过程中可能会因为各种原因触发复位,导致程序重新开始执行。如果程序卡死,首先需要确认是否发生了复位。常见的复位类型包括: - **看门狗复位**:当软件无法按时喂狗时,看门狗会触发复位。这种情况通常不会留下错误码,与硬复位的效果相同。 - **内存泄露**:某些单片机(如BK3432)在内存泄露时可能会打印特定的错误码(例如`0xf2f2f2f2`),帮助定位问题。 - **硬复位**:包括上电复位、欠压复位和RST引脚复位。这些复位会导致寄存器重置,可以通过检查复位标志寄存器来确认。 - **软件复位**:可能是由于OTA更新完成等原因触发的主动复位,寄存器不会被重置。 通过检查复位原因寄存器或打印的错误码,可以确定是哪种类型的复位[^1]。 #### 2. **检查外设初始化** 程序卡死的一个常见原因是外设未正确初始化。特别是在上电或休眠唤醒后,某些外设(如硬件IIC、串口)如果没有重新初始化,直接进行发送或读取操作可能会导致死机。因此,确保所有外设在使用前都已正确初始化是非常重要的[^1]。 #### 3. **分析堆栈溢出** 堆栈溢出是另一个常见的程序卡死原因。如果堆栈空间不足,可能会导致函数调用时堆栈溢出,进而引发不可预测的行为。可以通过以下方法来排查堆栈问题: - **增大堆栈大小**:将堆栈大小设置为足够大的值(如0x800,即2KB),以确保有足够的空间供程序使用。 - **简化中断处理函数**:在中断处理函数中尽量减少复杂的操作,只保留必要的代码。例如,在`SysTick_Handler`中仅保留`HAL_IncTick()`,避免在中断中执行耗时的操作。 - **调试器验证**:使用调试器单步执行代码,特别是在时钟初始化等关键部分,检查寄存器值是否符合预期。 #### 4. **检查变量初始化问题** 变量初始化不当也可能导致程序卡死。例如,在算法移植调试过程中,将局部变量改为全局变量后,如果没有对该变量进行归零初始化,可能会导致变量在多次计算中不断累加,最终超出数组索引范围,引发程序错误。因此,确保所有变量在使用前都进行了正确的初始化是非常重要的[^4]。 #### 5. **使用调试工具** 调试工具可以帮助更有效地定位问题。可以使用以下工具和技术: - **日志输出**:在关键代码段添加日志输出,记录程序执行流程和关键变量的值,帮助定位卡死的位置。 - **ETW事件监控**:通过ETW(Event Tracing for Windows)监控程序执行过程,捕获异常事件。但需要注意,长时间监控可能会生成大量事件,影响性能。 - **断点调试**:使用调试器设置断点,逐步执行代码,观察程序状态和寄存器值的变化。 #### 6. **优化代码结构** 代码结构不合理也可能导致程序卡死。例如,长时间的循环或递归调用可能会导致程序陷入死循环。可以通过以下方式优化代码: - **避免无限循环**:确保所有循环都有明确的退出条件,避免无限循环。 - **减少递归深度**:尽量避免使用深度递归,改用迭代或其他方式实现相同功能。 - **合理分配资源**:确保动态分配的内存及时释放,防止内存泄露。 #### 7. **验证时钟配置** 时钟配置错误可能会导致程序运行不稳定。例如,在STM32F103C8T6中,如果系统时钟配置不正确,可能会导致程序卡死在`SysTick_Handler`中。可以通过以下方式验证时钟配置: - **增加超时等待**:在`SystemInit()`中增加超时等待机制,确保外部高速晶振(HSE)准备好后再继续执行。 - **检查时钟频率**:确保系统时钟频率为预期值(如72MHz),可以通过调试器检查相关寄存器的值。 ### 示例代码 ```c // 在SystemInit()中增加超时等待 if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET) { // 提示时钟故障 Error_Handler(); } ``` ```c // 简化的SysTick_Handler void SysTick_Handler(void) { HAL_IncTick(); // 仅保留必要的代码 } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值