4、probe-rs深度解析:安装、工具链与VS Code集成

probe-rs,说白了就是嵌入式Rust调试的瑞士军刀。它把调试探针、烧录、GDB通信这些杂事全包了。我刚开始用的时候也觉得这东西就是个烧录工具,后来才发现它远不止这么简单。

4.1 probe-rs是什么?为什么它这么重要?

传统嵌入式开发,你得装OpenOCD、装GDB、装各种厂商的驱动。probe-rs把这些全整合了。它直接通过USB跟调试探针通信,不需要中间人。你想想看,少了一层依赖,出问题的概率就少了一大半。

核心能力一览:

  • 烧录:支持ELF/HEX/BIN格式,自动解析
  • 调试:内置GDB stub,支持断点、单步、内存查看
  • RTT:实时终端输出,比串口好用十倍
  • 硬件抽象:统一API,换探针不用改代码

我个人习惯把probe-rs看作一个硬件抽象层。不管你是用J-Link、ST-Link还是CMSIS-DAP,probe-rs都给你一套统一的接口。我在项目中遇到过最头疼的事,就是团队里有人用J-Link有人用ST-Link,烧录脚本各写各的。换成probe-rs后,一个命令通吃。

4.2 安装probe-rs

安装其实很简单,但有几个坑我得提前说。

4.2.1 标准安装方式

# 安装probe-rs工具链
cargo install probe-rs --features cli

# 验证安装
probe-rs --version

# 列出连接的调试探针
probe-rs list

嗯,这里要注意。如果你在Linux上,记得把当前用户加到plugdev组,不然没权限访问USB设备。

sudo usermod -a -G plugdev $USER
# 然后注销重新登录

我曾经踩过的坑:Windows上如果装了ST-Link的官方驱动,probe-rs可能认不到探针。原因是WinUSB驱动冲突。解决办法是用Zadig工具把探针的驱动换成WinUSB。别问我怎么知道的,那次折腾了我一下午。

4.2.2 从源码编译(可选)

如果你想用最新特性,或者你的平台没有预编译包,可以自己编译:

git clone https://github.com/probe-rs/probe-rs
cd probe-rs
cargo build --release --features cli
# 编译产物在 target/release/probe-rs

编译时间有点长,大概5-10分钟。我建议除非必要,否则用cargo install就够了。

4.3 cargo-flash:一键烧录

cargo-flash是probe-rs提供的Cargo子命令。说白了,就是cargo flash代替了cargo build + 手动烧录的繁琐流程。

4.3.1 基本用法

# 烧录当前项目
cargo flash --chip STM32F103C8

# 指定芯片和探针
cargo flash --chip nRF52840_xxAA --probe 0

# 烧录并复位运行
cargo flash --chip STM32F407VG --reset

你可能会问:芯片型号怎么查?用probe-rs chip list可以列出所有支持的芯片。我数过,大概有3000多种。基本上你能想到的MCU都在里面。

4.3.2 配置文件

每次敲--chip太麻烦。我习惯在项目根目录建一个.cargo/config.toml:

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-rs run --chip STM32F103C8"

[env]
DEFMT_LOG = "debug"

这样你只需要:

cargo run

就能自动编译+烧录+运行。省事多了。

小技巧:如果你用defmt做日志,记得在配置里加上DEFMT_LOG环境变量。不然你什么都看不到,还以为程序没跑起来。

4.4 cargo-embed:调试与RTT的瑞士军刀

cargo-embed比cargo-flash更进一步。它不仅能烧录,还能启动GDB调试、打开RTT终端、监控内存。我90%的调试工作都靠它完成。

4.4.1 安装与配置

cargo install cargo-embed

然后你需要一个Embed.toml配置文件,放在项目根目录:

[default.general]
chip = "STM32F103C8"

[default.flashing]
enabled = true
halt_afterwards = false

[default.rtt]
enabled = true

[default.gdb]
enabled = true
gdb_connection_string = "pipe:arm-none-eabi-gdb"

这个配置的意思是:烧录后直接运行,开启RTT输出,同时启动GDB服务。你可以在VS Code里连上这个GDB服务进行调试。

4.4.2 启动调试会话

cargo embed

就这么简单。你会看到终端里同时显示RTT日志和GDB端口信息。我个人习惯开两个终端:一个跑cargo embed,另一个用GDB连上去做断点调试。

RTT vs 串口:为什么我推荐RTT?

  • 速度:RTT走SWD,速度是串口的几十倍
  • 不占外设:串口需要UART引脚,RTT不需要
  • 双向通信:RTT支持输入,你可以给MCU发命令
  • 低延迟:RTT延迟在微秒级,串口在毫秒级

4.5 与VS Code集成

命令行虽然强大,但图形化调试确实更直观。VS Code加上probe-rs插件,体验不输IDE。

4.5.1 安装插件

在VS Code扩展市场搜索probe-rs,安装官方插件。装好后,你会在左侧看到一个新的调试面板。

4.5.2 配置launch.json

按F5,选择probe-rs调试器,VS Code会自动生成.vscode/launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "probe-rs",
            "request": "launch",
            "name": "probe-rs Debug",
            "cwd": "${workspaceFolder}",
            "chip": "STM32F103C8",
            "flashingConfig": {
                "flashingEnabled": true,
                "haltAfterReset": false
            },
            "coreConfigs": [
                {
                    "coreIndex": 0,
                    "programBinary": "target/thumbv7m-none-eabi/debug/your-project"
                }
            ]
        }
    ]
}

这里有个坑:programBinary路径要跟你cargo build的输出一致。我建议用${workspaceFolder}/target/thumbv7m-none-eabi/debug/${workspaceFolderBasename}这种动态路径,省得每次改。

4.5.3 调试体验

配置好后,按F5就能开始调试。你能看到:

  • 断点:点一下行号就能设断点,跟调试桌面程序一样
  • 变量监视:鼠标悬停在变量上就能看到值
  • 调用栈:能看到当前执行到哪个函数
  • 外设寄存器:可以直接查看和修改MCU的寄存器值

我的调试习惯:我会在main函数入口设一个断点,然后单步执行。这样能确保MCU启动流程没问题。如果连main都进不去,那肯定是启动文件或者链接脚本的问题。

4.6 知识体系总览

下面这张图总结了probe-rs的完整工作流程:

probe-rs 工作流程与工具链 用户代码 (Rust) cargo-flash / cargo-embed VS Code 调试界面 probe-rs 核心引擎 烧录引擎 ELF解析 / 校验 调试引擎 GDB stub / 断点 RTT引擎 实时终端 / 双向 探针抽象层 (统一API) J-Link | ST-Link | CMSIS-DAP | FTDI 目标硬件 (MCU) SWD / JTAG 接口 核心优势:统一接口 + 跨平台 + 零外部依赖

4.7 常见问题与避坑指南

问题 原因 解决方案
probe-rs list 找不到探针 驱动冲突或权限不足 Linux加plugdev组;Windows用Zadig换WinUSB驱动
烧录后程序不运行 halt_afterwards = true 在Embed.toml里设置halt_afterwards = false
RTT没有输出 没启用defmt或RTT通道 检查Cargo.toml是否加了defmt依赖,Embed.toml是否开启rtt
VS Code连不上GDB 端口被占用或路径不对 先关掉其他调试会话,检查launch.json里的端口号

我曾经踩过的坑:有一次我烧录nRF52840,怎么都连不上。折腾了两小时,最后发现是USB线的问题。那根线只能充电不能传数据。所以,如果你遇到莫名其妙的连接问题,先换根USB线试试。这听起来很蠢,但真的能解决80%的问题。

4.8 小结

probe-rs把嵌入式调试的门槛降了一大截。你不需要再折腾OpenOCD的配置文件,不需要记一堆GDB命令。一个cargo embed搞定烧录、调试、日志输出。配合VS Code,调试体验跟桌面开发没什么区别。

我个人建议:刚开始用的时候,先跑通cargo flash烧录一个LED闪烁程序。确认硬件连接没问题后,再上cargo embed和VS Code调试。一步一步来,别想一口吃成胖子。