esp_hal/
time.rs

1//! # Timekeeping
2//!
3//! This module provides types for representing frequency and duration, as well
4//! as an instant in time. Time is measured since boot, and can be accessed
5//! by the [`Instant::now`] function.
6
7use core::fmt::{Debug, Display, Formatter, Result as FmtResult};
8
9#[cfg(esp32)]
10use crate::peripherals::TIMG0;
11
12type InnerRate = fugit::Rate<u32, 1, 1>;
13type InnerInstant = fugit::Instant<u64, 1, 1_000_000>;
14type InnerDuration = fugit::Duration<u64, 1, 1_000_000>;
15
16/// Represents a rate or frequency of events.
17#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
18pub struct Rate(InnerRate);
19
20impl core::hash::Hash for Rate {
21    #[inline]
22    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
23        self.as_hz().hash(state);
24    }
25}
26
27impl Display for Rate {
28    #[inline]
29    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
30        write!(f, "{} Hz", self.as_hz())
31    }
32}
33
34impl Debug for Rate {
35    #[inline]
36    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
37        write!(f, "Rate({} Hz)", self.as_hz())
38    }
39}
40
41#[cfg(feature = "defmt")]
42impl defmt::Format for Rate {
43    #[inline]
44    fn format(&self, f: defmt::Formatter<'_>) {
45        defmt::write!(f, "{=u32} Hz", self.as_hz())
46    }
47}
48
49impl Rate {
50    /// Shorthand for creating a rate which represents hertz.
51    #[inline]
52    pub const fn from_hz(val: u32) -> Self {
53        Self(InnerRate::Hz(val))
54    }
55
56    /// Shorthand for creating a rate which represents kilohertz.
57    #[inline]
58    pub const fn from_khz(val: u32) -> Self {
59        Self(InnerRate::kHz(val))
60    }
61
62    /// Shorthand for creating a rate which represents megahertz.
63    #[inline]
64    pub const fn from_mhz(val: u32) -> Self {
65        Self(InnerRate::MHz(val))
66    }
67
68    /// Convert the `Rate` to an interger number of Hz.
69    #[inline]
70    pub const fn as_hz(&self) -> u32 {
71        self.0.to_Hz()
72    }
73
74    /// Convert the `Rate` to an interger number of kHz.
75    #[inline]
76    pub const fn as_khz(&self) -> u32 {
77        self.0.to_kHz()
78    }
79
80    /// Convert the `Rate` to an interger number of MHz.
81    #[inline]
82    pub const fn as_mhz(&self) -> u32 {
83        self.0.to_MHz()
84    }
85
86    /// Convert the `Rate` to a `Duration`.
87    #[inline]
88    pub const fn as_duration(&self) -> Duration {
89        Duration::from_micros(1_000_000 / self.as_hz() as u64)
90    }
91}
92
93impl core::ops::Div for Rate {
94    type Output = u32;
95
96    #[inline]
97    fn div(self, rhs: Self) -> Self::Output {
98        self.0 / rhs.0
99    }
100}
101
102impl core::ops::Mul<u32> for Rate {
103    type Output = Rate;
104
105    #[inline]
106    fn mul(self, rhs: u32) -> Self::Output {
107        Rate(self.0 * rhs)
108    }
109}
110
111impl core::ops::Div<u32> for Rate {
112    type Output = Rate;
113
114    #[inline]
115    fn div(self, rhs: u32) -> Self::Output {
116        Rate(self.0 / rhs)
117    }
118}
119
120/// Represents an instant in time.
121#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
122pub struct Instant(InnerInstant);
123
124impl Debug for Instant {
125    #[inline]
126    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
127        write!(
128            f,
129            "Instant({} µs since epoch)",
130            self.duration_since_epoch().as_micros()
131        )
132    }
133}
134
135impl Display for Instant {
136    #[inline]
137    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
138        write!(
139            f,
140            "{} µs since epoch",
141            self.duration_since_epoch().as_micros()
142        )
143    }
144}
145
146#[cfg(feature = "defmt")]
147impl defmt::Format for Instant {
148    #[inline]
149    fn format(&self, f: defmt::Formatter<'_>) {
150        defmt::write!(
151            f,
152            "{=u64} µs since epoch",
153            self.duration_since_epoch().as_micros()
154        )
155    }
156}
157
158impl Instant {
159    /// Represents the moment the system booted.
160    pub const EPOCH: Instant = Instant(InnerInstant::from_ticks(0));
161
162    /// Returns the current instant.
163    ///
164    /// The counter won’t measure time in sleep-mode.
165    ///
166    /// The timer has a 1 microsecond resolution and will wrap after
167    #[cfg_attr(esp32, doc = "36_558 years")]
168    #[cfg_attr(esp32s2, doc = "7_311 years")]
169    #[cfg_attr(not(any(esp32, esp32s2)), doc = "more than 7 years")]
170    #[inline]
171    pub fn now() -> Self {
172        now()
173    }
174
175    #[inline]
176    pub(crate) fn from_ticks(ticks: u64) -> Self {
177        Instant(InnerInstant::from_ticks(ticks))
178    }
179
180    /// Returns the elapsed `Duration` since boot.
181    #[inline]
182    pub fn duration_since_epoch(&self) -> Duration {
183        Self::EPOCH.elapsed()
184    }
185
186    /// Returns the elapsed `Duration` since this `Instant` was created.
187    #[inline]
188    pub fn elapsed(&self) -> Duration {
189        Self::now() - *self
190    }
191}
192
193impl core::ops::Add<Duration> for Instant {
194    type Output = Self;
195
196    #[inline]
197    fn add(self, rhs: Duration) -> Self::Output {
198        Instant(self.0 + rhs.0)
199    }
200}
201
202impl core::ops::AddAssign<Duration> for Instant {
203    #[inline]
204    fn add_assign(&mut self, rhs: Duration) {
205        self.0 += rhs.0;
206    }
207}
208
209impl core::ops::Sub for Instant {
210    type Output = Duration;
211
212    #[inline]
213    fn sub(self, rhs: Self) -> Self::Output {
214        Duration(self.0 - rhs.0)
215    }
216}
217
218impl core::ops::Sub<Duration> for Instant {
219    type Output = Self;
220
221    #[inline]
222    fn sub(self, rhs: Duration) -> Self::Output {
223        Instant(self.0 - rhs.0)
224    }
225}
226
227impl core::ops::SubAssign<Duration> for Instant {
228    #[inline]
229    fn sub_assign(&mut self, rhs: Duration) {
230        self.0 -= rhs.0;
231    }
232}
233
234/// Represents a duration of time.
235#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
236pub struct Duration(InnerDuration);
237
238impl Debug for Duration {
239    #[inline]
240    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
241        write!(f, "Duration({} µs)", self.as_micros())
242    }
243}
244
245impl Display for Duration {
246    #[inline]
247    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
248        write!(f, "{} µs", self.as_micros())
249    }
250}
251
252#[cfg(feature = "defmt")]
253impl defmt::Format for Duration {
254    #[inline]
255    fn format(&self, f: defmt::Formatter<'_>) {
256        defmt::write!(f, "{=u64} µs", self.as_micros())
257    }
258}
259
260impl Duration {
261    /// A duration of zero time.
262    pub const ZERO: Self = Self(InnerDuration::from_ticks(0));
263
264    /// A duration representing the maximum possible time.
265    pub const MAX: Self = Self(InnerDuration::from_ticks(u64::MAX));
266
267    /// Creates a duration which represents microseconds.
268    #[inline]
269    pub const fn from_micros(val: u64) -> Self {
270        Self(InnerDuration::micros(val))
271    }
272
273    /// Creates a duration which represents milliseconds.
274    #[inline]
275    pub const fn from_millis(val: u64) -> Self {
276        Self(InnerDuration::millis(val))
277    }
278
279    /// Creates a duration which represents seconds.
280    #[inline]
281    pub const fn from_secs(val: u64) -> Self {
282        Self(InnerDuration::secs(val))
283    }
284
285    /// Creates a duration which represents minutes.
286    #[inline]
287    pub const fn from_minutes(val: u64) -> Self {
288        Self(InnerDuration::minutes(val))
289    }
290
291    /// Creates a duration which represents hours.
292    #[inline]
293    pub const fn from_hours(val: u64) -> Self {
294        Self(InnerDuration::hours(val))
295    }
296
297    delegate::delegate! {
298        #[inline]
299        to self.0 {
300            /// Convert the `Duration` to an interger number of microseconds.
301            #[call(to_micros)]
302            pub const fn as_micros(&self) -> u64;
303
304            /// Convert the `Duration` to an interger number of milliseconds.
305            #[call(to_millis)]
306            pub const fn as_millis(&self) -> u64;
307
308            /// Convert the `Duration` to an interger number of seconds.
309            #[call(to_secs)]
310            pub const fn as_secs(&self) -> u64;
311
312            /// Convert the `Duration` to an interger number of minutes.
313            #[call(to_minutes)]
314            pub const fn as_minutes(&self) -> u64;
315
316            /// Convert the `Duration` to an interger number of hours.
317            #[call(to_hours)]
318            pub const fn as_hours(&self) -> u64;
319        }
320    }
321
322    /// Add two durations while checking for overflow.
323    #[inline]
324    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
325        if let Some(val) = self.0.checked_add(rhs.0) {
326            Some(Duration(val))
327        } else {
328            None
329        }
330    }
331
332    /// Subtract two durations while checking for overflow.
333    #[inline]
334    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
335        if let Some(val) = self.0.checked_sub(rhs.0) {
336            Some(Duration(val))
337        } else {
338            None
339        }
340    }
341
342    /// Add two durations, returning the maximum value if overflow occurred.
343    #[inline]
344    pub const fn saturating_add(self, rhs: Self) -> Self {
345        if let Some(val) = self.checked_add(rhs) {
346            val
347        } else {
348            Self::MAX
349        }
350    }
351
352    /// Subtract two durations, returning the minimum value if the result would
353    /// be negative.
354    #[inline]
355    pub const fn saturating_sub(self, rhs: Self) -> Self {
356        if let Some(val) = self.checked_sub(rhs) {
357            val
358        } else {
359            Self::ZERO
360        }
361    }
362}
363
364impl core::ops::Add for Duration {
365    type Output = Self;
366
367    #[inline]
368    fn add(self, rhs: Self) -> Self::Output {
369        Duration(self.0 + rhs.0)
370    }
371}
372
373impl core::ops::AddAssign for Duration {
374    #[inline]
375    fn add_assign(&mut self, rhs: Self) {
376        self.0 += rhs.0;
377    }
378}
379
380impl core::ops::Sub for Duration {
381    type Output = Self;
382
383    #[inline]
384    fn sub(self, rhs: Self) -> Self::Output {
385        Duration(self.0 - rhs.0)
386    }
387}
388
389impl core::ops::SubAssign for Duration {
390    #[inline]
391    fn sub_assign(&mut self, rhs: Self) {
392        self.0 -= rhs.0;
393    }
394}
395
396impl core::ops::Mul<u32> for Duration {
397    type Output = Self;
398
399    #[inline]
400    fn mul(self, rhs: u32) -> Self::Output {
401        Duration(self.0 * rhs)
402    }
403}
404
405impl core::ops::Div<u32> for Duration {
406    type Output = Self;
407
408    #[inline]
409    fn div(self, rhs: u32) -> Self::Output {
410        Duration(self.0 / rhs)
411    }
412}
413
414impl core::ops::Div<Duration> for Duration {
415    type Output = u64;
416
417    #[inline]
418    fn div(self, rhs: Duration) -> Self::Output {
419        self.0 / rhs.0
420    }
421}
422
423#[inline]
424fn now() -> Instant {
425    #[cfg(esp32)]
426    let (ticks, div) = {
427        // on ESP32 use LACT
428        let tg0 = TIMG0::regs();
429        tg0.lactupdate().write(|w| unsafe { w.update().bits(1) });
430
431        // The peripheral doesn't have a bit to indicate that the update is done, so we
432        // poll the lower 32 bit part of the counter until it changes, or a timeout
433        // expires.
434        let lo_initial = tg0.lactlo().read().bits();
435        let mut div = tg0.lactconfig().read().divider().bits();
436        let lo = loop {
437            let lo = tg0.lactlo().read().bits();
438            if lo != lo_initial || div == 0 {
439                break lo;
440            }
441            div -= 1;
442        };
443        let hi = tg0.lacthi().read().bits();
444
445        let ticks = ((hi as u64) << 32u64) | lo as u64;
446        (ticks, 16)
447    };
448
449    #[cfg(not(esp32))]
450    let (ticks, div) = {
451        use crate::timer::systimer::{SystemTimer, Unit};
452        // otherwise use SYSTIMER
453        let ticks = SystemTimer::unit_value(Unit::Unit0);
454        (ticks, (SystemTimer::ticks_per_second() / 1_000_000))
455    };
456
457    Instant::from_ticks(ticks / div)
458}
459
460#[cfg(esp32)]
461pub(crate) fn time_init() {
462    let apb = crate::Clocks::get().apb_clock.as_hz();
463    // we assume 80MHz APB clock source - there is no way to configure it in a
464    // different way currently
465    assert_eq!(apb, 80_000_000u32);
466
467    let tg0 = TIMG0::regs();
468
469    tg0.lactconfig().write(|w| unsafe { w.bits(0) });
470    tg0.lactalarmhi().write(|w| unsafe { w.bits(u32::MAX) });
471    tg0.lactalarmlo().write(|w| unsafe { w.bits(u32::MAX) });
472    tg0.lactload().write(|w| unsafe { w.load().bits(1) });
473
474    // 16 MHz counter
475    tg0.lactconfig()
476        .modify(|_, w| unsafe { w.divider().bits((apb / 16_000_000u32) as u16) });
477    tg0.lactconfig().modify(|_, w| {
478        w.increase().bit(true);
479        w.autoreload().bit(true);
480        w.en().bit(true)
481    });
482}