diff options
| -rw-r--r-- | embassy/src/time/duration.rs | 13 | ||||
| -rw-r--r-- | embassy/src/time/instant.rs | 15 | ||||
| -rw-r--r-- | embassy/src/time/mod.rs | 9 |
3 files changed, 34 insertions, 3 deletions
diff --git a/embassy/src/time/duration.rs b/embassy/src/time/duration.rs index e04afa184..5157450ad 100644 --- a/embassy/src/time/duration.rs +++ b/embassy/src/time/duration.rs | |||
| @@ -5,6 +5,7 @@ use super::TICKS_PER_SECOND; | |||
| 5 | 5 | ||
| 6 | #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] | 6 | #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
| 7 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 7 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 8 | /// Represents the difference between two [Instant](struct.Instant.html)s | ||
| 8 | pub struct Duration { | 9 | pub struct Duration { |
| 9 | pub(crate) ticks: u64, | 10 | pub(crate) ticks: u64, |
| 10 | } | 11 | } |
| @@ -26,49 +27,55 @@ impl Duration { | |||
| 26 | self.ticks * 1_000_000 / TICKS_PER_SECOND | 27 | self.ticks * 1_000_000 / TICKS_PER_SECOND |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 30 | /// Creates a duration from the specified number of clock ticks | ||
| 29 | pub const fn from_ticks(ticks: u64) -> Duration { | 31 | pub const fn from_ticks(ticks: u64) -> Duration { |
| 30 | Duration { ticks } | 32 | Duration { ticks } |
| 31 | } | 33 | } |
| 32 | 34 | ||
| 35 | /// Creates a duration from the specified number of seconds | ||
| 33 | pub const fn from_secs(secs: u64) -> Duration { | 36 | pub const fn from_secs(secs: u64) -> Duration { |
| 34 | Duration { | 37 | Duration { |
| 35 | ticks: secs * TICKS_PER_SECOND, | 38 | ticks: secs * TICKS_PER_SECOND, |
| 36 | } | 39 | } |
| 37 | } | 40 | } |
| 38 | 41 | ||
| 42 | /// Creates a duration from the specified number of milliseconds | ||
| 39 | pub const fn from_millis(millis: u64) -> Duration { | 43 | pub const fn from_millis(millis: u64) -> Duration { |
| 40 | Duration { | 44 | Duration { |
| 41 | ticks: millis * TICKS_PER_SECOND / 1000, | 45 | ticks: millis * TICKS_PER_SECOND / 1000, |
| 42 | } | 46 | } |
| 43 | } | 47 | } |
| 44 | 48 | ||
| 45 | /* | 49 | /// Creates a duration from the specified number of microseconds |
| 46 | NOTE: us delays may not be as accurate | 50 | /// NOTE: Delays this small may be inaccurate. |
| 47 | */ | ||
| 48 | pub const fn from_micros(micros: u64) -> Duration { | 51 | pub const fn from_micros(micros: u64) -> Duration { |
| 49 | Duration { | 52 | Duration { |
| 50 | ticks: micros * TICKS_PER_SECOND / 1_000_000, | 53 | ticks: micros * TICKS_PER_SECOND / 1_000_000, |
| 51 | } | 54 | } |
| 52 | } | 55 | } |
| 53 | 56 | ||
| 57 | /// Adds one Duration to another, returning a new Duration or None in the event of an overflow. | ||
| 54 | pub fn checked_add(self, rhs: Duration) -> Option<Duration> { | 58 | pub fn checked_add(self, rhs: Duration) -> Option<Duration> { |
| 55 | self.ticks | 59 | self.ticks |
| 56 | .checked_add(rhs.ticks) | 60 | .checked_add(rhs.ticks) |
| 57 | .map(|ticks| Duration { ticks }) | 61 | .map(|ticks| Duration { ticks }) |
| 58 | } | 62 | } |
| 59 | 63 | ||
| 64 | /// Subtracts one Duration to another, returning a new Duration or None in the event of an overflow. | ||
| 60 | pub fn checked_sub(self, rhs: Duration) -> Option<Duration> { | 65 | pub fn checked_sub(self, rhs: Duration) -> Option<Duration> { |
| 61 | self.ticks | 66 | self.ticks |
| 62 | .checked_sub(rhs.ticks) | 67 | .checked_sub(rhs.ticks) |
| 63 | .map(|ticks| Duration { ticks }) | 68 | .map(|ticks| Duration { ticks }) |
| 64 | } | 69 | } |
| 65 | 70 | ||
| 71 | /// Multiplies one Duration by a scalar u32, returning a new Duration or None in the event of an overflow. | ||
| 66 | pub fn checked_mul(self, rhs: u32) -> Option<Duration> { | 72 | pub fn checked_mul(self, rhs: u32) -> Option<Duration> { |
| 67 | self.ticks | 73 | self.ticks |
| 68 | .checked_mul(rhs as _) | 74 | .checked_mul(rhs as _) |
| 69 | .map(|ticks| Duration { ticks }) | 75 | .map(|ticks| Duration { ticks }) |
| 70 | } | 76 | } |
| 71 | 77 | ||
| 78 | /// Divides one Duration a scalar u32, returning a new Duration or None in the event of an overflow. | ||
| 72 | pub fn checked_div(self, rhs: u32) -> Option<Duration> { | 79 | pub fn checked_div(self, rhs: u32) -> Option<Duration> { |
| 73 | self.ticks | 80 | self.ticks |
| 74 | .checked_div(rhs as _) | 81 | .checked_div(rhs as _) |
diff --git a/embassy/src/time/instant.rs b/embassy/src/time/instant.rs index 06ab84c75..61a61defe 100644 --- a/embassy/src/time/instant.rs +++ b/embassy/src/time/instant.rs | |||
| @@ -6,6 +6,7 @@ use super::{now, Duration}; | |||
| 6 | 6 | ||
| 7 | #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] | 7 | #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
| 8 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 8 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 9 | /// An Instant in time, based on the MCU's clock ticks since startup. | ||
| 9 | pub struct Instant { | 10 | pub struct Instant { |
| 10 | ticks: u64, | 11 | ticks: u64, |
| 11 | } | 12 | } |
| @@ -14,44 +15,55 @@ impl Instant { | |||
| 14 | pub const MIN: Instant = Instant { ticks: u64::MIN }; | 15 | pub const MIN: Instant = Instant { ticks: u64::MIN }; |
| 15 | pub const MAX: Instant = Instant { ticks: u64::MAX }; | 16 | pub const MAX: Instant = Instant { ticks: u64::MAX }; |
| 16 | 17 | ||
| 18 | /// Returns an Instant representing the current time. | ||
| 17 | pub fn now() -> Instant { | 19 | pub fn now() -> Instant { |
| 18 | Instant { ticks: now() } | 20 | Instant { ticks: now() } |
| 19 | } | 21 | } |
| 20 | 22 | ||
| 23 | /// Instant as clock ticks since MCU start. | ||
| 21 | pub const fn from_ticks(ticks: u64) -> Self { | 24 | pub const fn from_ticks(ticks: u64) -> Self { |
| 22 | Self { ticks } | 25 | Self { ticks } |
| 23 | } | 26 | } |
| 24 | 27 | ||
| 28 | /// Instant as milliseconds since MCU start. | ||
| 25 | pub const fn from_millis(millis: u64) -> Self { | 29 | pub const fn from_millis(millis: u64) -> Self { |
| 26 | Self { | 30 | Self { |
| 27 | ticks: millis * TICKS_PER_SECOND as u64 / 1000, | 31 | ticks: millis * TICKS_PER_SECOND as u64 / 1000, |
| 28 | } | 32 | } |
| 29 | } | 33 | } |
| 30 | 34 | ||
| 35 | /// Instant representing seconds since MCU start. | ||
| 31 | pub const fn from_secs(seconds: u64) -> Self { | 36 | pub const fn from_secs(seconds: u64) -> Self { |
| 32 | Self { | 37 | Self { |
| 33 | ticks: seconds * TICKS_PER_SECOND as u64, | 38 | ticks: seconds * TICKS_PER_SECOND as u64, |
| 34 | } | 39 | } |
| 35 | } | 40 | } |
| 36 | 41 | ||
| 42 | /// Instant as ticks since MCU start. | ||
| 43 | |||
| 37 | pub const fn as_ticks(&self) -> u64 { | 44 | pub const fn as_ticks(&self) -> u64 { |
| 38 | self.ticks | 45 | self.ticks |
| 39 | } | 46 | } |
| 47 | /// Instant as seconds since MCU start. | ||
| 40 | 48 | ||
| 41 | pub const fn as_secs(&self) -> u64 { | 49 | pub const fn as_secs(&self) -> u64 { |
| 42 | self.ticks / TICKS_PER_SECOND as u64 | 50 | self.ticks / TICKS_PER_SECOND as u64 |
| 43 | } | 51 | } |
| 52 | /// Instant as miliseconds since MCU start. | ||
| 44 | 53 | ||
| 45 | pub const fn as_millis(&self) -> u64 { | 54 | pub const fn as_millis(&self) -> u64 { |
| 46 | self.ticks * 1000 / TICKS_PER_SECOND as u64 | 55 | self.ticks * 1000 / TICKS_PER_SECOND as u64 |
| 47 | } | 56 | } |
| 48 | 57 | ||
| 58 | /// Duration between this Instant and another Instant | ||
| 59 | /// Panics on over/underflow. | ||
| 49 | pub fn duration_since(&self, earlier: Instant) -> Duration { | 60 | pub fn duration_since(&self, earlier: Instant) -> Duration { |
| 50 | Duration { | 61 | Duration { |
| 51 | ticks: self.ticks.checked_sub(earlier.ticks).unwrap(), | 62 | ticks: self.ticks.checked_sub(earlier.ticks).unwrap(), |
| 52 | } | 63 | } |
| 53 | } | 64 | } |
| 54 | 65 | ||
| 66 | /// Duration between this Instant and another Instant | ||
| 55 | pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> { | 67 | pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> { |
| 56 | if self.ticks < earlier.ticks { | 68 | if self.ticks < earlier.ticks { |
| 57 | None | 69 | None |
| @@ -62,6 +74,8 @@ impl Instant { | |||
| 62 | } | 74 | } |
| 63 | } | 75 | } |
| 64 | 76 | ||
| 77 | /// Returns the duration since the "earlier" Instant. | ||
| 78 | /// If the "earlier" instant is in the future, the duration is set to zero. | ||
| 65 | pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { | 79 | pub fn saturating_duration_since(&self, earlier: Instant) -> Duration { |
| 66 | Duration { | 80 | Duration { |
| 67 | ticks: if self.ticks < earlier.ticks { | 81 | ticks: if self.ticks < earlier.ticks { |
| @@ -72,6 +86,7 @@ impl Instant { | |||
| 72 | } | 86 | } |
| 73 | } | 87 | } |
| 74 | 88 | ||
| 89 | /// Duration elapsed since this Instant. | ||
| 75 | pub fn elapsed(&self) -> Duration { | 90 | pub fn elapsed(&self) -> Duration { |
| 76 | Instant::now() - *self | 91 | Instant::now() - *self |
| 77 | } | 92 | } |
diff --git a/embassy/src/time/mod.rs b/embassy/src/time/mod.rs index b45a608dd..4e9b5f592 100644 --- a/embassy/src/time/mod.rs +++ b/embassy/src/time/mod.rs | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | //! Time abstractions | ||
| 2 | //! To use these abstractions, first call `set_clock` with an instance of an [Clock](trait.Clock.html). | ||
| 3 | //! | ||
| 1 | mod duration; | 4 | mod duration; |
| 2 | mod instant; | 5 | mod instant; |
| 3 | mod traits; | 6 | mod traits; |
| @@ -14,10 +17,16 @@ pub const TICKS_PER_SECOND: u64 = 32768; | |||
| 14 | 17 | ||
| 15 | static mut CLOCK: Option<&'static dyn Clock> = None; | 18 | static mut CLOCK: Option<&'static dyn Clock> = None; |
| 16 | 19 | ||
| 20 | /// Sets the clock used for the timing abstractions | ||
| 21 | /// | ||
| 22 | /// Safety: Sets a mutable global. | ||
| 17 | pub unsafe fn set_clock(clock: &'static dyn Clock) { | 23 | pub unsafe fn set_clock(clock: &'static dyn Clock) { |
| 18 | CLOCK = Some(clock); | 24 | CLOCK = Some(clock); |
| 19 | } | 25 | } |
| 20 | 26 | ||
| 27 | /// Return the current timestamp in ticks. | ||
| 28 | /// This is guaranteed to be monotonic, i.e. a call to now() will always return | ||
| 29 | /// a greater or equal value than earler calls. | ||
| 21 | pub(crate) fn now() -> u64 { | 30 | pub(crate) fn now() -> u64 { |
| 22 | unsafe { unwrap!(CLOCK, "No clock set").now() } | 31 | unsafe { unwrap!(CLOCK, "No clock set").now() } |
| 23 | } | 32 | } |
