Skip to content
Back to skills

Embedded Rust

BSecurity

Embedded Rust skill for bare-metal microcontroller development. Use when using probe-rs or cargo-embed for flashing and debugging, setting up defmt logging, using the RTIC framework, configuring cortex-m-rt startup, writing no_std + no_main firmware, or choosing between panic-halt and panic-semihosting. Activates on queries about embedded Rust, probe-rs, cargo-embed, defmt, RTIC, cortex-m-rt, no_std embedded, or panic handling in embedded Rust.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
toolsrustgobashdebugginggitbackend

Security analysis

B75/100
  • criticalPipes output to a shell interpreter
  • criticalDownloads and executes remote scripts — classic supply chain attack

Pro scans all 2 files and shows the line behind each finding

Scanned October 17, 2026

npx -y skills add NetVar1337/agent-skill-canon --skill embedded-rust --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Embedded Rust?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Embedded Rust
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/netvar1337-embedded-rust/badge)](https://www.skillsdirectory.com/skills/netvar1337-embedded-rust)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: embedded-rust
description: Embedded Rust skill for bare-metal microcontroller development. Use when using probe-rs or cargo-embed for flashing and debugging, setting up defmt logging, using the RTIC framework, configuring cortex-m-rt startup, writing no_std + no_main firmware, or choosing between panic-halt and panic-semihosting. Activates on queries about embedded Rust, probe-rs, cargo-embed, defmt, RTIC, cortex-m-rt, no_std embedded, or panic handling in embedded 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.

## 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?"

## Workflow

### 1. Project setup

```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"] }

# Embassy (async embedded) — alternative to RTIC
# 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

# .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
```

### 2. Minimal bare-metal program

```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+ | `thumbv6m-none-eabi` |
| Cortex-M3 | `thumbv7m-none-eabi` |
| Cortex-M4 (no FPU) | `thumbv7em-none-eabi` |
| Cortex-M4F / M7 | `thumbv7em-none-eabihf` |
| Cortex-M33 | `thumbv8m.main-none-eabihf` |
| RISC-V RV32IMAC | `riscv32imac-unknown-none-elf` |

```bash
rustup target add thumbv7em-none-eabihf
```

### 3. probe-rs — flash and debug

```bash
# Install probe-rs
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

# Interactive debug session
probe-rs debug --chip STM32F411CEUx target/thumbv7em-none-eabihf/release/firmware

# List connected probes
probe-rs list

# Supported chips
probe-rs chip list | grep STM32
```

With `cargo`:

```bash
# Using the runner in .cargo/config.toml
cargo run --release           # builds, flashes, and streams defmt logs
cargo build --release         # build only
```

### 4. defmt — efficient logging

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
# RTT (fastest, needs debug probe connected)
defmt-rtt = "0.4"

# Semihosting (slower, works without RTT support)
defmt-semihosting = "0.1"
```

### 5. RTIC — Real-Time Interrupt-driven Concurrency

```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

| Crate | Behavior | Use when |
|-------|----------|----------|
| `panic-halt` | Infinite loop | Production, no debug probe |
| `panic-probe` | defmt message + halt | Development with probe-rs |
| `panic-semihosting` | GDB semihosting output | Development with GDB |
| `panic-reset` | Hard reset | Watchdog-style recovery |

```toml
# Choose exactly one panic handler
[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).

## Related skills

- Use `skills/embedded/openocd-jtag` for OpenOCD-based debugging alternative to probe-rs
- Use `skills/rust/rust-no-std` for `#![no_std]` patterns and constraints
- Use `skills/embedded/linker-scripts` for memory layout configuration
- Use `skills/rust/rust-cross` for cross-compilation toolchain setup

Files in this skill

  • SKILL.md6.2 KB
  • references/embedded-rust-targets.md2.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.