Analysis

Seven Essential HAL Crates for Embedded Rust no_std Projects

Picking the wrong HAL in embedded Rust costs weeks, not hours; here are the seven crates worth trusting across the RP2040, STM32, nRF52, and ESP32 families.

Sam Ortega6 min read
Published
Listen to this article0:00 min
Share this article:
Seven Essential HAL Crates for Embedded Rust no_std Projects
Source: techbuddies.io
This article contains affiliate links, marked with a blue dot. We may earn a small commission at no extra cost to you.

Picking a HAL crate in embedded Rust is the decision everything else hinges on. Choose one that's poorly maintained or missing half the peripherals you need, and Rust's memory-safety guarantees won't save you from months of brittle workarounds. Choose well, and the borrow checker becomes your best integration test. Here are the seven HAL crates that have earned community trust for real no_std production firmware, organized by the silicon you're most likely to be holding.

Comparison Table

CrateTarget Siliconno_stdPAC BackingDocs QualityExample Coverage
embedded-halAll (trait only)N/AExcellentLimited (trait defs)
rp2040-halRP2040rp2040-pac (svd2rust)GoodStrong
embassy-stm32All STM32 familiesstm32-rs (svd2rust)ExcellentExcellent
embassy-nrfnRF52/53/54/91nrf-pacGoodStrong
embassy-rpRP2040, RP235xrp2040-pac (svd2rust)GoodGrowing
esp-halESP32 familyesp-pacsGoodGrowing
atsamd-halATSAMD21/51, ATSAME seriesatsamd-pac (svd2rust)GoodModerate

1. embedded-hal

Before picking any device-specific HAL, you need to understand what holds the entire embedded Rust ecosystem together: the `embedded-hal` trait crate. It defines the standard interfaces (SPI, I2C, UART, GPIO, delay) that every driver crate programs against, so a BME280 sensor driver written against `embedded-hal` traits runs on your STM32 Nucleo and your Raspberry Pi Pico without a single line of change. Version 1.0 of the crate landed alongside Rust 1.75 as a stable, semver-stable foundation. If a HAL crate doesn't implement `embedded-hal` v1.0 traits (plus `embedded-hal-async` for async variants), it's a yellow flag on long-term ecosystem compatibility.

2. rp2040-hal

The gateway drug for most hobbyists entering embedded Rust is the Raspberry Pi Pico, and `rp2040-hal` from the `rp-rs` organization is the crate that makes it work. It exposes high-level drivers for the RP2040's internal peripherals, including its dual-core architecture, PIO state machines, I2C, SPI, and UART controllers, sitting on top of the `rp2040-pac` peripheral access crate generated via `svd2rust`. The abstraction is deliberate: `rp2040-hal` knows nothing about how any given board routes its pins, which is why BSP crates like `rp-pico` and `sparkfun-pro-micro-rp2040` layer on top to add pin-map definitions. Start here for a blocking, step-by-step GPIO blinky or I2C sensor read before you reach for the async stack.

3. embassy-stm32

For teams building production STM32 firmware in Rust, `embassy-stm32` is the clear benchmark. It spans every STM32 microcontroller family via automatically generated feature flags that select the correct peripheral implementation per chip, so one crate targets the STM32F4, STM32H7, STM32L4, and others without forking. The crate implements both `embedded-hal` v0.2 and v1.0 as well as `embedded-hal-async` and `embedded-io-async`, which means you get a uniform async/await surface for DMA-backed SPI, I2C, and UART transfers. With 255 contributors having touched the Embassy codebase, it is the most battle-tested async embedded Rust HAL available, backed by the `stm32-rs` PAC project whose SVD files are continuously patched for register-description errors.

4. embassy-nrf

AI-generated illustration
AI-generated illustration

Nordic's nRF52 family, and its successors in the nRF53, nRF54, and nRF91 series, are the default choice for Bluetooth Low Energy and cellular IoT products. `embassy-nrf` gives you an async HAL covering those families with native support for the nRF's UARTE, TWIM (I2C), SPIM, and GPIOTE peripherals. The real power move for BLE projects is pairing `embassy-nrf` with `nrf-softdevice`, which wraps Nordic's proprietary SoftDevice Bluetooth stack in idiomatic Rust bindings, giving you BLE without abandoning the Rust safety model. If your project involves low-power sensor nodes or BLE peripherals and you want async sleep plus interrupt handling that Rust's ownership system can reason about, this is the HAL to reach for.

5. embassy-rp

Where `rp2040-hal` gives you a blocking, bare-metal API for the RP2040, `embassy-rp` gives you the async version, fully integrated with the Embassy executor. It supports both the original RP2040 and the newer RP235x family, and its async DMA-backed drivers mean a PIO-driven LED strip or an SPI display doesn't block your entire task loop. For projects that start with a simple blinky on the Pico and grow into multi-task firmware with concurrent I2C, Wi-Fi via CYW43439, and USB CDC, `embassy-rp` is the natural upgrade path without switching ecosystems. The `embassy-rp` and `rp2040-hal` crates share the same underlying PAC (`rp2040-pac`, svd2rust-generated), so peripheral access is consistent at the register level even as the API surface diverges.

6. esp-hal

No roundup of embedded Rust HALs is complete without the ESP32 family. Espressif has invested heavily in Rust support via the `esp-rs` organization, and `esp-hal` is the result: a no_std HAL covering ESP32, ESP32-S2, ESP32-S3, ESP32-C3, and related variants. The crate backs into auto-generated PACs built from Espressif's SVD files. Critically, async Wi-Fi, Bluetooth, and ESP-NOW support is being developed in the same ecosystem, which makes the ESP32 the go-to silicon when wireless connectivity is a hard requirement and you want to stay in Rust's no_std model throughout. Be prepared for faster-moving APIs than the STM32 or nRF stacks as the crate matures, and confirm which chip variant's feature flags you need before starting.

7. atsamd-hal

The Microchip ATSAMD family (ATSAMD21, ATSAMD51, ATSAME51, ATSAME53, ATSAME54) underpins a large portion of the Adafruit Feather and Circuit Playground ecosystem, making `atsamd-hal` the practical choice for anyone building on those boards in Rust. The crate generates its PAC layer from svd2rust, covers the full GPIO, I2C, SPI, and USB peripheral set, and maintains tiered BSP support so popular boards like the Feather M0 and Feather M4 Express have well-tested crate wrappers. If your project involves hardware that already runs CircuitPython or Arduino and you're migrating to Rust for reliability, `atsamd-hal` is the least-friction path: the community has already mapped the peripherals and the pin assignments you'd otherwise reverse-engineer from the schematic.

Pick your first embedded Rust stack in 15 minutes

If you have an RP2040 (Pico or Pico W) and want a GPIO blinky running in under 15 minutes: start with `rp2040-hal`, use `probe-rs` as your flash-and-debug tool (it replaces the older OpenOCD + GDB setup entirely), and wire your `Cargo.toml` to target `thumbv6m-none-eabi`. When you outgrow blocking loops, graduate to `embassy-rp` without changing your PAC or toolchain.

If you have an STM32 Nucleo or a custom board: `embassy-stm32` is the correct first pick. The docs are thorough, the peripheral feature flag system handles chip differences automatically, and the example library is extensive enough that SPI, I2C, and DMA are all covered with working reference code.

If wireless connectivity is the core requirement, reach for the ESP32 with `esp-hal`. If it's BLE specifically, an nRF52840-DK running `embassy-nrf` with `nrf-softdevice` is the combination the embedded Rust community defaults to.

Whatever you pick, confirm two things before writing a line of firmware: the HAL's CI pipeline cross-compiles against your exact chip variant, and `svd2rust` PAC files for that chip exist and are actively maintained. A HAL without PAC backing eventually becomes a hand-rolled volatile nightmare, which is precisely the category of bug embedded Rust was built to make impossible.

Know something we missed? Have a correction or additional information?

Submit a Tip

Never miss a story.
Get Rust Programming updates weekly.

The top stories delivered to your inbox.

Free forever · Unsubscribe anytime

Discussion

More Rust Programming News