In the realm of embedded software, the demand for efficient and responsive
applications is ever-increasing. Asynchronous programming, with its ability
to handle concurrent tasks effectively, holds immense potential in this domain.
Let’s delve into the world of asynchronous Rust specifically tailored for
microcontrollers.
It’s worth calling out that Embassy provides an async Rust wrapper around Nordic’s proprietary Bluetooth stack (SoftDevice), giving you access to a battle-tested BT stack without having to use unsafe C bindings (at least for the use cases covered by their high-level API): GitHub - embassy-rs/nrf-softdevice
Thanks for the article! I am interested in async programming on microcontrollers and was delighted to see this featured in Interrupt.
IMHO one more thing that should be added to the benefits of using cooperative scheduling is the lack of need for IPC and other synchronization primitives, which can be error-prone and cause hard to debug data races on preemptive systems.
Which brings me to the use of AtomicBool in the example. I am by far not an expert on Rust, so correct me if I am wrong, but I believe due to the single threaded nature of cooperative scheduling, a regular global variable without thread safety would be sufficient instead of AtomicBool. Can you explain why you used this construct?
The AtomicBool is needed because the Boolean is being shared between interrupt context and non- interrupt context. If it was only being shared between futures then you are correct and a regular bool could be used.
Which part of the code runs on interrupt context? From what I understand the executor runs on the non-interrupt context and the interrupt is used to wake the executor. Please provide a source if I am wrong.
Cheers to the author. Very useful and well written post.
You don’t mention what happens while waiting for Poll::Ready(). Can Embassy send the microcontroller to a low power mode while on hold? How would that work?