Crate embassy_nrf

source ·
Expand description

§Embassy nRF HAL

HALs implement safe, idiomatic Rust APIs to use the hardware capabilities, so raw register manipulation is not needed.

The Embassy nRF HAL targets the Nordic Semiconductor nRF family of hardware. The HAL implements both blocking and async APIs for many peripherals. The benefit of using the async APIs is that the HAL takes care of waiting for peripherals to complete operations in low power mode and handling interrupts, so that applications can focus on more important matters.

NOTE: The Embassy HALs can be used both for non-async and async operations. For async, you can choose which runtime you want to use.

For a complete list of available peripherals and features, see the embassy-nrf documentation.

§Hardware support

The embassy-nrf HAL supports most variants of the nRF family:

Most peripherals are supported, but can vary between chip families. To check what’s available, make sure to pick the MCU you’re targeting in the top menu in the documentation.

For MCUs with TrustZone support, both Secure (S) and Non-Secure (NS) modes are supported. Running in Secure mode allows running Rust code without a SPM or TF-M binary, saving flash space and simplifying development.

§Time driver

If the time-driver-rtc1 feature is enabled, the HAL uses the RTC peripheral as a global time driver for embassy-time, with a tick rate of 32768 Hz.


The embassy-nrf HAL implements the traits from embedded-hal (v0.2 and 1.0) and embedded-hal-async, as well as embedded-io and embedded-io-async.


This crate can run on any executor.

Optionally, some features requiring embassy-time can be activated with the time feature. If you enable it, you must link an embassy-time driver in your project.

§EasyDMA considerations

On nRF chips, peripherals can use the so called EasyDMA feature to offload the task of interacting with peripherals. It takes care of sending/receiving data over a variety of bus protocols (TWI/I2C, UART, SPI). However, EasyDMA requires the buffers used to transmit and receive data to reside in RAM. Unfortunately, Rust slices will not always do so. The following example using the SPI peripheral shows a common situation where this might happen:

// As we pass a slice to the function whose contents will not ever change,
// the compiler writes it into the flash and thus the pointer to it will
// reference static memory. Since EasyDMA requires slices to reside in RAM,
// this function call will fail.
let result = spim.write_from_ram(&[1, 2, 3]);
assert_eq!(result, Err(Error::BufferNotInRAM));

// The data is still static and located in flash. However, since we are assigning
// it to a variable, the compiler will load it into memory. Passing a reference to the
// variable will yield a pointer that references dynamic memory, thus making EasyDMA happy.
// This function call succeeds.
let data = [1, 2, 3];
let result = spim.write_from_ram(&data);

Each peripheral struct which uses EasyDMA (Spim, Uarte, Twim) has two variants of their mutating functions:

  • Functions with the suffix (e.g. write_from_ram, transfer_from_ram) will return an error if the passed slice does not reside in RAM.
  • Functions without the suffix (e.g. write, transfer) will check whether the data is in RAM and copy it into memory prior to transmission.

Since copying incurs a overhead, you are given the option to choose from _from_ram variants which will fail and notify you, or the more convenient versions without the suffix which are potentially a little bit more inefficient. Be aware that this overhead is not only in terms of instruction count but also in terms of memory usage as the methods without the suffix will be allocating a statically sized buffer (up to 512 bytes for the nRF52840).

Note that the methods that read data like read and transfer_in_place do not have the corresponding _from_ram variants as mutable slices always reside in RAM.

§Feature flags

  • rt (enabled by default) — Cortex-M runtime (enabled by default)
  • time — Enable features requiring embassy-time
  • defmt — Enable defmt
  • unstable-pac — Reexport the PAC for the currently enabled chip at embassy_nrf::pac (unstable)
  • gpiote — Enable GPIO tasks and events
  • time-driver-rtc1 — Use RTC1 as the time driver for embassy-time, with a tick rate of 32.768khz
  • nfc-pins-as-gpio — Allow using the NFC pins as regular GPIO pins (P0_09/P0_10 on nRF52, P0_02/P0_03 on nRF53)
  • reset-pin-as-gpio — Allow using the RST pin as a regular GPIO pin.
    • nRF52805, nRF52810, nRF52811, nRF52832: P0_21
    • nRF52820, nRF52833, nRF52840: P0_18
  • qspi-multiwrite-flash — Implements the MultiwriteNorFlash trait for QSPI. Should only be enabled if your external flash supports the semantics described here

§Chip selection features

  • nrf51 — nRF51
  • nrf52805 — nRF52805
  • nrf52810 — nRF52810
  • nrf52811 — nRF52811
  • nrf52820 — nRF52820
  • nrf52832 — nRF52832
  • nrf52833 — nRF52833
  • nrf52840 — nRF52840
  • nrf5340-app-s — nRF5340 application core in Secure mode
  • nrf5340-app-ns — nRF5340 application core in Non-Secure mode
  • nrf5340-net — nRF5340 network core
  • nrf9160-s — nRF9160 in Secure mode
  • nrf9160-ns — nRF9160 in Non-Secure mode


  • Async buffered UART driver.
  • Configuration options used when initializing the HAL.
  • General purpose input/output (GPIO) driver.
  • GPIO task/event (GPIOTE) driver.
  • Interrupt definitions.
  • Non-Volatile Memory Controller (NVMC, AKA internal flash) driver.
  • Peripheral Access Crate
  • Pulse Density Modulation (PDM) mirophone driver
  • Types for the peripheral singletons.
  • Programmable Peripheral Interconnect (PPI/DPPI) driver.
  • Pulse Width Modulation (PWM) driver.
  • Quadrature decoder (QDEC) driver.
  • Quad Serial Peripheral Interface (QSPI) flash driver.
  • Successive Approximation Analog-to-Digital Converter (SAADC) driver.
  • Serial Peripheral Instance in master mode (SPIM) driver.
  • Serial Peripheral Instance in slave mode (SPIS) driver.
  • Timer driver.
  • I2C-compatible Two Wire Interface in master mode (TWIM) driver.
  • I2C-compatible Two Wire Interface in slave mode (TWIM) driver.
  • Universal Asynchronous Receiver Transmitter (UART) driver.
  • Universal Serial Bus (USB) driver.




  • The maximum buffer size that the EasyDMA can send/recv in one operation.
  • Number available in the NVIC for configuring priority


  • Trait for any type that can be used as a peripheral of type P.


  • Initialize the embassy-nrf HAL with the provided configuration.

Attribute Macros§