diff options
| author | Dániel Buga <[email protected]> | 2024-12-15 19:24:49 +0100 |
|---|---|---|
| committer | Dániel Buga <[email protected]> | 2024-12-15 19:24:49 +0100 |
| commit | 0492dba5368e7cb22ede2d41d26d4d0431ba2252 (patch) | |
| tree | 735ad32cd3f40acbc57248373ab2622c8a9a03e3 /embassy-time-driver | |
| parent | e861344b179b3e955ac47f1985b7f97fdfb93892 (diff) | |
Update documentation and changelogs
Diffstat (limited to 'embassy-time-driver')
| -rw-r--r-- | embassy-time-driver/CHANGELOG.md | 3 | ||||
| -rw-r--r-- | embassy-time-driver/src/lib.rs | 79 |
2 files changed, 62 insertions, 20 deletions
diff --git a/embassy-time-driver/CHANGELOG.md b/embassy-time-driver/CHANGELOG.md index ebc37b6f4..2af1dc736 100644 --- a/embassy-time-driver/CHANGELOG.md +++ b/embassy-time-driver/CHANGELOG.md | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Changelog for embassy-time-queue-driver | 1 | # Changelog for embassy-time-driver |
| 2 | 2 | ||
| 3 | All notable changes to this project will be documented in this file. | 3 | All notable changes to this project will be documented in this file. |
| 4 | 4 | ||
| @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 8 | ## Unreleased | 8 | ## Unreleased |
| 9 | 9 | ||
| 10 | - The `allocate_alarm`, `set_alarm_callback`, `set_alarm` functions have been removed. | 10 | - The `allocate_alarm`, `set_alarm_callback`, `set_alarm` functions have been removed. |
| 11 | - `schedule_wake` has been added to the `Driver` trait. | ||
| 11 | 12 | ||
| 12 | ## 0.1.0 - 2024-01-11 | 13 | ## 0.1.0 - 2024-01-11 |
| 13 | 14 | ||
diff --git a/embassy-time-driver/src/lib.rs b/embassy-time-driver/src/lib.rs index 090969d8c..57a9f7587 100644 --- a/embassy-time-driver/src/lib.rs +++ b/embassy-time-driver/src/lib.rs | |||
| @@ -17,25 +17,7 @@ | |||
| 17 | //! Otherwise, don’t enable any `tick-hz-*` feature to let the user configure the tick rate themselves by | 17 | //! Otherwise, don’t enable any `tick-hz-*` feature to let the user configure the tick rate themselves by |
| 18 | //! enabling a feature on `embassy-time`. | 18 | //! enabling a feature on `embassy-time`. |
| 19 | //! | 19 | //! |
| 20 | //! # Linkage details | 20 | //! ### Example |
| 21 | //! | ||
| 22 | //! Instead of the usual "trait + generic params" approach, calls from embassy to the driver are done via `extern` functions. | ||
| 23 | //! | ||
| 24 | //! `embassy` internally defines the driver function as `extern "Rust" { fn _embassy_time_now() -> u64; }` and calls it. | ||
| 25 | //! The driver crate defines the function as `#[no_mangle] fn _embassy_time_now() -> u64`. The linker will resolve the | ||
| 26 | //! calls from the `embassy` crate to call into the driver crate. | ||
| 27 | //! | ||
| 28 | //! If there is none or multiple drivers in the crate tree, linking will fail. | ||
| 29 | //! | ||
| 30 | //! This method has a few key advantages for something as foundational as timekeeping: | ||
| 31 | //! | ||
| 32 | //! - The time driver is available everywhere easily, without having to thread the implementation | ||
| 33 | //! through generic parameters. This is especially helpful for libraries. | ||
| 34 | //! - It means comparing `Instant`s will always make sense: if there were multiple drivers | ||
| 35 | //! active, one could compare an `Instant` from driver A to an `Instant` from driver B, which | ||
| 36 | //! would yield incorrect results. | ||
| 37 | //! | ||
| 38 | //! # Example | ||
| 39 | //! | 21 | //! |
| 40 | //! ``` | 22 | //! ``` |
| 41 | //! use core::task::Waker; | 23 | //! use core::task::Waker; |
| @@ -56,6 +38,65 @@ | |||
| 56 | //! | 38 | //! |
| 57 | //! embassy_time_driver::time_driver_impl!(static DRIVER: MyDriver = MyDriver{}); | 39 | //! embassy_time_driver::time_driver_impl!(static DRIVER: MyDriver = MyDriver{}); |
| 58 | //! ``` | 40 | //! ``` |
| 41 | //! | ||
| 42 | //! ## Implementing the timer queue | ||
| 43 | //! | ||
| 44 | //! The simplest (but suboptimal) way to implement a timer queue is to define a single queue in the | ||
| 45 | //! time driver. Declare a field protected by an appropriate mutex (e.g. `critical_section::Mutex`). | ||
| 46 | //! | ||
| 47 | //! Then, you'll need to adapt the `schedule_wake` method to use this queue. | ||
| 48 | //! | ||
| 49 | //! ```ignore | ||
| 50 | //! use core::cell::RefCell; | ||
| 51 | //! use core::task::Waker; | ||
| 52 | //! | ||
| 53 | //! use embassy_time_queue_driver::Queue; | ||
| 54 | //! use embassy_time_driver::Driver; | ||
| 55 | //! | ||
| 56 | //! struct MyDriver { | ||
| 57 | //! timer_queue: critical_section::Mutex<RefCell<Queue>>, | ||
| 58 | //! } | ||
| 59 | //! | ||
| 60 | //! impl MyDriver { | ||
| 61 | //! fn set_alarm(&self, cs: &CriticalSection, at: u64) -> bool { | ||
| 62 | //! todo!() | ||
| 63 | //! } | ||
| 64 | //! } | ||
| 65 | //! | ||
| 66 | //! impl Driver for MyDriver { | ||
| 67 | //! // fn now(&self) -> u64 { ... } | ||
| 68 | //! | ||
| 69 | //! fn schedule_wake(&self, at: u64, waker: &Waker) { | ||
| 70 | //! critical_section::with(|cs| { | ||
| 71 | //! let mut queue = self.queue.borrow(cs).borrow_mut(); | ||
| 72 | //! if queue.schedule_wake(at, waker) { | ||
| 73 | //! let mut next = queue.next_expiration(self.now()); | ||
| 74 | //! while !self.set_alarm(cs, next) { | ||
| 75 | //! next = queue.next_expiration(self.now()); | ||
| 76 | //! } | ||
| 77 | //! } | ||
| 78 | //! }); | ||
| 79 | //! } | ||
| 80 | //! } | ||
| 81 | //! ``` | ||
| 82 | //! | ||
| 83 | //! # Linkage details | ||
| 84 | //! | ||
| 85 | //! Instead of the usual "trait + generic params" approach, calls from embassy to the driver are done via `extern` functions. | ||
| 86 | //! | ||
| 87 | //! `embassy` internally defines the driver function as `extern "Rust" { fn _embassy_time_now() -> u64; }` and calls it. | ||
| 88 | //! The driver crate defines the function as `#[no_mangle] fn _embassy_time_now() -> u64`. The linker will resolve the | ||
| 89 | //! calls from the `embassy` crate to call into the driver crate. | ||
| 90 | //! | ||
| 91 | //! If there is none or multiple drivers in the crate tree, linking will fail. | ||
| 92 | //! | ||
| 93 | //! This method has a few key advantages for something as foundational as timekeeping: | ||
| 94 | //! | ||
| 95 | //! - The time driver is available everywhere easily, without having to thread the implementation | ||
| 96 | //! through generic parameters. This is especially helpful for libraries. | ||
| 97 | //! - It means comparing `Instant`s will always make sense: if there were multiple drivers | ||
| 98 | //! active, one could compare an `Instant` from driver A to an `Instant` from driver B, which | ||
| 99 | //! would yield incorrect results. | ||
| 59 | 100 | ||
| 60 | //! ## Feature flags | 101 | //! ## Feature flags |
| 61 | #![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)] | 102 | #![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)] |
