openvela 使用 VSCode 调试 SIM 环境

一、概述

本指南详细阐述了如何在 Visual Studio Code (VSCode) 中配置和使用 GDB,以实现对 openvela sim 仿真环境的图形化调试。通过 VSCode,您可以获得现代化的调试体验,包括设置断点、查看调用栈、监视变量和内存,从而显著提升开发与排错效率。

核心流程包括:

  1. 环境准备:安装必要的 VSCode 扩展。
  2. 项目配置:创建并配置 launch.json 文件,以告知 VSCode 如何启动调试会话。
  3. 实战调试:通过一个实际案例,演示如何启动调试、设置断点并分析程序状态。
  4. 高级主题:解决在特定场景(如 SMP、网络功能)下可能遇到的问题。

二、准备工作

在开始调试前,请确保您的开发环境满足以下要求。

1、环境要求

  • Visual Studio Code:已安装。
  • C/C++ 扩展:这是 VSCode 提供 C/C++ 语言支持和调试能力的核心插件。
  • 已编译的 sim 目标:已成功编译 openvela 的 sim 版本,并确保生成了包含调试信息的可执行文件 (nuttx)。编译时必须包含 -g 或 -g3 标志。

2、VSCode 环境设置

步骤 1:安装 C/C++ 扩展

在 VSCode 的扩展市场中搜索 C/C++(由 Microsoft 发布),并单击安装。

步骤 2:打开项目工作区

启动 VSCode,通过菜单 File > Add Folder to Workspace...,将您的 openvela 项目根目录添加进来。这能确保 VSCode 正确解析 launch.json 中的 ${workspaceFolder} 变量。

三、调试配置 (launch.json)

launch.json 文件是 VSCode 调试功能的核心,它定义了如何启动和附加到您的程序。

1、创建 launch.json

  1. 切换到 VSCode 的 "Run and Debug" 视图(快捷键 Ctrl+Shift+D)。
  2. 单击 "create a launch.json file" 链接。
  3. 在弹出的选择框中,选择 C++ (GDB/LLDB)
  4. VSCode 将会自动生成一个 launch.json 模板文件,并保存在项目根目录的 .vscode 文件夹下。

2、配置 launch.json

将 launch.json 的内容替换为以下配置。此配置专门为调试 openvela sim 环境定制。

复制代码
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug openvela (sim)",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/nuttx/nuttx",
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/nuttx",
            "environment": [],
            "console": "externalTerminal",
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

配置项解析

属性 说明
name Debug openvela (sim) 调试配置的名称,将显示在 VSCode 的调试下拉菜单中。
type cppdbg 指定使用 C/C++ 扩展进行调试。
request launch 表示这是一个 "启动" 型的调试会话,VSCode 将负责启动程序。
program ${workspaceFolder}/nuttx/nuttx 关键配置项 。 指定要调试的可执行文件的路径。${workspaceFolder} 代表您在 VSCode 中打开的项目根目录。
stopAtEntry false 如果设为 true,程序会在入口点(如 _start)处自动暂停。 通常设为 false,让程序直接运行到我们设置的断点。
cwd ${workspaceFolder}/nuttx 设置被调试程序的工作目录。 对于 sim 环境,这通常是包含 nuttx 可执行文件的目录。
console externalTerminal 指定在一个外部终端 中运行程序。 这对于需要与 NuttShell (NSH) 交互的 sim 环境至关重要,您可以在该终端中输入命令。
MIMode gdb 指定使用的调试器后端为 GDB。
setupCommands [...] GDB 启动后、程序运行前执行的命令。 这里默认启用了 "pretty-printing",以更友好的格式显示 STL 等复杂数据结构。

四、调试实战

下面,我们以调试 ping 命令为例,走完整个流程。

步骤 1:打开源码并设置断点

在 VSCode 中,打开文件 apps/system/ping/ping.c。在 ping_main 函数的入口处(或任意您感兴趣的行),点击行号左侧的空白区域,设置一个红点断点。

步骤 2:启动调试会话

按下 F5 键或点击 "Run and Debug" 视图中的绿色启动按钮。VSCode 将:

  • 启动 GDB。
  • 打开一个新的外部终端窗口。
  • 在该终端中运行 nuttx 程序,您会看到 NSH 的启动提示符 nsh>。

步骤 3:触发断点

在 nsh> 提示符所在的外部终端中,输入触发断点的命令:

复制代码
nsh> ping 127.0.0.1

步骤 4:分析程序状态

当程序执行到 ping_main 时,您会看到:

  • VSCode 窗口自动获得焦点。
  • 代码视图中的断点行高亮显示。
  • 左侧的调试面板中填充了实时信息:
    • VARIABLES:显示当前作用域内的局部变量和全局变量的值。
    • WATCH:您可以添加表达式来持续监视其值的变化。
    • CALL STACK:清晰地展示了函数调用栈,帮助您理解程序的执行路径。
    • BREAKPOINTS:管理您设置的所有断点。

五、高级主题与常见问题

1、处理 SMP 调试中的 SIGUSR1 信号

问题现象

如果您的 openvela 配置启用了对称多处理(SMP),在调试时程序可能会在启动后不久就因 SIGUSR1 信号而意外暂停。

原因分析

openvela 在 SMP 模式下使用 SIGUSR1 信号进行核间任务调度和通信。默认情况下,GDB 会捕获所有信号并暂停程序,这干扰了系统的正常运行。

解决方案

您可以通过创建 GDB 的全局初始化脚本,让它忽略此信号。

  1. 创建一个文件:~/.gdbinit(位于您的用户主目录下)。

  2. 在该文件中添加以下命令:

    复制代码
    # Instruct GDB to not stop or print a message for SIGUSR1
    handle SIGUSR1 nostop noprint
  3. 保存文件。GDB 在每次启动时都会自动加载并执行此文件中的命令,从而解决了该问题。

2、为 sim 获取 Root 权限

问题场景

sim 环境的某些高级功能,特别是网络相关的(如使用 TAP 设备与主机系统通信),需要 root 权限才能正常工作。直接使用 sudo F5 是不可行的。

解决方案

推荐的方案是配置 sudo,允许您的用户账户在不输入密码的情况下以 root 身份运行 gdb。

  1. 配置免密 sudo。

    为了安全和规范,我们通过在 /etc/sudoers.d/ 目录下创建特定配置文件来实现。这种方法比直接修改主 sudoers 文件更安全。

    在您的 Linux 终端中执行以下命令,将 your_username 替换为您的实际用户名:

    复制代码
    # 使用您的用户名替换 your_username
    echo "your_username ALL=(ALL) NOPASSWD: /usr/bin/gdb" | sudo tee /etc/sudoers.d/gdb-nopasswd
  2. 创建 GDB 脚本。

    在您的项目根目录下(例如 openvela/),创建一个名为 sudo-gdb.sh 的文件,并填入以下内容:

    复制代码
    #!/bin/bash
    # This script acts as a wrapper to launch gdb with sudo.
    sudo /usr/bin/gdb "$$@"

    然后,赋予此脚本可执行权限:

    复制代码
    chmod +x sudo-gdb.sh
  3. 修改 launch.json。

    修改 .vscode/launch.json 文件,在您的调试配置中添加 "miDebuggerPath" 属性,使其指向我们刚刚创建的脚本。

    复制代码
    {
        "name": "Debug openvela (sim) with Root",
        "type": "cppdbg",
        "request": "launch",
        "program": "${workspaceFolder}/nuttx/nuttx",
        "miDebuggerPath": "${workspaceFolder}/sudo-gdb.sh", // <-- 添加此行
        "stopAtEntry": false,
        "cwd": "${workspaceFolder}/nuttx",
        "environment": [],
        "console": "externalTerminal",
        "MIMode": "gdb",
        "setupCommands": [
            {
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            }
        ]
    }

完成以上步骤后,选择新的调试配置并按 F5 启动,您的 sim 程序就会以 root 权限运行。

六、参考资料

相关推荐
自由的晚风6 个月前
基于小米Open-Vela开源系统的高级计算器实现 | 支持C++数学函数与 LVGL UI
经验分享·物联网·开源·嵌入式·小米·nuttx·openvela
byte轻骑兵10 个月前
OpenVela——专为AIoT领域打造的开源操作系统
开源·openvela
一只搬砖的猹10 个月前
小米vela系统(基于开源nuttx内核)——openvela开源项目
linux·开源·小米·rtos·nuttx·openvela·apache2.0