A collection of embedded Rust programming examples for the BBC micro:bit v2. This project demonstrates various aspects of embedded development using the nRF52833 microcontroller and the micro:bit v2 development board.
This project took inspiration and the initial Hello World example from The Embedded Rust Book and has evolved to include progressively advanced embedded programming concepts and techniques. The Embedded Rust Book is an excellent reference and readers are encouraged to refer to it alongside these examples.
- 📋 vscode_setup.md - Complete VS Code configuration guide for embedded Rust development
- 🦀 embedded_rust_primer.md - Beginner's guide to embedded Rust:
#![no_std]
,#[entry]
, HAL patterns, and memory management - 🔍 deep_dive.md - Technical deep dive into the Rust-to-hardware compilation pipeline
- ⚡ hardware.md - How memory mapping physically works: address bus, Flash, RAM, and peripherals
- 📄 micro:bit v2 Schematic - Official hardware schematic (PDF)
This project follows a progressive learning journey from high-level convenience to bare-metal understanding. Each example strips away more abstraction layers to show you exactly what's happening under the hood.
This project uses independent examples rather than a Cargo workspace - each example can be copied and used standalone.
🎯 High-Level HAL Approach - "I want to blink an LED easily"
- Board initialization using convenient HAL crates
- Hardware timer usage with high-level APIs
- Simple LED matrix control
- 5 dependencies - Maximum convenience and safety
- Best for: Getting started quickly with embedded Rust
🔧 Direct Register Access - "How do GPIO registers actually work?"
- Direct hardware register manipulation
- Reduced dependencies while maintaining essential functionality
- 3 dependencies - Balance of control and convenience
- Best for: Understanding hardware interfaces and register-level programming
⚡ Bare Metal Implementation - "How does the ENTIRE system work?"
- Zero dependencies - Everything implemented from scratch
- Custom ARM Cortex-M vector table and reset handler
- Hand-crafted linker script and memory initialization
- Direct assembly integration and complete system control
- Best for: Deep understanding of embedded systems architecture
🔥 Advanced Bare-Metal Implementation - "Complete hardware control"
- Pure ARM Thumb assembly implementation with minimal Rust scaffolding
- Hardcoded memory addresses and stack pointer configuration
- 8-byte minimal vector table with no runtime initialization
- Best for: Silicon-level understanding and maximum performance optimization
🎮 Interactive Input Processing - "How do I handle user input with polling?"
- Button polling with edge detection and software debouncing
- GPIO input configuration with pull-up resistors
- State management for toggle functionality
- Active-low input logic and mutability requirements
- Best for: Learning basic input processing techniques and interactive embedded applications
⚡ Interrupt-Driven Processing - "How do I use hardware interrupts for efficient input handling?"
- GPIOTE peripheral configuration for hardware interrupt generation
- Atomic state management between interrupt handler and main loop
- Power-efficient operation with Wait-For-Interrupt (WFI) instruction
- Direct register access and minimal interrupt service routines
- Best for: Learning interrupt-driven architecture and power-efficient embedded design
Educational Philosophy: Examples 03 and 04 represent progressively lower levels of embedded systems programming. While production code typically uses higher-level abstractions (Example 01 approach), understanding bare-metal implementation provides valuable insight into the underlying hardware behavior and system architecture.
Example 04 specifically demonstrates the absolute minimum required for ARM Cortex-M execution, showing exactly what instructions run on the processor without any runtime overhead or abstraction layers.
Abstraction Level | Example 01 | Example 02 | Example 03 | Example 04 |
---|---|---|---|---|
Dependencies | 5 crates | 3 crates | 0 crates | 0 crates |
Implementation | High-level Rust | Register access | Bare metal Rust | 99% Assembly |
Code Style | led.set_high()? |
gpio.out.set(1 << 4) |
ptr::write_volatile(0x50000508, 1 << 4) |
str r1, [r0] |
Startup | Automatic | Automatic | Manual reset handler | Assembly reset handler |
Memory Init | Hidden | Hidden | Explicit RAM setup | No initialization |
Vector Table | Generated | Generated | Hand-crafted | 8-byte minimal |
Binary Size | ~4KB+ | ~2KB+ | ~1KB+ | ~100 bytes |
When to Use | Production code | Learning registers | Understanding systems | Performance optimization |
Each example builds the same functionality (blinking LED) but reveals progressively more of the underlying machinery. The progression moves from high-level abstractions through register manipulation to complete bare-metal assembly implementation, providing comprehensive understanding of embedded systems from hardware reset vector to application logic.
Examples 5+: While Examples 01-04 focus on different abstraction levels of the same functionality, Examples 5 onwards explore different embedded programming concepts and peripherals (input processing, sensors, communication protocols, etc.) using practical implementation approaches.
💡 Note: Each example directory contains its own readme.md with detailed explanations, code walkthrough, and specific instructions for that example.
- BBC micro:bit v2 (with nRF52833 microcontroller)
Follow the installation guide from The Embedded Rust Book - Installation for complete setup instructions.
Required extensions for the best development experience:
-
rust-analyzer (
rust-lang.rust-analyzer
)- Provides Rust language support and Code Lens features
-
probe-rs-debugger (
probe-rs.probe-rs-debugger
)- Required for embedded debugging support
Each example is a complete, independent Rust project:
In VS Code (Recommended):
- Open an example's
src/main.rs
file in VS Code - Click the
▶️ Run button above the#[entry]
function - The program builds and flashes automatically to your micro:bit
From Command Line:
# Navigate to an example and run it
cd example_01_hello_world
cargo run
💡 Tip: See vscode_setup.md for complete VS Code configuration and debugging setup.