embassy-time-driver

Crates

git

Versions

default

Flavors

Crate embassy_time_driver

Source
Expand description

§embassy-time-driver

This crate contains the driver trait necessary for adding embassy-time support for a new hardware platform.

If you want to use embassy-time with already made drivers, you should depend on the main embassy-time crate, not on this crate.

If you are writing a driver, you should depend only on this crate, not on the main embassy-time crate. This will allow your driver to continue working for newer embassy-time major versions, without needing an update, if the driver trait has not had breaking changes.

§How it works

embassy-time 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.

§Implementing a driver

If your driver has a single set tick rate, enable the corresponding tick-hz-* feature, which will prevent users from needing to configure it themselves (or selecting an incorrect configuration).

If your driver supports a small number of set tick rates, expose your own cargo features and have each one enable the corresponding embassy-time-driver/tick-*.

Otherwise, don’t enable any tick-hz-* feature to let the user configure the tick rate themselves by enabling a feature on embassy-time.

§Example

use core::task::Waker;

use embassy_time_driver::Driver;

struct MyDriver{} // not public!

impl Driver for MyDriver {
    fn now(&self) -> u64 {
        todo!()
    }

    fn schedule_wake(&self, at: u64, waker: &Waker) {
        todo!()
    }
}

embassy_time_driver::time_driver_impl!(static DRIVER: MyDriver = MyDriver{});

§Implementing the timer queue

The simplest (but suboptimal) way to implement a timer queue is to define a single queue in the time driver. Declare a field protected by an appropriate mutex (e.g. critical_section::Mutex).

Then, you’ll need to adapt the schedule_wake method to use this queue.

Note that if you are using multiple queues, you will need to ensure that a single timer queue item is only ever enqueued into a single queue at a time.

use core::cell::RefCell;
use core::task::Waker;

use embassy_time_queue_driver::Queue;
use embassy_time_driver::Driver;

struct MyDriver {
    timer_queue: critical_section::Mutex<RefCell<Queue>>,
}

impl MyDriver {
   fn set_alarm(&self, cs: &CriticalSection, at: u64) -> bool {
       todo!()
   }
}

impl Driver for MyDriver {
    // fn now(&self) -> u64 { ... }

    fn schedule_wake(&self, at: u64, waker: &Waker) {
        critical_section::with(|cs| {
            let mut queue = self.queue.borrow(cs).borrow_mut();
            if queue.schedule_wake(at, waker) {
                let mut next = queue.next_expiration(self.now());
                while !self.set_alarm(cs, next) {
                    next = queue.next_expiration(self.now());
                }
            }
        });
    }
}

§Linkage details

Instead of the usual “trait + generic params” approach, calls from embassy to the driver are done via extern functions.

embassy internally defines the driver function as extern "Rust" { fn _embassy_time_now() -> u64; } and calls it. The driver crate defines the function as #[no_mangle] fn _embassy_time_now() -> u64. The linker will resolve the calls from the embassy crate to call into the driver crate.

If there is none or multiple drivers in the crate tree, linking will fail.

This method has a few key advantages for something as foundational as timekeeping:

  • The time driver is available everywhere easily, without having to thread the implementation through generic parameters. This is especially helpful for libraries.
  • It means comparing Instants will always make sense: if there were multiple drivers active, one could compare an Instant from driver A to an Instant from driver B, which would yield incorrect results.

§Feature flags

§Tick Rate

At most 1 tick-* feature can be enabled. If none is enabled, a default of 1MHz is used.

If the time driver in use supports using arbitrary tick rates, you can enable one tick-* feature from your binary crate to set the tick rate. The driver will use configured tick rate. If the time driver supports a fixed tick rate, it will enable one feature itself, so you should not enable one. Check the time driver documentation for details.

When using embassy-time from libraries, you should not enable any tick-* feature, to allow the end user or the driver to pick.

Available tick rates:
  • tick-hz-1 — 1Hz Tick Rate
  • tick-hz-2 — 2Hz Tick Rate
  • tick-hz-4 — 4Hz Tick Rate
  • tick-hz-8 — 8Hz Tick Rate
  • tick-hz-10 — 10Hz Tick Rate
  • tick-hz-16 — 16Hz Tick Rate
  • tick-hz-32 — 32Hz Tick Rate
  • tick-hz-64 — 64Hz Tick Rate
  • tick-hz-100 — 100Hz Tick Rate
  • tick-hz-128 — 128Hz Tick Rate
  • tick-hz-256 — 256Hz Tick Rate
  • tick-hz-512 — 512Hz Tick Rate
  • tick-hz-1_000 — 1.0kHz Tick Rate
  • tick-hz-1_024 — 1.024kHz Tick Rate
  • tick-hz-2_000 — 2.0kHz Tick Rate
  • tick-hz-2_048 — 2.048kHz Tick Rate
  • tick-hz-4_000 — 4.0kHz Tick Rate
  • tick-hz-4_096 — 4.096kHz Tick Rate
  • tick-hz-8_000 — 8.0kHz Tick Rate
  • tick-hz-8_192 — 8.192kHz Tick Rate
  • tick-hz-10_000 — 10.0kHz Tick Rate
  • tick-hz-16_000 — 16.0kHz Tick Rate
  • tick-hz-16_384 — 16.384kHz Tick Rate
  • tick-hz-20_000 — 20.0kHz Tick Rate
  • tick-hz-32_000 — 32.0kHz Tick Rate
  • tick-hz-32_768 — 32.768kHz Tick Rate
  • tick-hz-40_000 — 40.0kHz Tick Rate
  • tick-hz-64_000 — 64.0kHz Tick Rate
  • tick-hz-65_536 — 65.536kHz Tick Rate
  • tick-hz-80_000 — 80.0kHz Tick Rate
  • tick-hz-100_000 — 100.0kHz Tick Rate
  • tick-hz-128_000 — 128.0kHz Tick Rate
  • tick-hz-131_072 — 131.072kHz Tick Rate
  • tick-hz-160_000 — 160.0kHz Tick Rate
  • tick-hz-256_000 — 256.0kHz Tick Rate
  • tick-hz-262_144 — 262.144kHz Tick Rate
  • tick-hz-320_000 — 320.0kHz Tick Rate
  • tick-hz-512_000 — 512.0kHz Tick Rate
  • tick-hz-524_288 — 524.288kHz Tick Rate
  • tick-hz-640_000 — 640.0kHz Tick Rate
  • tick-hz-1_000_000 — 1.0MHz Tick Rate
  • tick-hz-1_024_000 — 1.024MHz Tick Rate
  • tick-hz-1_048_576 — 1.048576MHz Tick Rate
  • tick-hz-1_280_000 — 1.28MHz Tick Rate
  • tick-hz-2_000_000 — 2.0MHz Tick Rate
  • tick-hz-2_048_000 — 2.048MHz Tick Rate
  • tick-hz-2_097_152 — 2.097152MHz Tick Rate
  • tick-hz-2_560_000 — 2.56MHz Tick Rate
  • tick-hz-3_000_000 — 3.0MHz Tick Rate
  • tick-hz-4_000_000 — 4.0MHz Tick Rate
  • tick-hz-4_096_000 — 4.096MHz Tick Rate
  • tick-hz-4_194_304 — 4.194304MHz Tick Rate
  • tick-hz-5_120_000 — 5.12MHz Tick Rate
  • tick-hz-6_000_000 — 6.0MHz Tick Rate
  • tick-hz-8_000_000 — 8.0MHz Tick Rate
  • tick-hz-8_192_000 — 8.192MHz Tick Rate
  • tick-hz-8_388_608 — 8.388608MHz Tick Rate
  • tick-hz-9_000_000 — 9.0MHz Tick Rate
  • tick-hz-10_000_000 — 10.0MHz Tick Rate
  • tick-hz-10_240_000 — 10.24MHz Tick Rate
  • tick-hz-12_000_000 — 12.0MHz Tick Rate
  • tick-hz-16_000_000 — 16.0MHz Tick Rate
  • tick-hz-16_384_000 — 16.384MHz Tick Rate
  • tick-hz-16_777_216 — 16.777216MHz Tick Rate
  • tick-hz-18_000_000 — 18.0MHz Tick Rate
  • tick-hz-20_000_000 — 20.0MHz Tick Rate
  • tick-hz-20_480_000 — 20.48MHz Tick Rate
  • tick-hz-24_000_000 — 24.0MHz Tick Rate
  • tick-hz-30_000_000 — 30.0MHz Tick Rate
  • tick-hz-32_000_000 — 32.0MHz Tick Rate
  • tick-hz-32_768_000 — 32.768MHz Tick Rate
  • tick-hz-36_000_000 — 36.0MHz Tick Rate
  • tick-hz-40_000_000 — 40.0MHz Tick Rate
  • tick-hz-40_960_000 — 40.96MHz Tick Rate
  • tick-hz-48_000_000 — 48.0MHz Tick Rate
  • tick-hz-50_000_000 — 50.0MHz Tick Rate
  • tick-hz-60_000_000 — 60.0MHz Tick Rate
  • tick-hz-64_000_000 — 64.0MHz Tick Rate
  • tick-hz-65_536_000 — 65.536MHz Tick Rate
  • tick-hz-70_000_000 — 70.0MHz Tick Rate
  • tick-hz-72_000_000 — 72.0MHz Tick Rate
  • tick-hz-80_000_000 — 80.0MHz Tick Rate
  • tick-hz-81_920_000 — 81.92MHz Tick Rate
  • tick-hz-90_000_000 — 90.0MHz Tick Rate
  • tick-hz-96_000_000 — 96.0MHz Tick Rate
  • tick-hz-100_000_000 — 100.0MHz Tick Rate
  • tick-hz-110_000_000 — 110.0MHz Tick Rate
  • tick-hz-120_000_000 — 120.0MHz Tick Rate
  • tick-hz-128_000_000 — 128.0MHz Tick Rate
  • tick-hz-130_000_000 — 130.0MHz Tick Rate
  • tick-hz-131_072_000 — 131.072MHz Tick Rate
  • tick-hz-140_000_000 — 140.0MHz Tick Rate
  • tick-hz-144_000_000 — 144.0MHz Tick Rate
  • tick-hz-150_000_000 — 150.0MHz Tick Rate
  • tick-hz-160_000_000 — 160.0MHz Tick Rate
  • tick-hz-163_840_000 — 163.84MHz Tick Rate
  • tick-hz-170_000_000 — 170.0MHz Tick Rate
  • tick-hz-180_000_000 — 180.0MHz Tick Rate
  • tick-hz-190_000_000 — 190.0MHz Tick Rate
  • tick-hz-192_000_000 — 192.0MHz Tick Rate
  • tick-hz-200_000_000 — 200.0MHz Tick Rate
  • tick-hz-210_000_000 — 210.0MHz Tick Rate
  • tick-hz-220_000_000 — 220.0MHz Tick Rate
  • tick-hz-230_000_000 — 230.0MHz Tick Rate
  • tick-hz-240_000_000 — 240.0MHz Tick Rate
  • tick-hz-250_000_000 — 250.0MHz Tick Rate
  • tick-hz-256_000_000 — 256.0MHz Tick Rate
  • tick-hz-260_000_000 — 260.0MHz Tick Rate
  • tick-hz-262_144_000 — 262.144MHz Tick Rate
  • tick-hz-270_000_000 — 270.0MHz Tick Rate
  • tick-hz-280_000_000 — 280.0MHz Tick Rate
  • tick-hz-288_000_000 — 288.0MHz Tick Rate
  • tick-hz-290_000_000 — 290.0MHz Tick Rate
  • tick-hz-300_000_000 — 300.0MHz Tick Rate
  • tick-hz-320_000_000 — 320.0MHz Tick Rate
  • tick-hz-327_680_000 — 327.68MHz Tick Rate
  • tick-hz-340_000_000 — 340.0MHz Tick Rate
  • tick-hz-360_000_000 — 360.0MHz Tick Rate
  • tick-hz-380_000_000 — 380.0MHz Tick Rate
  • tick-hz-384_000_000 — 384.0MHz Tick Rate
  • tick-hz-400_000_000 — 400.0MHz Tick Rate
  • tick-hz-420_000_000 — 420.0MHz Tick Rate
  • tick-hz-440_000_000 — 440.0MHz Tick Rate
  • tick-hz-460_000_000 — 460.0MHz Tick Rate
  • tick-hz-480_000_000 — 480.0MHz Tick Rate
  • tick-hz-500_000_000 — 500.0MHz Tick Rate
  • tick-hz-512_000_000 — 512.0MHz Tick Rate
  • tick-hz-520_000_000 — 520.0MHz Tick Rate
  • tick-hz-524_288_000 — 524.288MHz Tick Rate
  • tick-hz-540_000_000 — 540.0MHz Tick Rate
  • tick-hz-560_000_000 — 560.0MHz Tick Rate
  • tick-hz-576_000_000 — 576.0MHz Tick Rate
  • tick-hz-580_000_000 — 580.0MHz Tick Rate
  • tick-hz-600_000_000 — 600.0MHz Tick Rate
  • tick-hz-620_000_000 — 620.0MHz Tick Rate
  • tick-hz-640_000_000 — 640.0MHz Tick Rate
  • tick-hz-655_360_000 — 655.36MHz Tick Rate
  • tick-hz-660_000_000 — 660.0MHz Tick Rate
  • tick-hz-680_000_000 — 680.0MHz Tick Rate
  • tick-hz-700_000_000 — 700.0MHz Tick Rate
  • tick-hz-720_000_000 — 720.0MHz Tick Rate
  • tick-hz-740_000_000 — 740.0MHz Tick Rate
  • tick-hz-760_000_000 — 760.0MHz Tick Rate
  • tick-hz-768_000_000 — 768.0MHz Tick Rate
  • tick-hz-780_000_000 — 780.0MHz Tick Rate
  • tick-hz-800_000_000 — 800.0MHz Tick Rate
  • tick-hz-820_000_000 — 820.0MHz Tick Rate
  • tick-hz-840_000_000 — 840.0MHz Tick Rate
  • tick-hz-860_000_000 — 860.0MHz Tick Rate
  • tick-hz-880_000_000 — 880.0MHz Tick Rate
  • tick-hz-900_000_000 — 900.0MHz Tick Rate
  • tick-hz-920_000_000 — 920.0MHz Tick Rate
  • tick-hz-940_000_000 — 940.0MHz Tick Rate
  • tick-hz-960_000_000 — 960.0MHz Tick Rate
  • tick-hz-980_000_000 — 980.0MHz Tick Rate
  • tick-hz-1_000_000_000 — 1.0GHz Tick Rate
  • tick-hz-1_310_720_000 — 1.31072GHz Tick Rate
  • tick-hz-2_621_440_000 — 2.62144GHz Tick Rate
  • tick-hz-5_242_880_000 — 5.24288GHz Tick Rate

Macros§

Constants§

  • Ticks per second of the global timebase.

Traits§

Functions§