[RTT] RT-Thread Hard Fault 死机问题定位方法

目录

  • 简述
  • 空函数指针
    • 示例:
    • 排查方法:
      • 1. 找到错误日志
      • 2. 分析错误日志
      • 3. 继续分析错误日志
      • 4. 1使用IDE定位错误代码
      • 4.2 使用map文件定位错误代码
  • 操作不可写内存
    • 示例:
    • 排查方法:
      • 1. 找到错误日志
      • 2. 分析错误日志
      • 3. 找到PC指针对应的代码

简述

RT-Thread操作系统中Hard Fault是比较常见的死机问题,造成这个问题的原因多种多样,但排查方式大同小异。本文以执行空函数死机和操作不可写内存死机两种情况为例,和大家分享下这类问题的排查定位方法。


空函数指针

示例:

手动写一个执行空函数指针执行死机的shell指令为例

void hard_fault_test1(void)
{
   void (*fun) (void) = 0;
   fun();
}
MSH_CMD_EXPORT(hard_fault_test1, hard_fault_test1);

排查方法:

1. 找到错误日志

RTT在hardfault后会打印MCU的几个运行相关的寄存器、各线程的运行情况:
[RTT] RT-Thread Hard Fault 死机问题定位方法_第1张图片


2. 分析错误日志

首先查看各线程栈的运行状态、线程栈占用是正常的。(只看线程列表不能完全排除线程栈溢出的情况,有的时候线程栈溢出导致死机但list里无法判断出来)
再查看几个MCU运行的指针,发现PC指针为0。
[RTT] RT-Thread Hard Fault 死机问题定位方法_第2张图片

PC是指程序计数器(Program Counter)。用于存放下一条将要执行的指令地址。很明显在该环境下0地址不是存放固件的地址,PC指针为0是不正常的。(PC指针不止为0是不正常,所有出现非代码段的地址都不正常)。

此时可以确定是执行了一个0地址的函数导致的,一般是回调函数未设置就直接执行了函数指针导致的。但此时还不确定这个错误的函数是在哪被执行的。


3. 继续分析错误日志

下一步是要定位这个错误的函数指针是被谁调用的。
直接看LR指针,这里记录的是PC指针执行后的返回地址,也就是调用错误函数指针的位置。
[RTT] RT-Thread Hard Fault 死机问题定位方法_第3张图片


4. 1使用IDE定位错误代码

在keil中打开汇编代码,在任意地方右键,选择show disassembly at address。
[RTT] RT-Thread Hard Fault 死机问题定位方法_第4张图片

在输入框中输入刚刚的LR指针地址0x7001857B,点击go to
在这里插入图片描述

汇编代码窗口跳转的同时,C代码也跳转到了对应位置:
[RTT] RT-Thread Hard Fault 死机问题定位方法_第5张图片

可以看到光标指到了hard_fault_test1()函数的结尾,说明是在执行该函数时触发的hard fault。
结合之前确定的空指针函数的问题,分析代码可以看到是44行执行了空指针函数。
问题找到。


4.2 使用map文件定位错误代码

如果当前环境不能使用IDE进行debug查看汇编代码,通过编译器生成的.map文件定位也可以定位到是哪个.c文件的哪个函数。
注意,map文件中显示的是各个函数的起始地址,但LR指针指向的是函数中的某条指令的地址,因此可以将指针值减去一到两位搜索,再根据搜索结果判断LR在哪个函数的地址范围内。
在这里插入图片描述

如打开map文件后查找0x7001857,可以看到在hard_fault_test1的地址范围内再按照上面的方法去该函数中排查。
问题找到。


操作不可写内存

示例:

手动写一个操作不可写内存导致死机的shell指令为例

void hard_fault_test2(void)
{
    char *str = 0;
    *str = '1';
    rt_kprintf("%s", str);
}
MSH_CMD_EXPORT(hard_fault_test2, hard_fault_test2);

排查方法:

1. 找到错误日志

[RTT] RT-Thread Hard Fault 死机问题定位方法_第6张图片


2. 分析错误日志

首先查看各线程栈的运行状态、线程栈占用是正常的。再查看几个MCU运行的指针,也没有明显的异常。
在这里插入图片描述


3. 找到PC指针对应的代码

因为根据错误日志没有发现明显的错误,只能先跳转到PC指针指向的代码,查看发生hard fault时正在执行哪些代码。
通过上一节的方法,使用IDE查找汇编,或查找map文件,定位到对应的C代码:

PC指针指向的是52行的rt_kprintf输出,即死机之前执行的是51行的数据写入,分析代码发现是想0地址写入了数据导致的死机。
问题找到。


相关文章:
RT-Thread线程调度机制、线程切换时机分析:
https://blog.csdn.net/weixin_43854928/article/details/119985822

RT-Thread RT_ASSERT 断言死机问题定位方法:
https://blog.csdn.net/weixin_43854928/article/details/123884381?spm=1001.2014.3001.5502

你可能感兴趣的:(RT-Thread,arm,stm32)