domain-embedded
actionbook/rust-skills
Embedded Rust development constraints: no_std, no heap, interrupt safety, and hardware ownership patterns.
What is domain-embedded?
Use this skill when developing embedded systems, microcontrollers, or bare-metal Rust code. It provides domain constraints, design patterns, and critical rules for no_std environments where dynamic allocation, standard library, and blocking operations are forbidden.
- Enforces no_std and no-heap constraints using heapless collections and static buffers
- Ensures interrupt-safe shared state via Mutex<RefCell<T>> and critical sections
- Manages hardware peripheral ownership through singleton patterns and HAL abstractions
- Guides framework selection (RTIC for priority-based, Embassy for async state machines)
- Documents common embedded mistakes: Vec usage, missing critical sections, blocking in ISRs, unsafe peripheral access
- Provides code patterns for entry points, static state initialization, and fixed-size data structures
How to install domain-embedded
npx skills add https://github.com/actionbook/rust-skills --skill domain-embedded- Rust toolchain with embedded target support (e.g., thumbv7em-none-eabihf)
- Understanding of microcontroller architecture and interrupt handling basics
- Familiarity with Cargo.toml and .cargo/config.toml for target configuration
- Knowledge of peripheral access crates (PAC) or hardware abstraction layers (HAL) for your target
How to use domain-embedded
- 1.Review the domain constraints table to understand no_std, no-heap, real-time, and interrupt-safety rules
- 2.Check the framework comparison to choose between RTIC, Embassy, or bare-metal approaches
- 3.Apply the static peripheral code pattern for initializing and accessing hardware safely
- 4.Use heapless collections instead of Vec/Box for all dynamic data structures
- 5.Wrap shared state in Mutex<RefCell<Option<T>>> and access within interrupt::free() critical sections
- 6.Consult the common mistakes table to avoid heap allocation, missing critical sections, and blocking in ISRs
Use cases
- Developing firmware for ARM Cortex-M, RISC-V, or ESP32/STM32 microcontrollers
- Building interrupt-driven applications with real-time constraints and predictable timing
- Creating device drivers and HAL layers that safely abstract hardware peripherals
- Implementing no_std libraries and utilities for resource-constrained environments
- Debugging race conditions and interrupt safety issues in concurrent embedded code
- Embedded systems engineers and firmware developers
- Microcontroller and IoT device programmers
- Hardware abstraction layer (HAL) maintainers
- Real-time systems developers requiring deterministic behavior
- Rust developers transitioning from std to embedded domains
domain-embedded FAQ
Use RTIC for priority-based interrupt-driven applications with clear task priorities. Use Embassy for complex state machines and async workflows where you need structured concurrency.
Vec requires a heap allocator, which is unavailable in no_std environments and introduces non-deterministic memory behavior. Use heapless::Vec<T, N> with a fixed capacity instead.
Use Mutex<RefCell<Option<T>>> to wrap peripheral state and access it only within interrupt::free(|cs| {...}) critical sections to prevent race conditions.
PAC (Peripheral Access Crate) provides low-level register access; HAL (Hardware Abstraction Layer) wraps PAC with safe, ergonomic APIs and enforces ownership rules.
No. Embedded code requires #![no_std] and cannot use std. Use core and alloc (if an allocator is available) or heapless for collections.
Full instructions (SKILL.md)
Source of truth, from actionbook/rust-skills.
name: domain-embedded description: "Use when developing embedded/no_std Rust. Keywords: embedded, no_std, microcontroller, MCU, ARM, RISC-V, bare metal, firmware, HAL, PAC, RTIC, embassy, interrupt, DMA, peripheral, GPIO, SPI, I2C, UART, embedded-hal, cortex-m, esp32, stm32, nrf, 嵌入式, 单片机, 固件, 裸机" globs: ["/Cargo.toml", "/.cargo/config.toml"] user-invocable: false
Project Context (Auto-Injected)
Target configuration:
!cat .cargo/config.toml 2>/dev/null || echo "No .cargo/config.toml found"
Embedded Domain
Layer 3: Domain Constraints
Domain Constraints → Design Implications
| Domain Rule | Design Constraint | Rust Implication |
|---|---|---|
| No heap | Stack allocation | heapless, no Box/Vec |
| No std | Core only | #![no_std] |
| Real-time | Predictable timing | No dynamic alloc |
| Resource limited | Minimal memory | Static buffers |
| Hardware safety | Safe peripheral access | HAL + ownership |
| Interrupt safe | No blocking in ISR | Atomic, critical sections |
Critical Constraints
No Dynamic Allocation
RULE: Cannot use heap (no allocator)
WHY: Deterministic memory, no OOM
RUST: heapless::Vec<T, N>, arrays
Interrupt Safety
RULE: Shared state must be interrupt-safe
WHY: ISR can preempt at any time
RUST: Mutex<RefCell<T>> + critical section
Hardware Ownership
RULE: Peripherals must have clear ownership
WHY: Prevent conflicting access
RUST: HAL takes ownership, singletons
Trace Down ↓
From constraints to design (Layer 2):
"Need no_std compatible data structures"
↓ m02-resource: heapless collections
↓ Static sizing: heapless::Vec<T, N>
"Need interrupt-safe state"
↓ m03-mutability: Mutex<RefCell<Option<T>>>
↓ m07-concurrency: Critical sections
"Need peripheral ownership"
↓ m01-ownership: Singleton pattern
↓ m12-lifecycle: RAII for hardware
Layer Stack
| Layer | Examples | Purpose |
|---|---|---|
| PAC | stm32f4, esp32c3 | Register access |
| HAL | stm32f4xx-hal | Hardware abstraction |
| Framework | RTIC, Embassy | Concurrency |
| Traits | embedded-hal | Portable drivers |
Framework Comparison
| Framework | Style | Best For |
|---|---|---|
| RTIC | Priority-based | Interrupt-driven apps |
| Embassy | Async | Complex state machines |
| Bare metal | Manual | Simple apps |
Key Crates
| Purpose | Crate |
|---|---|
| Runtime (ARM) | cortex-m-rt |
| Panic handler | panic-halt, panic-probe |
| Collections | heapless |
| HAL traits | embedded-hal |
| Logging | defmt |
| Flash/debug | probe-run |
Design Patterns
| Pattern | Purpose | Implementation |
|---|---|---|
| no_std setup | Bare metal | #![no_std] + #![no_main] |
| Entry point | Startup | #[entry] or embassy |
| Static state | ISR access | Mutex<RefCell<Option<T>>> |
| Fixed buffers | No heap | heapless::Vec<T, N> |
Code Pattern: Static Peripheral
#![no_std]
#![no_main]
use cortex_m::interrupt::{self, Mutex};
use core::cell::RefCell;
static LED: Mutex<RefCell<Option<Led>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let led = Led::new(dp.GPIOA);
interrupt::free(|cs| {
LED.borrow(cs).replace(Some(led));
});
loop {
interrupt::free(|cs| {
if let Some(led) = LED.borrow(cs).borrow_mut().as_mut() {
led.toggle();
}
});
}
}
Common Mistakes
| Mistake | Domain Violation | Fix |
|---|---|---|
| Using Vec | Heap allocation | heapless::Vec |
| No critical section | Race with ISR | Mutex + interrupt::free |
| Blocking in ISR | Missed interrupts | Defer to main loop |
| Unsafe peripheral | Hardware conflict | HAL ownership |
Trace to Layer 1
| Constraint | Layer 2 Pattern | Layer 1 Implementation |
|---|---|---|
| No heap | Static collections | heapless::Vec<T, N> |
| ISR safety | Critical sections | Mutex<RefCell<T>> |
| Hardware ownership | Singleton | take().unwrap() |
| no_std | Core-only | #![no_std], #![no_main] |
Related Skills
| When | See |
|---|---|
| Static memory | m02-resource |
| Interior mutability | m03-mutability |
| Interrupt patterns | m07-concurrency |
| Unsafe for hardware | unsafe-checker |
Related skills
More from actionbook/rust-skills and the wider catalog.

domain-fintech
Fintech domain constraints and patterns for Rust: precision, immutability, and audit trails.

domain-iot
Design IoT apps with offline-first, power-efficient, and secure patterns in Rust.

domain-ml
Build ML/AI applications in Rust with efficient tensor operations, GPU acceleration, and model inference.

domain-web
Build concurrent, type-safe web services with async handlers, middleware, and shared state patterns.

m01-ownership
Diagnose and fix Rust ownership, borrowing, and lifetime errors by understanding data roles and scope boundaries.

m02-resource
Master Rust smart pointers and resource management for correct ownership patterns.