Skip to content

Bare-metal (no std library) Rust system controllers on a resberry pi pico

License

Notifications You must be signed in to change notification settings

ombayley/EmbeddedRustSystems

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

32 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ“˜ Bare Metal Raspberry Pi Pico 2W

Bare-metal (no_std) Rust on a Raspberry Pi Pico 2W microcontroller with USB Serial Communication


๐Ÿงฉ Overview

This project is a bare-metal Rust implementation for the Raspberry Pi Pico 2W (RP2350 processor) featuring:

  • USB Serial Communication: Custom Modbus-inspired framing protocol for reliable device communication
  • Async/Await Programming: Using Embassy async runtime for efficient embedded systems
  • GPIO Control: LED chase pattern demonstration with configurable timing
  • Zero Standard Library: Complete no_std implementation optimized for embedded constraints

The project showcases advanced embedded Rust concepts including async executors, USB device communication, and hardware abstraction layers while maintaining memory safety without runtime overhead.


๐ŸŽฏ Objectives / Learning Goals

  • ๐Ÿ”น Bare-metal Programming โ€” Master no_std Rust and embedded systems fundamentals
  • ๐Ÿ”น Async Embedded Development โ€” Learn Embassy framework for async/await in embedded contexts
  • ๐Ÿ”น Hardware Abstraction โ€” Understand GPIO, USB, and peripheral control using embassy-rp HAL
  • ๐Ÿ”น Communication Protocols โ€” Implement custom framing protocol with CRC-16 error checking
  • ๐Ÿ”น Memory Safety โ€” Leverage Rust's ownership system in resource-constrained environments

โš™๏ธ Tech Stack

Category Tools / Technologies
Language Rust (Edition 2024, no_std)
Frameworks embassy (async executor), embassy-rp (RP2350 HAL)
Tools probe-rs, cargo-embed, defmt (logging)
Hardware Raspberry Pi Pico 2W (RP2350A), USB Serial
Protocol Custom Modbus-inspired framing with CRC-16/Modbus

๐Ÿ—๏ธ Project Architecture

Core Components

    src/
    โ”œโ”€โ”€ main.rs         # Entry point with command loop and USB handling
    โ”œโ”€โ”€ protocol.rs     # Frame parser and builder (Modbus-inspired protocol)
    โ”œโ”€โ”€ serial_usb.rs   # USB Serial communication layer
    โ”œโ”€โ”€ chase.rs        # LED chase pattern demo
    โ””โ”€โ”€ sys.rs          # System initialization helpers

Communication Protocol

The project implements a custom framing protocol for reliable transport-agnostic communication:

Frame Structure:

    [ STX | LEN | ADDR | CMD | <PAYLOAD...> | CRCL | CRCH ]
  • STX: Start marker (0xA5) for frame synchronization
  • LEN: Payload length (includes ADDR + CMD + data)
  • ADDR: Device address (1 byte)
  • CMD: Command/function code (1 byte)
  • PAYLOAD: Variable data (0-253 bytes)
  • CRC: CRC-16/Modbus checksum (little-endian)

Supported Commands:

  • 0x01 โ€” PING: Device health check
  • 0x02 โ€” CHASE: Trigger LED chase pattern
  • 0x20 โ€” GET_DEVICE_ID: Query unique device identifier

Response Types:

  • ACK: Success response with status byte
  • ERROR: Error response with error code
  • DATA: Data response with byte count and payload

Hardware Features

  • USB Serial: Full-duplex communication over USB CDC-ACM
  • GPIO Control: 5-pin LED chase sequence (pins 0-4)
  • Async Runtime: Embassy executor enables concurrent tasks without blocking

๐Ÿš€ Getting Started

Prerequisites

  1. Rust Toolchain
    Install from https://rustup.rs/

  2. Target Architecture
    Add RP2350 ARM Cortex-M33 target:

    rustup target add thumbv8m.main-none-eabihf
  3. Debugging Tools (Optional)

    • Install probe-rs: cargo install probe-rs-tools
    • Install cargo-embed: Built into probe-rs suite

Building the Firmware

The project uses a custom build script that automatically configures the target based on .pico-rs file:

# Build for RP2350 (Pico 2W default)
cargo build --release

# Build for RP2040 (legacy Pico)
echo "rp2040" > .pico-rs
cargo build --release

# Build for RP2350 RISC-V core
echo "rp2350-riscv" > .pico-rs
cargo build --release

Build Profiles:

  • dev โ€” Fast compilation, larger binaries, debug symbols
  • release โ€” Optimized for size and speed (recommended for deployment)

Flashing to Device

Option 1: USB Bootloader (UF2)

  1. Hold BOOTSEL button while connecting USB

  2. Device mounts as mass storage

  3. Copy .uf2 binary to mounted drive:

    # Convert ELF to UF2 (if needed)
    elf2uf2-rs target/thumbv8m.main-none-eabihf/release/embedded-systems firmware.uf2

Option 2: Debug Probe (Recommended)

# Flash and attach debugger
cargo embed --release

# Or use probe-rs directly
probe-rs run --chip RP2350 target/thumbv8m.main-none-eabihf/release/embedded-systems

๐Ÿงช Usage

Serial Communication

The device communicates over USB Serial (CDC-ACM). Use the Python client in tools/serial_client/:

Setup Python Environment

cd tools/serial_client
conda env create -f serial_client_env.yml
conda activate serial_client

Example Commands

Send PING (0x01):

python serial_client.py -c 0x01

Trigger Chase Pattern (0x02):

python serial_client.py -c 0x02

Get Device ID (0x20):

python serial_client.py -c 0x20

Hardware Setup

For the LED chase demo, connect LEDs (with appropriate resistors) to:

  • GPIO 0-4 โ†’ Anode (positive)
  • Ground โ†’ Cathode (negative)

Chase Pattern: Each LED illuminates sequentially for 100ms with 100ms intervals.

Code Notes

Bare-metal systems require removal of std library To ensure proper global initialisation, Rust's default 'main' call must also be overwriten by:

  • #[embassy_executor::main] for embassy (async environment) OR
  • #[hal::entry] for bare-metal (blocking)

๐Ÿ“Š Implementation Highlights

Memory Efficiency

  • Heapless Data Structures: All buffers use compile-time fixed sizes (heapless::Vec)
  • Zero Dynamic Allocation: No heap allocator required
  • Static Resources: USB buffers and peripherals use static_cell for lifetime management

Safety Features

  • CRC-16 Error Detection: Modbus polynomial ensures data integrity
  • Frame Resynchronization: Parser recovers from transmission errors by scanning for STX markers
  • Type-Safe Peripherals: Rust ensures exclusive access to hardware resources at compile time

Async Architecture

  • Non-blocking I/O: USB reads/writes don't block the executor
  • Concurrent Tasks: Spawner enables multiple async tasks (USB, timers, GPIO)
  • Zero-cost Abstractions: Embassy compiles to efficient state machines

๐Ÿ“‚ Project Structure

    EmbeddedRustSystems/
    โ”œโ”€โ”€ .cargo/             # Cargo configuration (target defaults, runner)
    โ”œโ”€โ”€ docs/               # Documentation (build guides, etc.)
    โ”œโ”€โ”€ embassy_examples/   # Example code from Embassy framework (66 files)
    โ”œโ”€โ”€ src/                # Main source code
    โ”‚   โ”œโ”€โ”€ main.rs         # Application entry point
    โ”‚   โ”œโ”€โ”€ protocol.rs     # Frame protocol implementation
    โ”‚   โ”œโ”€โ”€ serial_usb.rs   # USB Serial abstraction
    โ”‚   โ”œโ”€โ”€ chase.rs        # LED chase pattern
    โ”‚   โ””โ”€โ”€ sys.rs          # System initialization
    โ”œโ”€โ”€ tools/              # Development tools
    โ”‚   โ””โ”€โ”€ serial_client/  # Python USB Serial client
    โ”œโ”€โ”€ build.rs            # Build script for linker configuration
    โ”œโ”€โ”€ Cargo.toml          # Dependencies and build profiles
    โ”œโ”€โ”€ Embed.toml          # probe-rs configuration
    โ”œโ”€โ”€ rp2350.x            # Linker script for RP2350 ARM
    โ”œโ”€โ”€ rp2350_riscv.x      # Linker script for RP2350 RISC-V
    โ””โ”€โ”€ rp2040.x            # Linker script for RP2040

๐Ÿ”ฎ Future Improvements

Planned Features

  • Stepper Motor Control: Implement PWM-based stepper motor driver
  • WiFi Integration: Enable CYW43 driver for wireless communication
  • Advanced Protocols: Add support for I2C/SPI peripheral communication
  • C++ Comparison: Port implementation to C++ for performance benchmarking
  • Flash Storage: Persistent configuration using RP2350 flash memory

Potential Enhancements

  • Multi-device addressing (use ADDR field for bus communication)
  • Interrupt-driven GPIO with debouncing
  • Watchdog timer for fault recovery
  • Power management and sleep modes

๐Ÿ“š References / Resources

Documentation

RP2350 Resources

Tools

  • probe-rs โ€” Rust debugging and flashing tool
  • defmt โ€” Efficient embedded logging

๐Ÿง‘โ€๐Ÿ’ป Author

Olly Bayley
GitHub: @ombayley


๐Ÿชช License

This project is licensed under the GNU General Public License (GPL) โ€” See the LICENSE file for details. The GPL License is a copyleft license, that requires any derivative work to also be released under the GPL License. This means any derivative software that uses this code remains open-source and freely available to the public.

About

Bare-metal (no std library) Rust system controllers on a resberry pi pico

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published