embassy/embassy-time
bors[bot] e5097a8866
Merge #959
959: Generic, executor-agnostic queue implementation r=ivmarkov a=ivmarkov

Hopefully relatively well documented.

Implementation relies on a fixed-size `SortedLinkedList` from `heapless`. (By default, for up to 128 timer schedules, but we can lower this number to - say - 64.)

As discussed earlier, on queue overflow, the `WakerRegistration` approach is utilized, whereas the waker that is ordered first in the queue is awoken to make room for the incoming one (which might be the waker that would be awoken after all!). Wakers are compared with `Waker::will_wake`, so the queue should actually not fill up that easily, if at all.

I've left provisions for the user to manually instantiate the queue using a dedicated macro - `generic_queue!` so that users willing to adjust the queue size, or users (like me) who have to use the queue in a complex "on-top-of-RTOS-but-the-timer-driver-calling-back-from-ISR" scenario can customize the mutex that protects the queue.

The one thing I'm not completely happy with is the need to call `{ embassy_time::queue::initialize() }` early on before any futures using embassy-time are polled, which is currently on the shoulders of the user. I'm open to any ideas where we can get rid of this and do it on the first call to `_embassy_time_schedule_wake`, without introducing very complex combinations of critical sections, atomics and whatnot.




Co-authored-by: ivmarkov <ivan.markov@gmail.com>
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2022-10-26 19:14:12 +00:00
..
src time/generic_queue: use Vec instead of SortedLinkedList 2022-10-26 21:00:50 +02:00
Cargo.toml Merge #959 2022-10-26 19:14:12 +00:00
gen_tick.py time: add more tick rates, use 1mhz as default. 2022-09-02 00:59:34 +02:00
README.md Add readme for embassy-time 2022-08-23 13:58:57 +02:00

embassy-time

Timekeeping, delays and timeouts.

Timekeeping is done with elapsed time since system boot. Time is represented in ticks, where the tick rate is defined by the current driver, usually to match the tick rate of the hardware.

Tick counts are 64 bits. At the highest supported tick rate of 1Mhz this supports representing time spans of up to ~584558 years, which is big enough for all practical purposes and allows not having to worry about overflows.

[Instant] represents a given instant of time (relative to system boot), and [Duration] represents the duration of a span of time. They implement the math operations you'd expect, like addition and substraction.

Delays and timeouts

[Timer] allows performing async delays. [Ticker] allows periodic delays without drifting over time.

An implementation of the embedded-hal delay traits is provided by [Delay], for compatibility with libraries from the ecosystem.

Wall-clock time

The time module deals exclusively with a monotonically increasing tick count. Therefore it has no direct support for wall-clock time ("real life" datetimes like 2021-08-24 13:33:21).

If persistence across reboots is not needed, support can be built on top of embassy_time by storing the offset between "seconds elapsed since boot" and "seconds since unix epoch".

Time driver

The time module is backed by a global "time driver" specified at build time. Only one driver can be active in a program.

All methods and structs transparently call into the active driver. This makes it possible for libraries to use embassy_time in a driver-agnostic way without requiring generic parameters.

For more details, check the [driver] module.