LPC11xx Async HAL
Asynchronous HAL for the NXP LPC111x/LPC11Cxx/LPC11xxL/LPC11xxXL family of Cortex-M0 microcontrollers using async-await syntax.
Example
Below is a minimal echo server using the UART driver. The microcontroller will wake up from sleep only to send/receive data in the UART interrupt and to issue additional UART commands from the async fn inside PendSV and will be sleeping the rest of the time.
use uart;
// Initialize the UART driver ahead of time, e.g. 9600 baud at 12MHz
// The UART peripheral must have power, a clock, configured pins etc
let uart = initialize;
// The actual logic, to be polled from the PendSV interrupt handler
async ! 
Status
Async drivers for the following peripherals are currently available:
| Peripheral | Missing features | Won't implement | 
|---|---|---|
| UART | Autobaud, RS-485 | |
| I2C | Slave Mode | Monitor Mode | 
| ADC | Timer Match | |
| SysTick | 
More are in development, contributions and suggestions welcome.
Caveats
The Rust async-await feature is still under heavy development to say nothing of its #![no_std] integration so this crate should be viewed as a proof of concept and ongoing experiment in writing automatically generated asynchronous state machines on LPC11xx devices. It works fine and does useful things though.
No-std support
An additional problem is brought about when using async-await in #![no_std] crates; essentially, it doesn't work because the compiler machinery to generate the resulting futures depends on thread-local storage which is in std. You can work around this by using the core-futures-stateless helper crate which will patch libcore to make #![feature(async_await)] work:
[]
 = "core-futures-stateless"
 = "0.1.0"
This can be removed once fixed in libcore. Note that this will (unfortunately) change the crate name of all types in the core crate in compiler messages.
Futures behaviour
This crate is built exclusively around the PendSV facility in Cortex-M processors. That is, all futures depend on being polled inside the PendSV exception handler, and all peripheral interrupt handlers will raise PendSV to progress the futures. As a result the task::Context associated with your main async task is irrelevant and you should create a dummy Waker that does absolutely nothing. The core-futures-stateless crate provides a convenience method task::stateless_waker() which does just that.
use Future;
use ;
// your executor somewhere inside the PendSV exception handler
match poll 
In the future the crate might become context-aware but in the meantime this is the way it works for simplicity and because using PendSV is quite a natural approach to polling futures.
Memory safety
There is currently a minor soundness hole in this crate in that interrupt handlers reference stack-like memory from currently running futures, which means that Drop impls for Future types must run to ensure memory safety. I am not sure how to fix this without significant compromises in performance or ergonomics and don't really consider this a major issue from a pragmatic standpoint. Leak futures at your own peril.