使用 Eclipse 和 GDB 调试 FreeRTOS ARM 线程

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.2 + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 138 小节,累计 21w+ 字,讲解图:905 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 350+ 小伙伴加入,欢迎点击围观

FreeRTOS 可能是最流行的 RTOS,我喜欢它:它高效、具有许多功能、简单且易于使用。但是,尽管它很受欢迎,但使用 Eclipse 和 GDB 等开源工具对其进行调试确实不是那么用户友好:与商业解决方案相比,调试线程和任务是一件痛苦的事情。对于本学期的大学课程,我一直在寻找对我的学生来说易于使用的东西。最后,我设法使用了一个 GDB 帮助程序,它使事情变得更容易:我现在可以使用 GDB 在 Eclipse 中切换任务线程:-)

切换到 Shell 任务

问题是:当我停止运行的 FreeRTOS 应用程序时,它很可能停止在 IDLE 任务中,并且只有该空闲任务显示在调试视图中:

停止 FreeROTS 应用程序

我需要的是检查其他任务或堆栈的简单方法。

FreeRTOS Eclipse GDB 插件

我知道有两个插件可以简化 Eclipse 中 FreeRTOS 的调试:

  1. Wittenstein/High Integrity System Plugins(参见 Kinetis 的 DIY 免费工具链:第 5 部分 – FreeRTOS Eclipse Kernel Awareness with GDB ):免费,但不开源,需要从 Wittenstein 注册和下载。它们显示任务、队列和计时器,但不允许切换到给定的任务堆栈。

    高完整性系统插件中的任务表
  2. 来自 Code Confidence ( http://www.codeconfidence.com/freertos-tools.shtml ) 的插件。这不是开源的,也不是免费的(每个开发者席位 100 英镑,所以我们的课程遥不可及)。此外,它需要特殊的启动配置,因此不支持 GNU ARM Eclipse 启动。有一个demo模式允许2个线程,2分钟后调试结束。

    具有代码置信度插件的多线程

FreeRTOS GDB 任务回溯切换器

我在互联网上搜索了一些可以帮助我查看任务堆栈/线程的东西,并在 FreeRTOS 社区的贡献端口下找到了一个很酷的贡献( http://interactive.freertos.org/entries/23468301-Tasks-backtrace- switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support- ):这是一个很好的例子,说明如何使用 GDB 命令来自定义调试 :-)。

该方法有两个部分:

  1. 自定义 FreeRTOS vPortPendSVDHandler()
  2. 带有自定义命令的 GDB 脚本,用于显示和切换线程

GDB 脚本正在使用和设置变量,然后 GDB 脚本使用这些变量来切换上下文。这实际上是一个非常酷的想法,我很快就让这种方法奏效了。

FreeRTOS 端口集成

为了使其更易于使用,我已将该方法集成到 FreeRTOS Processor Expert 组件中。因此,通过简单的设置,我可以打开该自定义处理程序:


Processor Expert Component 打开 GDB Helper

该设置会启用我已添加到 FreeRTOSConfig.h 的自定义 FreeRTOS 配置:


 /*-----------------------------------------------------------
 * GDB <span data-mce-bogus="1" class="mceItemHidden"><span class="hiddenSpellError" pre="GDB " data-mce-bogus="1">backtrace</span></span> handler support
 * See http://interactive.freertos.org/entries/23468301-Tasks-<span class="hiddenSpellError" pre="stack " data-mce-bogus="1">backtrace</span>-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
 *----------------------------------------------------------*/
#define configGDB_HELPER (1 &amp;&amp; configCPU_FAMILY_IS_ARM(configCPU_FAMILY) &amp;&amp; (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */

有了这个定义,我也可以在没有 Processor Expert 的情况下轻松打开和关闭它。该组件将 GDB 脚本复制为:


 /*-----------------------------------------------------------
 * GDB <span data-mce-bogus="1" class="mceItemHidden"><span class="hiddenSpellError" pre="GDB " data-mce-bogus="1">backtrace</span></span> handler support
 * See http://interactive.freertos.org/entries/23468301-Tasks-<span class="hiddenSpellError" pre="stack " data-mce-bogus="1">backtrace</span>-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
 *----------------------------------------------------------*/
#define configGDB_HELPER (1 &amp;&amp; configCPU_FAMILY_IS_ARM(configCPU_FAMILY) &amp;&amp; (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */

用法

在设置中启用 GDB Helper 选项。它将创建 GDB 脚本和一个帮助文本文件(以防万一您不记得这篇博客文章):


使用 GDB 脚本生成的文件

默认情况下,.* 文件在 Eclipse 项目中不可见。我需要自定义视图以取消过滤 .* 资源:

Eclipse 项目过滤器设置

我需要从 .gdbinit-FreeRTOS-helpers 脚本文件添加自定义 gdb 命令。


 /*-----------------------------------------------------------
 * GDB <span data-mce-bogus="1" class="mceItemHidden"><span class="hiddenSpellError" pre="GDB " data-mce-bogus="1">backtrace</span></span> handler support
 * See http://interactive.freertos.org/entries/23468301-Tasks-<span class="hiddenSpellError" pre="stack " data-mce-bogus="1">backtrace</span>-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
 *----------------------------------------------------------*/
#define configGDB_HELPER (1 &amp;&amp; configCPU_FAMILY_IS_ARM(configCPU_FAMILY) &amp;&amp; (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */

对于 GDB 和 GNU ARM Eclipse 插件,GDB 的当前目录是项目根文件夹。否则您需要指定完整路径以确保 GDB 找到该文件。

我可以使用调试/启动配置中的“source”命令来执行此操作,因此每次我在 Eclipse 中启动调试器时都会执行它:


调试器设置和命令

当我停止目标时,我切换到 GDB 控制台(单击 arm-none-eabi-gdb 或在控制台视图中选择它):


GDB控制台视图

在控制台中,我使用


 /*-----------------------------------------------------------
 * GDB <span data-mce-bogus="1" class="mceItemHidden"><span class="hiddenSpellError" pre="GDB " data-mce-bogus="1">backtrace</span></span> handler support
 * See http://interactive.freertos.org/entries/23468301-Tasks-<span class="hiddenSpellError" pre="stack " data-mce-bogus="1">backtrace</span>-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
 *----------------------------------------------------------*/
#define configGDB_HELPER (1 &amp;&amp; configCPU_FAMILY_IS_ARM(configCPU_FAMILY) &amp;&amp; (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */

显示所有任务及其任务句柄:

freertos_show_threads


 /*-----------------------------------------------------------
 * GDB <span data-mce-bogus="1" class="mceItemHidden"><span class="hiddenSpellError" pre="GDB " data-mce-bogus="1">backtrace</span></span> handler support
 * See http://interactive.freertos.org/entries/23468301-Tasks-<span class="hiddenSpellError" pre="stack " data-mce-bogus="1">backtrace</span>-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
 *----------------------------------------------------------*/
#define configGDB_HELPER (1 &amp;&amp; configCPU_FAMILY_IS_ARM(configCPU_FAMILY) &amp;&amp; (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */

我切换到具有该句柄的任务:


切换到 Shell 任务

现在我可以检查该线程的调用链。

重要提示: 不要踩,只检查堆栈。稍后会详细介绍。

我可以用同样的方式检查其他任务堆栈或在任务中设置断点。

在恢复执行之前,请确保您切换回我们停止执行的上下文。为此用途:


 /*-----------------------------------------------------------
 * GDB <span data-mce-bogus="1" class="mceItemHidden"><span class="hiddenSpellError" pre="GDB " data-mce-bogus="1">backtrace</span></span> handler support
 * See http://interactive.freertos.org/entries/23468301-Tasks-<span class="hiddenSpellError" pre="stack " data-mce-bogus="1">backtrace</span>-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
 *----------------------------------------------------------*/
#define configGDB_HELPER (1 &amp;&amp; configCPU_FAMILY_IS_ARM(configCPU_FAMILY) &amp;&amp; (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */



使用 freertos_restore_running_context 恢复上下文

怎么运行的

了解发生了什么很重要


 /*-----------------------------------------------------------
 * GDB <span data-mce-bogus="1" class="mceItemHidden"><span class="hiddenSpellError" pre="GDB " data-mce-bogus="1">backtrace</span></span> handler support
 * See http://interactive.freertos.org/entries/23468301-Tasks-<span class="hiddenSpellError" pre="stack " data-mce-bogus="1">backtrace</span>-switcher-viewer-snippet-for-debugger-gcc-gdb-ARM-Cortex-M3-MPU-port-Eclipse-support-
 *----------------------------------------------------------*/
#define configGDB_HELPER (1 &amp;&amp; configCPU_FAMILY_IS_ARM(configCPU_FAMILY) &amp;&amp; (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */

.gdbinit-FreeRTOS-helpers 中的命令:

  1. 它将任务句柄写入全局变量
  2. 触发 PendSV 异常以调用自定义 PendSV 处理程序
  3. 自定义 PendSV 处理程序将在 brkt(断点)指令处停止以停止调试器
  4. 该脚本将执行指令步骤并停止以显示线程堆栈

因此,了解脚本实际上在目标上执行代码很重要。这就是为什么不要继续进入切换的上下文很重要,除非你知道你这样做!基本上切换上下文实际上是通过 GDB 调试器切换上下文。

概括

该 GDB 助手对我来说工作得很好,并且使调试 FreeRTOS 应用程序变得更加容易。最重要的是:它不需要插件,但可以与普通的 GDB 命令一起使用,因此可以轻松采用或更改。

所有资源都可以在 GitHub 上找到。请参阅文章末尾的链接。 FreeRTOS 组件将随 SourceForge 上的下一个版本提供。如果您想在“正式”发布之前获取并试用当前的 .PEupd 文件,请通过电子邮件与我联系(请参阅 关于 ),我可以提供它。

接下来会发生什么?

  • 添加对 Cortex-M0+ 的支持(我已经使用 Cortex-M4(F) 对其进行了测试)
  • 添加一个功能,我可以指定任务名称而不是上下文切换的任务句柄地址

我希望找到一个不错的 GDB 前端或无需编写插件即可轻松向 Eclipse 添加按钮的东西?有人有想法吗?也许我们可以一起构建一个开源插件?寻找志愿者:-)。