FreeRTOS中如何定位HardFault?

原创 鱼鹰谈单片机 2022-09-19 08:40

来源:公众号【鱼鹰谈单片机】

作者:鱼鹰Osprey

ID   :emOsprey


大家好,我是鱼鹰,因为一些事情,这次更新来的有点迟。但还是争取大家每次都能从鱼鹰公众号中到一些实实在在的技术,提高自己的核心竞争力。

感谢大家一直以来对鱼鹰的支持

今天继续聊聊开发中常见的 HardFault,这个问题应该从学习 STM32 开发以来就一直伴随着我们,很多人遇到这种问题也是不知道该如何定位。

如果只是独立开发,遇到这种问题,一般都是看代码、修改代码等等这些常规手段,因为自己写的代码最熟悉,改动一般也不会太大,容易缩小范围,也更容易定位。

但现在的产品越来越复杂,目前的开发模式都是合作开发,每个人负责各自的模块,这样的项目代码量大、复杂度高,也就更难定位问题。

而有的时候,刚入职一家公司,什么代码都不熟悉,又出现了 HardFault,更是让人崩溃,分分钟有跑路的冲动(你和代码,有一个能跑就行)。

此时,有一个能解决这种疑难杂症的大牛是能大大节省时间的,而我在公司也解决不少类似的问题,所以经验也算丰富,充当的也是这一类角色。

而鱼鹰定位 Hardfault 的方法一般是靠 KEIL在线调试+C语言+权威指南 中的知识搞定。

目前鱼鹰的解 BUG 差不多是这样的:

1、必现,代码熟悉的情况下,几个小时内搞定。

2、偶现,根据出现情况决定解决问题的时间,一般出现个四五次,基本就能定位。

3、难现。这种一般要挂一个记录仪实时记录运行情况。

经历了这么多,已经很少有能让鱼鹰需要花费几天时间才能解决的 Hardfault 问题了(犹记得刚来深圳时,因为别人写的一个 BUG 导致的 Hardfault,不得已加了几天通宵,要不是偶然机会还不一定能搞定)。

这里打个小广告,如果难解决,可以有偿请鱼鹰解决 Hardfault 问题哦。

不过最近工作上因为用了 C++,这个基础不是很熟悉,解决 Hardfault 的速度又下降了。而工程编译优化等级 -O2 也加大了不少调试难度,因此掌握下面的方法是很重要的:

总结 MDK 几种编译优化设置的方法


关于 Hardfault,鱼鹰以前也是分享了不少笔记的,不知道有多少人认真看过。

HardFault 之 INVSTAE 错误定位(一)

见鬼,过年回来后板子就 hardfault 了?

今天,鱼鹰继续分享关于在 FreeRTOS 定位 Hardfault 方法。

这里需要一个大佬写的组件 :CmBacktrace(事实上,如果能在线调试,鱼鹰是不需要借助这个组件的,但是难复现的情况下用这个组件还是比较香的)

gitee 仓库https://gitee.com/Armink/CmBacktrace

这个组件估计很多道友都听说过,也用过,但鱼鹰想说的是,有些道友在用的组件可能比较老,没有下面这种追踪功能,建议大家更新一下。

上面可以看到出错时,函数的调用栈(有时可能是错误的,需要实际分析,仅做参考)

_call_main ->  main -> fult_test_by_div0

相当实用。


同时,本篇笔记不仅适用于在 FreeRTOS 定位 Hardfault,实际上uCOS、rt-thread 等其它 RTOS 照样可以修改后使用(裸机更不用说了)。 

仓库例子支持的平台:裸机、rt-thread、ucoss-ii、freertos。

这里重点在如何移植这个组件到 freertos 中(实际上,仓库的说明文档也非常详细,可以参考)。由于 freertos  也是不断更新中,所以这个组件的例子不能完全适用于新版本,而鱼鹰刚好移植好了,在此记录一下,方便大家移植。


1、将仓库中的 cm_backtrace(源码文件) 整个文件夹拷贝到自己的工程文件夹下。

2、在自己的工程中添加这些文件(我们可以打开 demos -> os -> freertos 工程查看)

只有两个文件,相当简单。

一个是核心源码,另外一个则是汇编代码,代码执行入口。

注意,根据 IDE 不同,选择的汇编文件也不同:


其实就是将 startup_stm32f10x_hd.s 中的hardfault 默认处理函数重定位到 cmb_fault.S 中了。

注意这里有一个weak,这样链接的时候就不会链接这个,而是 cmb_fault.S 这个:

为了更方便的定位问题,我们后面还需要修改一下这个代码才行。

注意,如果你的启动文件内的 hardfault 代码被修改了,而你不懂汇编,建议恢复成上面那种,不然可能运行不正常。

3、主函数中初始化代码。

这里的字符串需要和这个一样(根据自己的工程名修改):

所以建议用英文建工程。这个在输出错误信息的时候用的上,否则每次查看调用栈都需要修改一下,比较麻烦。


如果开启了内部看门狗,建议关闭一下:

// HAL 库__HAL_DBGMCU_FREEZE_IWDG1();// 标准库DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE);

在断言失败的位置添加该函数 cm_backtrace_assert:

这样断言失败了也能看到调用栈了。


4、FreeROTS 内核文件修改(内核版本 V10.2.1)

    为了分析出错的代码,必须知道每个任务的栈信息,而 FreeRTOS 可能没有这些信息,因此,我们需要添加进去。

 task.c

FreeRTOS.h

注意,老版本freertos 是只要修改一处的,但新版本需要修改两处,否则会断言失败,运行不下去。

建议把注释也一起添加进去。

UBaseType_t     uxSizeOfStack;      /*< Support For CmBacktrace >*/


相关函数修改  task.c    prvInitialiseNewTask() :


task.c 文件最后添加如下代码用于获取栈地址、大小、名字:

为方便复制,在此贴代码

/*-----------------------------------------------------------*//*< Support For CmBacktrace >*/uint32_t * vTaskStackAddr(){    return pxCurrentTCB->pxStack;}
uint32_t vTaskStackSize(){ #if ( portSTACK_GROWTH > 0 ) return (pxNewTCB->pxEndOfStack - pxNewTCB->pxStack + 1); #else /* ( portSTACK_GROWTH > 0 )*/ return pxCurrentTCB->uxSizeOfStack; #endif /* ( portSTACK_GROWTH > 0 )*/}
char * vTaskName(){ return pxCurrentTCB->pcTaskName;}/*-----------------------------------------------------------*/

5、根据所属 RTOS 平台和芯片内核修改组件配置信息

cmb_cfg.h

1)需要定义打印输出函数,一般用 printf 打印,也可以用你自定义的一些打印函数,功能和 printf 类似即可。

#define cmb_println(...)               printf(__VA_ARGS__);printf("\r\n")

2)使能 RTOS 支持

#define CMB_USING_OS_PLATFORM

3)具体 RTOS 选择 FreeRTOS

#define CMB_OS_PLATFORM_TYPE           CMB_OS_PLATFORM_FREERTOS

4)芯片内核根据实际选择,目前支持 M0、M3、M4M7。

#define CMB_CPU_PLATFORM_TYPE          CMB_CPU_ARM_CORTEX_M3

5)打印虚拟栈,可以将出错时的原始栈信息打印出来,可能对分析有些帮助

#define CMB_USING_DUMP_STACK_INFO

6)语言支持:英语。实际也支持中文,但建议使用英语(不配置,默认就是英语)

#define CMB_PRINT_LANGUAGE             CMB_PRINT_LANGUAGE_ENGLISH

7) 如果是 C++ 编译的,有可能出错,可以在开头定义这个:

#define __CLANG_ARM


7、根据需要修改组件,方便使用(这些看看能不能有机会合并到大佬的分支里面)

1)因为功能涉及范围小,因此可以将相关头文件包含形式改成这种,这样就不需要改头文件路径了,移植更方便:

#include -->>#include "./cm_backtrace.h"
#include -->>#include "./cmb_cfg.h"
#include "cmb_def.h"-->>#include "./cmb_def.h"

main 中也不需要包含头文件,而是在需要位置直接声明这个函数即可,因为外部只需要调用这个函数

#include -->void cm_backtrace_init(const char *firmware_name, const char *hardware_ver, const char *software_ver);

这样一来,就不需要添加头文件的路径了。

或者使用相对路径的方式添加头文件:

#include "../../driver/cm_backtrace/cm_backtrace.h"

另外,我们可以让程序进入 Hardfault 前,让代码自动停止,这样我们能更好的利用在线调试代码,《 传说中的软件断点到底是什么?

HardFault_Handler    PROC    LDR     r0, =0xE000EDF0; DEMCR    LDR     r0,[r0,#0x00]    AND     r0,r0,#0x00000001    CBZ     r0,not_in_debug    BKPT    0not_in_debug    MOV     r0, lr                  ; get lr    MOV     r1, sp                  ; get stack pointer (current is MSP)    BL      cm_backtrace_fault

因为刚进入 Hardfault 时的信息最全,又不想每次打断点,上面的代码很好的实现了功能,同时也不会影响程序的正常运行(会自动判断是否处于调试模式)。

8、实验。

上面都搞定了,就可以验证一下效果了。这里我们我们可以模拟仿真看看情况。(修改工程配置,这些内容鱼鹰以前分享过,不多说)

运行仓库例子后,应该能打印下面的信息,告诉我们出现了 div 0 错误

而你移植好的工程也应该打印类似的信息(加入测试代码 :fault_test_by_div0();)如果打印不出来,有两种可能:

1、打印函数没初始化好就进入了Hardfault

2、打印函数有问题。


之后我们复制最后一行,然后运行仓库 tools 里面的 add2line 工具看看调用栈信息:

在 git bash 中可能会执行失败,可以加入程序路径,当然也可以将该工具路径加入到Windows 环境变量中。有可能提示找不到 axf 文件,把这个文件拷贝到工具下即可。

正确的做法是,将该工具放到 C 盘目录下,同时添加环境变量,之后就可以在 axf 目录下打开 gitbash 或者 cmd 窗口执行命令即可。

这里只作为演示,就不多介绍这些了。


最后再简单介绍一下这个组件的实现原理:

如果出现hardfault, 首先进入汇编文件的 HardFault_Handler 处理,这里会得到当前的栈指针和 LR,并且根据 LR 确定出错的栈是哪个《STM32 两个栈,你用哪一个?》(这里是 PSP 栈)

根据错误寄存器信息,确定哪种错误(这里为 除 0 错误

然后对栈信息 和 LR 、PC 进行 FLASH 上的汇编代码分析,找出可能的跳转指令,这里找到的两个跳转地址为 0x08001f96 0x08000368,进而得到调用栈。


因此,要能准确的得到调用栈,有两点重要前提条件(建议优化等级 -O0):

1、栈未被破坏

2、芯片运行代码和 axf 文件保持一致。

即使如此,你也不能保证找出的调用栈就是正确的,比如你使用 fault_test_by_unalign() 测试,得到的结果如下: 

中间多了一个 fputc。

因此,这些打印信息只能作为参考使用。

但在线调试不同,它更专业,不容易出现错误调用关系。

鱼鹰想分享的内容到此就结束了,下期再见!

鱼鹰谈单片机 面向软件开发进阶读者,分享包括但不限于 C 语言、KEIL、STM32、51 等知识!
评论
  • 振动样品磁强计是一种用于测量材料磁性的精密仪器,广泛应用于科研、工业检测等领域。然而,其测量准确度会受到多种因素的影响,下面我们将逐一分析这些因素。一、温度因素温度是影响振动样品磁强计测量准确度的重要因素之一。随着温度的变化,材料的磁性也会发生变化,从而影响测量结果的准确性。因此,在进行磁性测量时,应确保恒温环境,以减少温度波动对测量结果的影响。二、样品制备样品的制备过程同样会影响振动样品磁强计的测量准确度。样品的形状、尺寸和表面处理等因素都会对测量结果产生影响。为了确保测量准确度,应严格按照规
    锦正茂科技 2025-02-28 14:05 134浏览
  • 请移步 gitee 仓库 https://gitee.com/Newcapec_cn/LiteOS-M_V5.0.2-Release_STM32F103_CubeMX/blob/main/Docs/%E5%9F%BA%E4%BA%8ESTM32F103RCT6%E7%A7%BB%E6%A4%8DLiteOS-M-V5.0.2-Release.md基于STM32F103RCT6移植LiteOS-M-V5.0.2-Release下载源码kernel_liteos_m: OpenHarmon
    逮到一只程序猿 2025-02-27 08:56 195浏览
  • RGB灯光无法同步?细致的动态光效设定反而成为产品客诉来源!随着科技的进步和消费者需求变化,电脑接口设备单一功能性已无法满足市场需求,因此在产品上增加「动态光效」的形式便应运而生,藉此吸引消费者目光。这种RGB灯光效果,不仅能增强电脑周边产品的视觉吸引力,还能为用户提供个性化的体验,展现独特自我风格。如今,笔记本电脑、键盘、鼠标、鼠标垫、耳机、显示器等多种电脑接口设备多数已配备动态光效。这些设备的灯光效果会随着音乐节奏、游戏情节或使用者的设置而变化。想象一个画面,当一名游戏玩家,按下电源开关,整
    百佳泰测试实验室 2025-02-27 14:15 137浏览
  • 1,微软下载免费Visual Studio Code2,安装C/C++插件,如果无法直接点击下载, 可以选择手动install from VSIX:ms-vscode.cpptools-1.23.6@win32-x64.vsix3,安装C/C++编译器MniGW (MinGW在 Windows 环境下提供类似于 Unix/Linux 环境下的开发工具,使开发者能够轻松地在 Windows 上编写和编译 C、C++ 等程序.)4,C/C++插件扩展设置中添加Include Path 5,
    黎查 2025-02-28 14:39 140浏览
  • 更多生命体征指标风靡的背后都只有一个原因:更多人将健康排在人生第一顺位!“AGEs,也就是晚期糖基化终末产物,英文名Advanced Glycation End-products,是存在于我们体内的一种代谢产物” 艾迈斯欧司朗亚太区健康监测高级市场经理王亚琴说道,“相信业内的朋友都会有关注,最近该指标的热度很高,它可以用来评估人的生活方式是否健康。”据悉,AGEs是可穿戴健康监测领域的一个“萌新”指标,近来备受关注。如果站在学术角度来理解它,那么AGEs是在非酶促条件下,蛋白质、氨基酸
    艾迈斯欧司朗 2025-02-27 14:50 400浏览
  •         近日,广电计量在聚焦离子束(FIB)领域编写的专业著作《聚焦离子束:失效分析》正式出版,填补了国内聚焦离子束领域实践性专业书籍的空白,为该领域的技术发展与知识传播提供了重要助力。         随着芯片技术不断发展,芯片的集成度越来越高,结构也日益复杂。这使得传统的失效分析方法面临巨大挑战。FIB技术的出现,为芯片失效分析带来了新的解决方案。它能够在纳米尺度上对芯片进行精确加工和分析。当芯
    广电计量 2025-02-28 09:15 116浏览
  •           近日受某专业机构邀请,参加了官方举办的《广东省科技创新条例》宣讲会。在与会之前,作为一名技术工作者一直认为技术的法例都是保密和侵权方面的,而潜意识中感觉法律有束缚创新工作的进行可能。通过一个上午学习新法,对广东省的科技创新有了新的认识。广东是改革的前沿阵地,是科技创新的沃土,企业是创新的主要个体。《广东省科技创新条例》是广东省为促进科技创新、推动高质量发展而制定的地方性法规,主要内容包括: 总则:明确立法目
    广州铁金刚 2025-02-28 10:14 103浏览
  • 一、VSM的基本原理震动样品磁强计(Vibrating Sample Magnetometer,简称VSM)是一种灵敏且高效的磁性测量仪器。其基本工作原理是利用震动样品在探测线圈中引起的变化磁场来产生感应电压,这个感应电压与样品的磁矩成正比。因此,通过测量这个感应电压,我们就能够精确地确定样品的磁矩。在VSM中,被测量的样品通常被固定在一个震动头上,并以一定的频率和振幅震动。这种震动在探测线圈中引起了变化的磁通量,从而产生了一个交流电信号。这个信号的幅度和样品的磁矩有着直接的关系。因此,通过仔细
    锦正茂科技 2025-02-28 13:30 100浏览
  • 在物联网领域中,无线射频技术作为设备间通信的核心手段,已深度渗透工业自动化、智慧城市及智能家居等多元场景。然而,随着物联网设备接入规模的不断扩大,如何降低运维成本,提升通信数据的传输速度和响应时间,实现更广泛、更稳定的覆盖已成为当前亟待解决的系统性难题。SoC无线收发模块-RFM25A12在此背景下,华普微创新推出了一款高性能、远距离与高性价比的Sub-GHz无线SoC收发模块RFM25A12,旨在提升射频性能以满足行业中日益增长与复杂的设备互联需求。值得一提的是,RFM25A12还支持Wi-S
    华普微HOPERF 2025-02-28 09:06 143浏览
  • Matter 协议,原名 CHIP(Connected Home over IP),是由苹果、谷歌、亚马逊和三星等科技巨头联合ZigBee联盟(现连接标准联盟CSA)共同推出的一套基于IP协议的智能家居连接标准,旨在打破智能家居设备之间的 “语言障碍”,实现真正的互联互通。然而,目标与现实之间总有落差,前期阶段的Matter 协议由于设备支持类型有限、设备生态协同滞后以及设备通信协议割裂等原因,并未能彻底消除智能家居中的“设备孤岛”现象,但随着2025年的到来,这些现象都将得到完美的解决。近期,
    华普微HOPERF 2025-02-27 10:32 214浏览
  • 构建巨量的驾驶场景时,测试ADAS和AD系统面临着巨大挑战,如传统的实验设计(Design of Experiments, DoE)方法难以有效覆盖识别驾驶边缘场景案例,但这些边缘案例恰恰是进一步提升自动驾驶系统性能的关键。一、传统解决方案:静态DoE标准的DoE方案旨在系统性地探索场景的参数空间,从而确保能够实现完全的测试覆盖范围。但在边缘案例,比如暴露在潜在安全风险的场景或是ADAS系统性能极限场景时,DoE方案通常会失效,让我们看一些常见的DoE方案:1、网格搜索法(Grid)实现原理:将
    康谋 2025-02-27 10:00 252浏览
  • 应用趋势与客户需求,AI PC的未来展望随着人工智能(AI)技术的日益成熟,AI PC(人工智能个人电脑)逐渐成为消费者和企业工作中的重要工具。这类产品集成了最新的AI处理器,如NPU、CPU和GPU,并具备许多智能化功能,为用户带来更高效且直观的操作体验。AI PC的目标是提升工作和日常生活的效率,通过深度学习与自然语言处理等技术,实现更流畅的多任务处理、实时翻译、语音助手、图像生成等功能,满足现代用户对生产力和娱乐的双重需求。随着各行各业对数字转型需求的增长,AI PC也开始在各个领域中显示
    百佳泰测试实验室 2025-02-27 14:08 255浏览
  • 美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?‌美国加州CEC能效认证与美国DOE能效认证在多个方面存在显著差异‌。认证范围和适用地区‌CEC能效认证‌:仅适用于在加利福尼亚州销售的电器产品。CEC认证的范围包括制冷设备、房间空调、中央空调、便携式空调、加热器、热水器、游泳池加热器、卫浴配件、光源、应急灯具、交通信号模块、灯具、洗碗机、洗衣机、干衣机、烹饪器具、电机和压缩机、变压器、外置电源、消费类电子设备
    张工nx808593 2025-02-27 18:04 120浏览
  • 2025年2月26日,广州】全球领先的AIoT服务商机智云正式发布“Gokit5 AI智能体开发板”,该产品作为行业首个全栈式AIoT开发中枢,深度融合火山引擎云原生架构、豆包多模态大模型、扣子智能体平台和机智云Aiot开发平台,首次实现智能体开发全流程工业化生产模式。通过「扣子+机智云」双引擎协同架构与API开放生态,开发者仅需半天即可完成智能体开发、测试、发布到硬件应用的全流程,标志着智能体开发进入分钟级响应时代。一、开发框架零代码部署,构建高效开发生态Gokit5 AI智能体开发板采用 “
    机智云物联网 2025-02-26 19:01 162浏览
  • 在2024年的科技征程中,具身智能的发展已成为全球关注的焦点。从实验室到现实应用,这一领域正以前所未有的速度推进,改写着人类与机器的互动边界。这一年,我们见证了具身智能技术的突破与变革,它不仅落地各行各业,带来新的机遇,更在深刻影响着我们的生活方式和思维方式。随着相关技术的飞速发展,具身智能不再仅仅是一个技术概念,更像是一把神奇的钥匙。身后的众多行业,无论愿意与否,都像是被卷入一场伟大变革浪潮中的船只,注定要被这股汹涌的力量重塑航向。01为什么是具身智能?为什么在中国?最近,中国具身智能行业的进
    艾迈斯欧司朗 2025-02-28 15:45 221浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦