2. 开发环境搭建:ARM Cortex-M与RISC-V工具链配置,OpenOCD与probe-rs调试器选择
说实话,嵌入式开发的第一步往往最让人头疼。工具链没配好,后面全是白搭。我见过太多新手卡在环境搭建这一步,代码写好了却烧不进去,或者烧进去跑不起来——最后发现是调试器配置错了。
这一章,咱们就把 ARM Cortex-M 和 RISC-V 两条路的工具链捋清楚。同时聊聊 OpenOCD 和 probe-rs 这两个调试器该怎么选。嗯,都是我在项目里踩过坑之后总结出来的经验。
2.1 ARM Cortex-M 工具链配置
ARM Cortex-M 系列在嵌入式领域太常见了。STM32、nRF52、LPC 这些芯片,内核都是 Cortex-M。Rust 要编译到这些芯片上,需要一套完整的交叉编译工具链。
2.1.1 安装 Rust 目标支持
首先,你得告诉 Rust 编译器,我们要编译到 ARM Cortex-M 架构。这通过添加 target 来实现:
rustup target add thumbv6m-none-eabi # Cortex-M0, M0+
rustup target add thumbv7m-none-eabi # Cortex-M3
rustup target add thumbv7em-none-eabi # Cortex-M4, M7(无FPU)
rustup target add thumbv7em-none-eabihf # Cortex-M4, M7(有FPU)
rustup target add thumbv8m.main-none-eabi # Cortex-M33, M55
我个人习惯把常用的 target 一次性全加上。反正不占多少空间,省得后面换芯片时再折腾。
2.1.2 安装 ARM 交叉编译工具链
Rust 编译器只负责生成机器码。但链接、生成二进制文件这些活,还得靠 ARM 的 GNU 工具链。我推荐用 arm-none-eabi-gcc 系列:
# Ubuntu/Debian
sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi
# macOS (Homebrew)
brew install arm-none-eabi-gcc
# Windows (MSYS2)
pacman -S mingw-w64-x86_64-arm-none-eabi-gcc
这里有个坑——版本问题。我曾经在项目里用了太老的 arm-none-eabi-gcc,结果链接出来的二进制文件在芯片上跑着跑着就死机了。后来发现是链接脚本的兼容性问题。所以,我建议用 2020 年之后的版本。
2.1.3 配置 Cargo 项目
新建一个 Rust 嵌入式项目时,需要配置 .cargo/config.toml:
[target.thumbv7em-none-eabihf]
linker = "arm-none-eabi-gcc"
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-nostartfiles",
]
[build]
target = "thumbv7em-none-eabihf"
这里的 link.x 是链接脚本,一般由 cortex-m-rt crate 提供。你不需要自己写,但得知道它在哪里。
2.2 RISC-V 工具链配置
RISC-V 这两年发展很快。我手头有好几个项目已经切到了 RISC-V 内核的芯片,比如 GD32V、K210、ESP32-C 系列。Rust 对 RISC-V 的支持其实比 ARM 还要干净一些。
2.2.1 安装 Rust 目标支持
rustup target add riscv32imac-unknown-none-elf # 带乘法和原子指令
rustup target add riscv32imc-unknown-none-elf # 只有乘法和压缩指令
rustup target add riscv64imac-unknown-none-elf # 64位版本
RISC-V 的 target 命名很直观。比如 riscv32imac 表示:32位、带乘法指令(M)、原子指令(A)、压缩指令(C)。你想想看,芯片手册里一般都会写清楚支持哪些扩展,对着选就行。
2.2.2 安装 RISC-V GCC 工具链
# Ubuntu/Debian
sudo apt install gcc-riscv64-unknown-elf binutils-riscv64-unknown-elf
# macOS (Homebrew)
brew install riscv64-elf-gcc
# 或者从 SiFive 官方下载预编译包
wget https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-...
2.2.3 配置 Cargo 项目
[target.riscv32imac-unknown-none-elf]
linker = "riscv64-unknown-elf-gcc"
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-nostartfiles",
]
[build]
target = "riscv32imac-unknown-none-elf"
嗯,这里和 ARM 的配置几乎一样。只是 linker 换成了 RISC-V 的版本。Rust 的嵌入式生态在这方面做得挺统一的。
2.3 OpenOCD 与 probe-rs 调试器选择
工具链配好了,接下来就是调试器。这是把代码烧进芯片、在芯片上调试的关键环节。目前主流的选择有两个:OpenOCD 和 probe-rs。
我两个都用过,各有优劣。下面这张图能帮你快速理解它们的定位:
2.3.1 OpenOCD:老牌劲旅
OpenOCD 是嵌入式调试的老牌工具。它支持几乎所有的调试器:J-Link、ST-Link、CMSIS-DAP、FTDI 等等。配置起来稍微麻烦一点,但胜在稳定。
安装 OpenOCD:
# Ubuntu/Debian
sudo apt install openocd
# macOS
brew install openocd
# 或者从源码编译
git clone https://github.com/openocd-org/openocd.git
cd openocd
./bootstrap
./configure --enable-jlink --enable-stlink --enable-cmsis-dap
make -j4
sudo make install
使用 OpenOCD 调试时,一般需要写一个配置文件。比如针对 STM32F4 的配置:
# stm32f4.cfg
source [find interface/stlink.cfg]
source [find target/stm32f4x.cfg]
# 可选:设置 SWD 速度
adapter speed 4000
然后启动 OpenOCD:
openocd -f stm32f4.cfg
再开一个终端,用 GDB 连接:
arm-none-eabi-gdb target/thumbv7em-none-eabihf/debug/my_firmware
(gdb) target remote :3333
(gdb) load
(gdb) continue
2.3.2 probe-rs:Rust 原生调试器
probe-rs 是 Rust 社区自己开发的调试工具。它最大的优势是——零配置。你不需要写配置文件,不需要启动 GDB,一条命令就能烧录和调试。
安装 probe-rs:
# 通过 cargo 安装
cargo install probe-rs --features cli
# 或者用包管理器
# Ubuntu/Debian (需要添加仓库)
sudo apt install probe-rs
使用 probe-rs 烧录:
# 自动检测调试器并烧录
probe-rs run --chip STM32F407VGTx target/thumbv7em-none-eabihf/debug/my_firmware
# 或者指定调试器
probe-rs run --chip STM32F407VGTx --probe 0483:3748 target/.../my_firmware
调试也很简单:
# 启动调试会话
probe-rs debug --chip STM32F407VGTx target/.../my_firmware
它会自动启动一个 GDB 服务器,你直接用 GDB 连接就行。或者用 VS Code 的插件,图形化调试。
2.3.3 如何选择?
我把两个调试器的核心差异整理成了表格,方便你对比:
| 特性 | OpenOCD | probe-rs |
|---|---|---|
| 配置复杂度 | 高,需要写配置文件 | 低,自动检测 |
| 调试器支持 | 非常广泛(J-Link, ST-Link, CMSIS-DAP, FTDI...) | 有限(CMSIS-DAP, J-Link, ST-Link) |
| 速度 | 中等 | 快(Rust 实现,零拷贝) |
| Rust 生态集成 | 一般,需要手动配置 | 优秀,cargo 原生支持 |
| 稳定性 | 非常稳定,久经考验 | 持续迭代中,偶有 bug |
| 社区资源 | 丰富,文档多 | 较少,但增长快 |
| 适用场景 | 量产项目、复杂调试、多调试器环境 | 快速原型、Rust 项目、新手友好 |
我个人建议:
- 如果你是新手,或者只是做原型验证,直接用 probe-rs。省心。
- 如果你在做量产项目,或者需要支持多种调试器,用 OpenOCD。稳。
- 如果你两个都装,也不冲突。我自己的开发机上就是两个都装了,根据项目需求切换。
2.4 验证环境是否配置成功
工具链和调试器都装好了,怎么知道配没配对?写个最简单的程序试试:
// src/main.rs
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use panic_halt as _;
#[entry]
fn main() -> ! {
loop {}
}
编译:
cargo build
如果编译通过,说明 Rust 工具链和目标支持没问题。然后烧录到芯片上,如果能正常运行(比如 LED 闪烁),说明调试器配置正确。