FreeRTOS 可能是最流行的 RTOS,我喜欢它:它高效、具有许多功能、简单且易于使用。但是,尽管它很受欢迎,但使用 Eclipse 和 GDB 等开源工具对其进行调试确实不是那么用户友好:与商业解决方案相比,调试线程和任务是一件痛苦的事情。对于本学期的大学课程,我一直在寻找对我的学生来说易于使用的东西。最后,我设法使用了一个 GDB 帮助程序,它使事情变得更容易:我现在可以使用 GDB 在 Eclipse 中切换任务线程:-)
切换到 Shell 任务
问题是:当我停止运行的 FreeRTOS 应用程序时,它很可能停止在 IDLE 任务中,并且只有该空闲任务显示在调试视图中:
停止 FreeROTS 应用程序
我需要的是检查其他任务或堆栈的简单方法。
FreeRTOS Eclipse GDB 插件
我知道有两个插件可以简化 Eclipse 中 FreeRTOS 的调试:
-
Wittenstein/High Integrity System Plugins(参见
Kinetis 的 DIY 免费工具链:第 5 部分 – FreeRTOS Eclipse Kernel Awareness with GDB
):免费,但不开源,需要从 Wittenstein 注册和下载。它们显示任务、队列和计时器,但不允许切换到给定的任务堆栈。
高完整性系统插件中的任务表 -
来自 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 命令来自定义调试 :-)。
该方法有两个部分:
- 自定义 FreeRTOS vPortPendSVDHandler()
- 带有自定义命令的 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 && configCPU_FAMILY_IS_ARM(configCPU_FAMILY) && (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 && configCPU_FAMILY_IS_ARM(configCPU_FAMILY) && (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 && configCPU_FAMILY_IS_ARM(configCPU_FAMILY) && (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 && configCPU_FAMILY_IS_ARM(configCPU_FAMILY) && (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 && configCPU_FAMILY_IS_ARM(configCPU_FAMILY) && (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 && configCPU_FAMILY_IS_ARM(configCPU_FAMILY) && (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 && configCPU_FAMILY_IS_ARM(configCPU_FAMILY) && (configCOMPILER==configCOMPILER_ARM_GCC)) /* 1: enable special GDB stack backtrace debug helper; 0: disabled */
.gdbinit-FreeRTOS-helpers 中的命令:
- 它将任务句柄写入全局变量
- 触发 PendSV 异常以调用自定义 PendSV 处理程序
- 自定义 PendSV 处理程序将在 brkt(断点)指令处停止以停止调试器
- 该脚本将执行指令步骤并停止以显示线程堆栈
因此,了解脚本实际上在目标上执行代码很重要。这就是为什么不要继续进入切换的上下文很重要,除非你知道你这样做!基本上切换上下文实际上是通过 GDB 调试器切换上下文。
概括
该 GDB 助手对我来说工作得很好,并且使调试 FreeRTOS 应用程序变得更加容易。最重要的是:它不需要插件,但可以与普通的 GDB 命令一起使用,因此可以轻松采用或更改。
所有资源都可以在 GitHub 上找到。请参阅文章末尾的链接。 FreeRTOS 组件将随 SourceForge 上的下一个版本提供。如果您想在“正式”发布之前获取并试用当前的 .PEupd 文件,请通过电子邮件与我联系(请参阅 关于 ),我可以提供它。
接下来会发生什么?
- 添加对 Cortex-M0+ 的支持(我已经使用 Cortex-M4(F) 对其进行了测试)
- 添加一个功能,我可以指定任务名称而不是上下文切换的任务句柄地址
我希望找到一个不错的 GDB 前端或无需编写插件即可轻松向 Eclipse 添加按钮的东西?有人有想法吗?也许我们可以一起构建一个开源插件?寻找志愿者:-)。