Embedded Rust - Beginner Core Concepts¶
Overview¶
Embedded Rust is a safe, efficient, and modern systems programming language designed for resource-constrained embedded systems. It leverages Rustβs memory safety guarantees, zero-cost abstractions, and strong type system to prevent common errors like null dereferencing and buffer overflows.
This guide covers beginner Embedded Rust concepts, including:
β
Why Rust for Embedded Systems?
β
Setting up an Embedded Rust Environment
β
Basic Program Structure
β
Memory Safety & Ownership in Embedded Rust
β
GPIO & Hardware Abstraction Layer (HAL)
β
Basic Concurrency with RTIC (Real-Time Interrupt-driven Concurrency)
Table of Contents¶
- Introduction to Embedded Rust
- Why Use Rust for Embedded Development?
- Setting Up the Development Environment
- Basic Program Structure in Embedded Rust
- Understanding Memory Safety & Ownership
- Working with GPIO & Peripherals
- Basic Concurrency in Embedded Rust
- Tools & Learning Resources
1. Introduction to Embedded Rust¶
What is Embedded Rust?¶
πΉ Embedded Rust is a subset of the Rust language that runs on bare-metal microcontrollers (MCUs) and other embedded devices.
πΉ It enables memory safety without garbage collection, making it ideal for real-time and safety-critical applications.
πΉ Rust's strong type system helps catch bugs at compile time, reducing runtime errors.
Common Use Cases¶
β
IoT Devices
β
Industrial Automation
β
Aerospace & Automotive Systems
β
Robotics & Drones
2. Why Use Rust for Embedded Development?¶
| Feature | Benefit for Embedded Systems |
|---|---|
| Memory Safety | No null pointer dereferencing, no buffer overflows |
| Zero-Cost Abstractions | No runtime overhead from high-level constructs |
| Concurrency without Data Races | Safe multi-threading and interrupts |
No Standard Library (#![no_std]) |
Runs on bare-metal devices without OS dependencies |
| Performance Comparable to C | Direct control over hardware like C, but safer |
3. Setting Up the Development Environment¶
Required Tools¶
πΉ Rust Toolchain (rustup, cargo, rustc) β Install Rust:
πΉ probe-rs β For flashing and debugging:
πΉ Target Support for Embedded MCUs β Example for ARM Cortex-M:
4. Basic Program Structure in Embedded Rust¶
A minimal "Blinky LED" program using the embedded-hal crate:
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use embedded_hal::digital::v2::OutputPin;
use panic_halt as _; // Panic handler
#[entry]
fn main() -> ! {
let mut led = ... // Configure GPIO as output
loop {
led.set_high().unwrap(); // Turn LED ON
cortex_m::asm::delay(10_000_000);
led.set_low().unwrap(); // Turn LED OFF
cortex_m::asm::delay(10_000_000);
}
}
β #![no_std] β No standard library, required for bare-metal applications.
β #![no_main] β Disables default main function (MCUs have custom boot logic).
β cortex_m_rt::entry β Marks entry point for embedded Rust programs.
5. Understanding Memory Safety & Ownership¶
Rust prevents common memory bugs found in C and C++:
β
No Null Pointers β Rust enforces explicit handling of Option<T>.
β
No Buffer Overflows β Rust enforces safe array indexing.
β
No Data Races β Rustβs ownership system prevents concurrent memory corruption.
Ownership Example in Embedded Context¶
fn configure_led(mut led: gpio::Pin<Output>) {
led.set_high().unwrap(); // LED ON
} // `led` is dropped here, preventing accidental reuse
6. Working with GPIO & Peripherals¶
Blink an LED using embedded-hal¶
use embedded_hal::digital::v2::OutputPin;
fn blink_led(mut led: impl OutputPin) {
led.set_high().unwrap();
cortex_m::asm::delay(10_000_000);
led.set_low().unwrap();
}
Reading a Button Input¶
use embedded_hal::digital::v2::InputPin;
fn read_button(button: impl InputPin) -> bool {
button.is_high().unwrap()
}
7. Basic Concurrency in Embedded Rust¶
Using RTIC (Real-Time Interrupt-driven Concurrency)¶
RTIC helps manage tasks, interrupts, and resource sharing safely.
Example: LED toggling with an interrupt-driven timer¶
#[rtic::app(device = stm32f4)]
mod app {
use rtic::cyccnt::U32Ext;
#[resources]
struct Resources {
led: gpio::Pin<Output>,
}
#[task(binds = TIM2, resources = [led])]
fn timer_interrupt(ctx: timer_interrupt::Context) {
ctx.resources.led.toggle().unwrap();
}
}
8. Tools & Learning Resources¶
Essential Tools for Embedded Rust¶
πΉ probe-rs β Flash and debug firmware
πΉ cargo-embed β Easy embedded development
πΉ defmt β Efficient logging for microcontrollers
Learning Resources¶
π The Embedded Rust Book
π Rust Embedded HAL Documentation
π RTIC (Real-Time Interrupt-driven Concurrency)
π Writing Embedded Rust for ARM Cortex-M
Conclusion¶
π― Key Takeaways
β
Rust offers memory safety, concurrency, and high performance for embedded systems.
β
#![no_std] enables Rust to run on bare-metal microcontrollers.
β
Embedded HAL abstracts hardware, enabling portability across MCUs.
β
RTIC provides safe task scheduling and interrupt management.
π Next Steps πΉ Try blinking an LED on an STM32 or ESP32 board. πΉ Explore embedded Rust projects like drone firmware or sensor integration. πΉ Learn real-time operating systems (RTOS) in Rust.