Intro to Embedded Rust Part 12: Async Programming with Embassy | DigiKey
In this tutorial, we cover async/await programming for embedded systems with Embassy, a modern Rust framework that enables concurrent multitasking on microcontrollers without a traditional RTOS. The written guide for this episode can be found here: https://www.digikey.com/en/maker/tutorials/2026/intro-to-embedded-rust-part-12-asynchronous-programming-with-embassy The GitHub repository containing the Docker image and example code for this series can be found here: https://github.com/ShawnHymel/introduction-to-embedded-rust Embassy provides cooperative task scheduling using Rust's native async/await syntax, allowing you to write code that handles multiple operations simultaneously, like monitoring buttons, blinking LEDs, and managing USB. We demonstrate how to replace bare-metal peripheral access with Embassy's higher-level abstractions, creating a button-controlled LED blinker with USB logging that showcases async GPIO, timers, task spawning, and inter-task communication. Embassy is a collection of modular crates including platform-specific HALs (embassy-rp for Raspberry Pi, embassy-stm32, embassy-nrf), the executor for running async tasks, timer abstractions, synchronization primitives, and protocol stacks for USB and networking. We demonstrate configuring Embassy dependencies in Cargo.toml, using the bind_interrupts! macro to connect hardware interrupts to handlers automatically, and marking functions with #[embassy_executor::task] to transform them into spawnable concurrent tasks. We also dive into futures (objects representing asynchronous operations that may not have completed yet) and look at how the executor manages them, pausing and resuming tasks as needed while automatically putting the processor to sleep when all tasks are waiting, providing efficient power management without manual wfi() calls. The tutorial showcases Embassy's async-first API design with real hardware interaction. You'll see how to use async GPIO methods like pin.wait_for_low().await that yield execution until events occur, eliminating manual interrupt service routines and polling loops. We demonstrate Timer::after_millis().await for non-blocking delays, Signal for inter-task communication (replacing the Mutex<RefCell<Option<T>>> pattern from bare-metal interrupt handling), and embassy_usb_logger for USB serial debugging output. We also show how to initialize the runtime and use a Spawner for launching tasks, using join_array to run multiple async operations concurrently, and structuring programs with both spawned tasks (independent lifecycle) and async functions within the main task. You'll see how Embassy abstracts interrupt handling, peripheral configuration, and resource sharing, making complex embedded applications more maintainable while preserving Rust's zero-cost abstractions and memory safety.
Part List
| Image | Manufacturer Part Number | Description | Available Quantity | Price | View Details | |
|---|---|---|---|---|---|---|
![]() | ![]() | FIT0096 | BREADBRD TERM STRIP 3.20X2.00" | 1630 - Immediate | $2.50 | View Details |
![]() | ![]() | 1957 | JUMPER WIRE M TO M 6" 28AWG | 3333 - Immediate | $1.68 | View Details |
![]() | ![]() | DH-20M50055 | USB AM TO USB MICRO, USB 2.0 - 1 | 10800 - Immediate | $1.33 | View Details |
![]() | ![]() | SC1634 | RASPBERRY PI PICO 2 WH RP2350 | 2145 - Immediate | $6.88 | View Details |
![]() | ![]() | 13314 | TMP102 DIGITAL TEMP SENSOR BOARD | 233 - Immediate | $5.12 | View Details |
![]() | ![]() | LTL-4224 | LED RED CLEAR T-1 3/4 T/H | 72091 - Immediate | $0.12 | View Details |
![]() | ![]() | SC1633 | RASPBERRY PI PICO 2 W RP2350 | 5891 - Immediate | $6.02 | View Details |
![]() | ![]() | 1825910-6 | SWITCH TACTILE SPST-NO 0.05A 24V | 41841 - Immediate | $0.11 | View Details |
![]() | ![]() | SC1631 | RASPBERRY PI PICO 2 RP2350 | 25819 - Immediate | $4.30 | View Details |
![]() | ![]() | SC1632 | RASPBERRY PI PICO 2 H RP2350 | 2583 - Immediate | $5.16 | View Details |















