RT-Thread论坛
直播中

qjqb

9年用户 1365经验值
擅长:5762
私信 关注
[问答]

使用RT-Thread Studio在程序进Hardfault时怎么方便的查看调用栈?

求助各位大神
使用RT-Thread Studio在程序进Hardfault时怎么方便的查看调用栈
使用MDK的时候可以方便的看调用堆栈,从而很快速的找到问题,使用RT-Thread Studio该如何快速找到问题呢

回帖(1)

贾埃罗

2025-10-20 17:03:12

在 RT-Thread Studio 中定位 HardFault 问题可以通过以下步骤高效实现,无需依赖 MDK 的专用功能:




一、启用内置故障诊断组件




  1. 开启 cm_backtrace 组件



    • 在 RT-Thread Settings 中启用 cm_backtrace(位于 libccommon 分类)

    • 或手动在 rtconfig.h 添加:
      #define PKG_USING_CM_BACKTRACE




  2. 初始化组件(在 main.c 中)


    #include 
    void main(void) {
       cm_backtrace_init("YourFirmwareName", "HW_VERSION", "SW_VERSION");
       // ...其他初始化
    }



  3. 触发故障时自动输出调用栈



    • 发生 HardFault 后,串口终端会打印详细诊断信息:
      ======== Stack information ========
      addr: 0x20001F00
      data: 0x20001F20  0x080001A9  0x00000000  ...  
      ======== Registers information =======
      R0 : 0x00000000    R1 : 0x00000000    R2 : 0x00000000    R3 : 0x00000000  
      R12: 0x00000000    LR : 0x0800025D    PC : 0x080001A8    PSR: 0x01000000
      ======== Call stack ========
      #0  pc:0x080001A8  test_error_func (at src/main.c:15)
      #1  pc:0x0800025D  main_thread_entry (at src/main.c:32)






二、使用 GDB 调试定位




  1. 启动调试会话



    • 点击工具栏的 Debug 按钮(虫形图标)

    • 程序停在 HardFault 时会自动暂停




  2. 查看关键信息



    • 调用栈 (Call Stack)

      • Debug 视图 → 展开 Call Stack 窗口

      • 双击堆栈帧跳转到对应源代码位置


    • 寄存器 (Registers)

      • 查看 PC(故障指令地址)、LR(返回地址)、SP(堆栈指针)


    • 反汇编 (Disassembly)

      • 右键 → Open Disassembly 查看当前汇编指令

      • 重点关注 PC 附近的指令





  3. 分析故障原因寄存器



    • Expressions 窗口输入:
      *(unsigned int*)0xE000ED28  // 查看 CFSR 寄存器
      *(unsigned int*)0xE000ED2C  // HFSR

    • 解析标志位:

      • IMPRECISERR:总线访问错误(常见于 DMA 操作)

      • IBUSERR:指令读取错误

      • DIVBYZERO:除零错误







三、手动解析堆栈(无调试器时)


若无法连接调试器,通过 cm_backtrace 输出的地址手动定位:


# 使用 addr2line 工具解析地址
arm-none-eabi-addr2line -e your_firmware.elf -a -f 0x080001A8 0x0800025D

# 输出示例
0x080001A8
test_error_func at /project/src/main.c:15
0x0800025D
main_thread_entry at /project/src/main.c:32



四、常见问题排查技巧




  1. 栈溢出检测



    • rtconfig.h 中启用:
      #define RT_USING_OVERFLOW_CHECK

    • 线程栈溢出时触发断言




  2. 关键位置断点



    • 在 HardFault 入口 HardFault_Handler() 设断点

    • 检查进入前的最后操作




  3. 内存访问检查



    • 使用 MPU 配置保护区域(需硬件支持)

    • 检查野指针/数组越界:
      // 在可疑代码后添加校验
      RT_ASSERT(ptr != RT_NULL);






五、对比 MDK 的功能替代方案



























MDK 功能 RT-Thread Studio 等效方案
Fault Reports cm_backtrace 组件 + 串口输出
Call Stack 窗口 GDB 的 Call Stack 视图
Disassembly 窗口 Disassembly 反汇编视图
Memory Watch Memory Browser 内存查看器



六、优化调试体验建议




  1. 减小优化等级



    • 项目属性 → C/C++ BuildOptimization Level 改为 -O0




  2. 保存崩溃现场



    • HardFault_Handler() 中保存寄存器到全局变量:
      volatile uint32_t fault_sp, fault_pc, fault_lr;
      void HardFault_Handler(void) {
      __asm volatile("mov %0, spn" : "=r"(fault_sp));
      __asm volatile("mov %0, lrn" : "=r"(fault_lr));
      fault_pc = (*((volatile uint32_t *)(fault_sp + 24)) & 0xFFFFFFFE);
      while(1);
      }






通过结合 cm_backtrace 自动诊断、GDB 交互调试和 addr2line 离线解析,可在 RT-Thread Studio 中高效定位 HardFault 问题,效果媲美 MDK。重点在于合理配置诊断组件并熟悉 GDB 调试界面操作。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分