尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

嵌入式踩坑:printf 未重定向引发 Semihosting BKPT 异常导致 HardFault 深度排查

嵌入式踩坑:printf 未重定向引发 Semihosting BKPT 异常导致 HardFault 深度排查 项目场景工况移动电源进行AC充电测试。环境GD32F305 FreeRTOS故障出在 BmsManageTask 任务。问题描述移动电源在AC充电时偶发性出现屏幕停止刷新并在几秒后重启。移动电源是新开发的还没有测试过稳定性。排查步骤步骤一通过问题现象大概推测导致此问题的原因。可能的原因1. 内存踩踏或任务栈越界导致程序进入Hardfault()最终看门狗复位系统。2. 喂狗任务和显示任务异常阻塞得不到运行最终看门狗复位系统。3. 程序不断进入中断导致喂狗任务和显示任务得不到运行最终看门狗复位系统。步骤二通过增加打印日志信息、仿真或其它方式来验证复位原因。1. 使用Cmbacktrace来排查程序异常时是否进入了Hardfault()和分析出Hardfault()的原因。当程序进入Hardfault()时会打印进入Hardfault()的原因和进入之前的调用了那些函数。2. 在每个业务任务入口打印独立标记例如温度、电压、电流采样任务LOG_ADC Bms通信任务LOG_BMS显示任务LOG_LCD等。当某个任务被永久阻塞时它的独立 标记不会被打印。3. 在可能连续进入的中断里添加电平翻转测试函数。当连续进入中断时电平会以极快速度进 行翻转。步骤三 还原当时设备运行的工况尝试复现问题。我当时复现出问题时设备打印了进入Hardfault()的原因和进入前的函数调用关系。进入Hardfault()原因函数调用关系步骤四 根据现象和打印的信息分析原因原因分析进入Hardfault(的原因是程序调用printf()打印接口但程序缺失printf()串口底层重定向标准库启用半主机机制执行BKPT指令触发DebugFault异常因未做对应异常拦截处理工程未实现Debug_HardFault异常处理函数故障级联升级进入HardFault中断同时造成JLINK仿真会话断开。为什么调用了printf当时是对系统添加系统日志使用log输出接口替换printf()函数但是由于printf()分散在各个文件比较零散bms的iic通信相关.c文件的printf()没有替换干净。当IIC受干扰出现偶发通信异常时程序会调用printf()打印IIC通信异常。补充1. semihosting(半主机调试)ARM 单片机专属调试功能仅插上 JLINK 仿真器时才能正常工作。作用没有自定义串口打印时C 标准库借助仿真器把printf文字打印到电脑 Keil 调试控制台。 实现方式库内部自动插入BKPT硬件断点指令和调试器通信。2. BKPTARM 汇编硬件断点指令BKPT专门给调试器用正常调试JLINK 识别这条指令接收 printf 数据程序继续跑无仿真器 / 调试配置不对CPU 识别到 BKPT但没人处理直接抛出异常。3. DebugFault单片机内核调试专用异常只要执行 BKPT 断点指令就会进入这个异常。 工程没有写DebugFault_Handler专门处理半主机断点这个异常无法正常释放。4. 级联进入HardFault嵌入式内核异常有优先级DebugFault 处理失败 → 异常升级统一进入总故障中断HardFault_Handler这就是调试看到进 HardFault 的根本原因。解决方案一检查工程里调用了printf()的地方删除干净并使用log打印接口替代。方案二自定实现fputc()输出函数。
返回列表