1 unstable release

0.1.0 Jul 7, 2020

#1395 in Embedded development

MIT license

44KB
707 lines

embedded-async-timer

Async timers for embedded devices in Rust.

This crate provides an interface and a generic implemention of a timer that can handle multiple concurrent deadlines using the Future architecture provided by Rust. This crate also provides two reference implementations for this interface for the STM32F103 and STM32L476.

Using implementations for the Timer trait, you can instance an AsyncTimer that provides methods to concurrently wait on a specific deadline or duration with a Future-compatible interface. Using this crate you can implement device drivers that require delays. Using HAL crates that are compatible with embedded-async-timer you can develop firmware that directly require delays or use these aforementioned drivers. For HAL RTC implementations with alarms it should be trivial to adapt them to implement the Timer trait. View the STM32F103 example in the impls module for inspiration.

Note: until const_generics lands the capacity for AsyncTimer is hard-coded.

Note: the current design assumes a bare_metal-like single core architecture that supports interrupt::free-like blocks. In the future I would like to rewrite everything to no longer require this.

Note: the priority queue used in this implementation is very likely to not be the most efficient choice of data structure. I intend to experiment with various setups to make an informed performance consideration based on real measurements given a small amount of concurrent timers.

State: this crate has been tested with trivial examples on two embedded devices, but has not yet been applied in production. It is beyond a simple proof of concept though. Our intention to provide a basis for an async ecosystem. The quality might also be insufficient to run on production. Also the current state of async-await might be such that it is practically unusable for memory constrained embedded devices. We encourage developing async HAL drivers using this crate though.

Example

async {
    let timer = AsyncTimer::new(rtc);
    timer.wait(Duration::from_millis(500).into()).await;

    let mut interval = Interval::new(Duration::from_secs(1).into(), &timer);

    loop {
        interval.wait(&timer).await;
        println!("ping");
    }
}

Dependencies

~0.1–11MB
~321K SLoC