embedded-rust
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEmbedded Rust
Embedded Rust
Purpose
用途
Guide agents through embedded Rust development: flashing and debugging with probe-rs/cargo-embed, structured logging with defmt, the RTIC concurrency framework, cortex-m-rt startup, no_std configuration, and panic handler selection.
为开发者指引Embedded Rust开发的全流程:使用probe-rs/cargo-embed进行烧录与调试、通过defmt实现结构化日志、使用RTIC并发框架、配置cortex-m-rt启动流程、设置no_std环境,以及选择panic处理器。
Triggers
触发场景
- "How do I flash my Rust firmware to an MCU?"
- "How do I debug my embedded Rust program?"
- "How do I use defmt for logging in embedded Rust?"
- "How do I use RTIC for interrupt-driven concurrency?"
- "What does #![no_std] #![no_main] mean for embedded Rust?"
- "How do I handle panics in no_std embedded Rust?"
- "如何将Rust固件烧录到MCU中?"
- "如何调试我的嵌入式Rust程序?"
- "如何在嵌入式Rust中使用defmt进行日志记录?"
- "如何使用RTIC实现中断驱动的并发?"
- "在嵌入式Rust中#![no_std] #![no_main]是什么意思?"
- "如何在no_std嵌入式Rust中处理panic?"
Workflow
开发流程
1. Project setup
1. 项目配置
toml
undefinedtoml
undefinedCargo.toml
Cargo.toml
[package]
name = "my-firmware"
version = "0.1.0"
edition = "2021"
[dependencies]
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
defmt = "0.3"
defmt-rtt = "0.4"
panic-probe = { version = "0.3", features = ["print-defmt"] }
[package]
name = "my-firmware"
version = "0.1.0"
edition = "2021"
[dependencies]
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
defmt = "0.3"
defmt-rtt = "0.4"
panic-probe = { version = "0.3", features = ["print-defmt"] }
Embassy (async embedded) — alternative to RTIC
Embassy (异步嵌入式) — RTIC的替代方案
embassy-executor = { version = "0.5", features = ["arch-cortex-m"] }
embassy-executor = { version = "0.5", features = ["arch-cortex-m"] }
[profile.release]
opt-level = "s" # size optimization for embedded
lto = true
codegen-units = 1
debug = true # keep debug info for defmt/probe-rs
[profile.release]
opt-level = "s" # 嵌入式场景下的尺寸优化
lto = true
codegen-units = 1
debug = true # 保留调试信息以支持defmt/probe-rs
.cargo/config.toml
.cargo/config.toml
[build]
target = "thumbv7em-none-eabihf" # Cortex-M4F / M7
[target.thumbv7em-none-eabihf]
runner = "probe-rs run --chip STM32F411CEUx" # auto-run after build
rustflags = ["-C", "link-arg=-Tlink.x"] # cortex-m-rt linker script
undefined[build]
target = "thumbv7em-none-eabihf" # Cortex-M4F / M7
[target.thumbv7em-none-eabihf]
runner = "probe-rs run --chip STM32F411CEUx" # 构建完成后自动运行
rustflags = ["-C", "link-arg=-Tlink.x"] # cortex-m-rt链接脚本
undefined2. Minimal bare-metal program
2. 极简裸机程序
rust
// src/main.rs
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use defmt::info;
use defmt_rtt as _; // RTT transport for defmt
use panic_probe as _; // panic handler that prints via defmt
#[entry]
fn main() -> ! {
info!("Booting up!");
// Access peripherals via PAC or HAL
let _core = cortex_m::Peripherals::take().unwrap();
// let dp = stm32f4xx_hal::pac::Peripherals::take().unwrap();
loop {
info!("Running...");
cortex_m::asm::delay(8_000_000); // rough delay
}
}Target triples for common MCUs:
| MCU family | Target triple |
|---|---|
| Cortex-M0/M0+ | |
| Cortex-M3 | |
| Cortex-M4 (no FPU) | |
| Cortex-M4F / M7 | |
| Cortex-M33 | |
| RISC-V RV32IMAC | |
bash
rustup target add thumbv7em-none-eabihfrust
// src/main.rs
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use defmt::info;
use defmt_rtt as _; // defmt的RTT传输层
use panic_probe as _; // 通过defmt打印信息的panic处理器
#[entry]
fn main() -> ! {
info!("Booting up!");
// 通过PAC或HAL访问外设
let _core = cortex_m::Peripherals::take().unwrap();
// let dp = stm32f4xx_hal::pac::Peripherals::take().unwrap();
loop {
info!("Running...");
cortex_m::asm::delay(8_000_000); // 粗略延时
}
}常见MCU对应的目标三元组:
| MCU系列 | 目标三元组 |
|---|---|
| Cortex-M0/M0+ | |
| Cortex-M3 | |
| Cortex-M4 (无FPU) | |
| Cortex-M4F / M7 | |
| Cortex-M33 | |
| RISC-V RV32IMAC | |
bash
rustup target add thumbv7em-none-eabihf3. probe-rs — flash and debug
3. probe-rs — 烧录与调试
bash
undefinedbash
undefinedInstall probe-rs
安装probe-rs
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh
Flash firmware
烧录固件
probe-rs run --chip STM32F411CEUx target/thumbv7em-none-eabihf/release/firmware
probe-rs run --chip STM32F411CEUx target/thumbv7em-none-eabihf/release/firmware
Interactive debug session
交互式调试会话
probe-rs debug --chip STM32F411CEUx target/thumbv7em-none-eabihf/release/firmware
probe-rs debug --chip STM32F411CEUx target/thumbv7em-none-eabihf/release/firmware
List connected probes
列出已连接的调试器
probe-rs list
probe-rs list
Supported chips
支持的芯片
probe-rs chip list | grep STM32
With `cargo`:
```bashprobe-rs chip list | grep STM32
配合`cargo`使用:
```bashUsing the runner in .cargo/config.toml
使用.cargo/config.toml中配置的runner
cargo run --release # builds, flashes, and streams defmt logs
cargo build --release # build only
undefinedcargo run --release # 构建、烧录并流式传输defmt日志
cargo build --release # 仅构建
undefined4. defmt — efficient logging
4. defmt — 高效日志
defmt (de-formatter) encodes log strings to integers, transmits minimal bytes, decodes on host:
rust
use defmt::{info, warn, error, debug, trace, Format};
// Basic logging
info!("Temperature: {} °C", temp);
warn!("Stack usage: {}/{}", used, total);
error!("I2C error: {:?}", err);
// Derive Format for custom types
#[derive(Format)]
struct Packet { id: u8, len: u16 }
info!("Received: {:?}", pkt);
// Assertions (panic with defmt message)
defmt::assert_eq!(result, expected);
defmt::assert!(condition, "message with {}", value);defmt backends (choose one):
toml
undefineddefmt(解格式化工具)将日志字符串编码为整数,传输最小化的字节数,在主机端进行解码:
rust
use defmt::{info, warn, error, debug, trace, Format};
// 基础日志
info!("Temperature: {} °C", temp);
warn!("Stack usage: {}/{}", used, total);
error!("I2C error: {:?}", err);
// 为自定义类型派生Format特性
#[derive(Format)]
struct Packet { id: u8, len: u16 }
info!("Received: {:?}", pkt);
// 断言(携带defmt信息的panic)
defmt::assert_eq!(result, expected);
defmt::assert!(condition, "message with {}", value);defmt后端(选择其一):
toml
undefinedRTT (fastest, needs debug probe connected)
RTT(速度最快,需要连接调试器)
defmt-rtt = "0.4"
defmt-rtt = "0.4"
Semihosting (slower, works without RTT support)
Semihosting(速度较慢,无需RTT支持即可工作)
defmt-semihosting = "0.1"
undefineddefmt-semihosting = "0.1"
undefined5. RTIC — Real-Time Interrupt-driven Concurrency
5. RTIC — 实时中断驱动并发
rust
// Cargo.toml
// rtic = { version = "2", features = ["thumbv7-backend"] }
#[rtic::app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [SPI1])]
mod app {
use stm32f4xx_hal::{pac, prelude::*};
use defmt::info;
#[shared]
struct Shared {
counter: u32,
}
#[local]
struct Local {}
#[init]
fn init(cx: init::Context) -> (Shared, Local) {
info!("RTIC init");
periodic_task::spawn().unwrap();
(Shared { counter: 0 }, Local {})
}
#[task(shared = [counter])]
async fn periodic_task(mut cx: periodic_task::Context) {
loop {
cx.shared.counter.lock(|c| *c += 1);
info!("Count: {}", cx.shared.counter.lock(|c| *c));
rtic_monotonics::systick::Systick::delay(500.millis()).await;
}
}
#[task(binds = EXTI0, local = [], priority = 2)]
fn button_isr(cx: button_isr::Context) {
info!("Button pressed!");
}
}rust
// Cargo.toml
// rtic = { version = "2", features = ["thumbv7-backend"] }
#[rtic::app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [SPI1])]
mod app {
use stm32f4xx_hal::{pac, prelude::*};
use defmt::info;
#[shared]
struct Shared {
counter: u32,
}
#[local]
struct Local {}
#[init]
fn init(cx: init::Context) -> (Shared, Local) {
info!("RTIC init");
periodic_task::spawn().unwrap();
(Shared { counter: 0 }, Local {})
}
#[task(shared = [counter])]
async fn periodic_task(mut cx: periodic_task::Context) {
loop {
cx.shared.counter.lock(|c| *c += 1);
info!("Count: {}", cx.shared.counter.lock(|c| *c));
rtic_monotonics::systick::Systick::delay(500.millis()).await;
}
}
#[task(binds = EXTI0, local = [], priority = 2)]
fn button_isr(cx: button_isr::Context) {
info!("Button pressed!");
}
}6. Panic handlers
6. Panic处理器
| Crate | Behavior | Use when |
|---|---|---|
| Infinite loop | Production, no debug probe |
| defmt message + halt | Development with probe-rs |
| GDB semihosting output | Development with GDB |
| Hard reset | Watchdog-style recovery |
toml
undefined| 依赖包 | 行为 | 适用场景 |
|---|---|---|
| 无限循环 | 生产环境,无调试器 |
| 输出defmt信息后暂停 | 使用probe-rs的开发环境 |
| 通过GDB semihosting输出信息 | 使用GDB的开发环境 |
| 硬重置 | 看门狗式恢复场景 |
toml
undefinedChoose exactly one panic handler
仅选择一个panic处理器
[dependencies]
panic-halt = "0.2" # or:
panic-probe = { version = "0.3", features = ["print-defmt"] }
For embedded Rust target triples reference, see [references/embedded-rust-targets.md](references/embedded-rust-targets.md).[dependencies]
panic-halt = "0.2" # 或:
panic-probe = { version = "0.3", features = ["print-defmt"] }
关于嵌入式Rust目标三元组的参考,见[references/embedded-rust-targets.md](references/embedded-rust-targets.md)。Related skills
相关技能
- Use for OpenOCD-based debugging alternative to probe-rs
skills/embedded/openocd-jtag - Use for
skills/rust/rust-no-stdpatterns and constraints#![no_std] - Use for memory layout configuration
skills/embedded/linker-scripts - Use for cross-compilation toolchain setup
skills/rust/rust-cross
- 若需替代probe-rs的OpenOCD调试方案,使用
skills/embedded/openocd-jtag - 若需了解的模式与约束,使用
#![no_std]skills/rust/rust-no-std - 若需配置内存布局,使用
skills/embedded/linker-scripts - 若需搭建交叉编译工具链,使用
skills/rust/rust-cross