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 core::hash::Hash for Instant {
159    #[inline]
160    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
161        self.duration_since_epoch().hash(state);
162    }
163}
164
165impl Instant {
166    /// Represents the moment the system booted.
167    pub const EPOCH: Instant = Instant(InnerInstant::from_ticks(0));
168
169    /// Returns the current instant.
170    ///
171    /// The counter won’t measure time in sleep-mode.
172    ///
173    /// The timer has a 1 microsecond resolution and will wrap after
174    #[cfg_attr(esp32, doc = "36_558 years")]
175    #[cfg_attr(esp32s2, doc = "7_311 years")]
176    #[cfg_attr(not(any(esp32, esp32s2)), doc = "more than 7 years")]
177    #[inline]
178    pub fn now() -> Self {
179        now()
180    }
181
182    #[inline]
183    pub(crate) fn from_ticks(ticks: u64) -> Self {
184        Instant(InnerInstant::from_ticks(ticks))
185    }
186
187    /// Returns the elapsed `Duration` since boot.
188    #[inline]
189    pub fn duration_since_epoch(&self) -> Duration {
190        *self - Self::EPOCH
191    }
192
193    /// Returns the elapsed `Duration` since this `Instant` was created.
194    #[inline]
195    pub fn elapsed(&self) -> Duration {
196        Self::now() - *self
197    }
198}
199
200impl core::ops::Add<Duration> for Instant {
201    type Output = Self;
202
203    #[inline]
204    fn add(self, rhs: Duration) -> Self::Output {
205        Instant(self.0 + rhs.0)
206    }
207}
208
209impl core::ops::AddAssign<Duration> for Instant {
210    #[inline]
211    fn add_assign(&mut self, rhs: Duration) {
212        self.0 += rhs.0;
213    }
214}
215
216impl core::ops::Sub for Instant {
217    type Output = Duration;
218
219    #[inline]
220    fn sub(self, rhs: Self) -> Self::Output {
221        Duration(self.0 - rhs.0)
222    }
223}
224
225impl core::ops::Sub<Duration> for Instant {
226    type Output = Self;
227
228    #[inline]
229    fn sub(self, rhs: Duration) -> Self::Output {
230        Instant(self.0 - rhs.0)
231    }
232}
233
234impl core::ops::SubAssign<Duration> for Instant {
235    #[inline]
236    fn sub_assign(&mut self, rhs: Duration) {
237        self.0 -= rhs.0;
238    }
239}
240
241/// Represents a duration of time.
242#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
243pub struct Duration(InnerDuration);
244
245impl Debug for Duration {
246    #[inline]
247    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
248        write!(f, "Duration({} µs)", self.as_micros())
249    }
250}
251
252impl Display for Duration {
253    #[inline]
254    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
255        write!(f, "{} µs", self.as_micros())
256    }
257}
258
259#[cfg(feature = "defmt")]
260impl defmt::Format for Duration {
261    #[inline]
262    fn format(&self, f: defmt::Formatter<'_>) {
263        defmt::write!(f, "{=u64} µs", self.as_micros())
264    }
265}
266
267impl core::hash::Hash for Duration {
268    #[inline]
269    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
270        self.as_micros().hash(state);
271    }
272}
273
274impl Duration {
275    /// A duration of zero time.
276    pub const ZERO: Self = Self(InnerDuration::from_ticks(0));
277
278    /// A duration representing the maximum possible time.
279    pub const MAX: Self = Self(InnerDuration::from_ticks(u64::MAX));
280
281    /// Creates a duration which represents microseconds.
282    #[inline]
283    pub const fn from_micros(val: u64) -> Self {
284        Self(InnerDuration::micros(val))
285    }
286
287    /// Creates a duration which represents milliseconds.
288    #[inline]
289    pub const fn from_millis(val: u64) -> Self {
290        Self(InnerDuration::millis(val))
291    }
292
293    /// Creates a duration which represents seconds.
294    #[inline]
295    pub const fn from_secs(val: u64) -> Self {
296        Self(InnerDuration::secs(val))
297    }
298
299    /// Creates a duration which represents minutes.
300    #[inline]
301    pub const fn from_minutes(val: u64) -> Self {
302        Self(InnerDuration::minutes(val))
303    }
304
305    /// Creates a duration which represents hours.
306    #[inline]
307    pub const fn from_hours(val: u64) -> Self {
308        Self(InnerDuration::hours(val))
309    }
310
311    delegate::delegate! {
312        #[inline]
313        to self.0 {
314            /// Convert the `Duration` to an interger number of microseconds.
315            #[call(to_micros)]
316            pub const fn as_micros(&self) -> u64;
317
318            /// Convert the `Duration` to an interger number of milliseconds.
319            #[call(to_millis)]
320            pub const fn as_millis(&self) -> u64;
321
322            /// Convert the `Duration` to an interger number of seconds.
323            #[call(to_secs)]
324            pub const fn as_secs(&self) -> u64;
325
326            /// Convert the `Duration` to an interger number of minutes.
327            #[call(to_minutes)]
328            pub const fn as_minutes(&self) -> u64;
329
330            /// Convert the `Duration` to an interger number of hours.
331            #[call(to_hours)]
332            pub const fn as_hours(&self) -> u64;
333        }
334    }
335
336    /// Add two durations while checking for overflow.
337    #[inline]
338    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
339        if let Some(val) = self.0.checked_add(rhs.0) {
340            Some(Duration(val))
341        } else {
342            None
343        }
344    }
345
346    /// Subtract two durations while checking for overflow.
347    #[inline]
348    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
349        if let Some(val) = self.0.checked_sub(rhs.0) {
350            Some(Duration(val))
351        } else {
352            None
353        }
354    }
355
356    /// Add two durations, returning the maximum value if overflow occurred.
357    #[inline]
358    pub const fn saturating_add(self, rhs: Self) -> Self {
359        if let Some(val) = self.checked_add(rhs) {
360            val
361        } else {
362            Self::MAX
363        }
364    }
365
366    /// Subtract two durations, returning the minimum value if the result would
367    /// be negative.
368    #[inline]
369    pub const fn saturating_sub(self, rhs: Self) -> Self {
370        if let Some(val) = self.checked_sub(rhs) {
371            val
372        } else {
373            Self::ZERO
374        }
375    }
376}
377
378impl core::ops::Add for Duration {
379    type Output = Self;
380
381    #[inline]
382    fn add(self, rhs: Self) -> Self::Output {
383        Duration(self.0 + rhs.0)
384    }
385}
386
387impl core::ops::AddAssign for Duration {
388    #[inline]
389    fn add_assign(&mut self, rhs: Self) {
390        self.0 += rhs.0;
391    }
392}
393
394impl core::ops::Sub for Duration {
395    type Output = Self;
396
397    #[inline]
398    fn sub(self, rhs: Self) -> Self::Output {
399        Duration(self.0 - rhs.0)
400    }
401}
402
403impl core::ops::SubAssign for Duration {
404    #[inline]
405    fn sub_assign(&mut self, rhs: Self) {
406        self.0 -= rhs.0;
407    }
408}
409
410impl core::ops::Mul<u32> for Duration {
411    type Output = Self;
412
413    #[inline]
414    fn mul(self, rhs: u32) -> Self::Output {
415        Duration(self.0 * rhs)
416    }
417}
418
419impl core::ops::Div<u32> for Duration {
420    type Output = Self;
421
422    #[inline]
423    fn div(self, rhs: u32) -> Self::Output {
424        Duration(self.0 / rhs)
425    }
426}
427
428impl core::ops::Div<Duration> for Duration {
429    type Output = u64;
430
431    #[inline]
432    fn div(self, rhs: Duration) -> Self::Output {
433        self.0 / rhs.0
434    }
435}
436
437#[inline]
438fn now() -> Instant {
439    #[cfg(esp32)]
440    let (ticks, div) = {
441        // on ESP32 use LACT
442        let tg0 = TIMG0::regs();
443        tg0.lactupdate().write(|w| unsafe { w.update().bits(1) });
444
445        // The peripheral doesn't have a bit to indicate that the update is done, so we
446        // poll the lower 32 bit part of the counter until it changes, or a timeout
447        // expires.
448        let lo_initial = tg0.lactlo().read().bits();
449        let mut div = tg0.lactconfig().read().divider().bits();
450        let lo = loop {
451            let lo = tg0.lactlo().read().bits();
452            if lo != lo_initial || div == 0 {
453                break lo;
454            }
455            div -= 1;
456        };
457        let hi = tg0.lacthi().read().bits();
458
459        let ticks = ((hi as u64) << 32u64) | lo as u64;
460        (ticks, 16)
461    };
462
463    #[cfg(not(esp32))]
464    let (ticks, div) = {
465        use crate::timer::systimer::{SystemTimer, Unit};
466        // otherwise use SYSTIMER
467        let ticks = SystemTimer::unit_value(Unit::Unit0);
468        (ticks, (SystemTimer::ticks_per_second() / 1_000_000))
469    };
470
471    Instant::from_ticks(ticks / div)
472}
473
474#[cfg(esp32)]
475pub(crate) fn time_init() {
476    let apb = crate::Clocks::get().apb_clock.as_hz();
477    // we assume 80MHz APB clock source - there is no way to configure it in a
478    // different way currently
479    assert_eq!(apb, 80_000_000u32);
480
481    let tg0 = TIMG0::regs();
482
483    tg0.lactconfig().write(|w| unsafe { w.bits(0) });
484    tg0.lactalarmhi().write(|w| unsafe { w.bits(u32::MAX) });
485    tg0.lactalarmlo().write(|w| unsafe { w.bits(u32::MAX) });
486    tg0.lactload().write(|w| unsafe { w.load().bits(1) });
487
488    // 16 MHz counter
489    tg0.lactconfig()
490        .modify(|_, w| unsafe { w.divider().bits((apb / 16_000_000u32) as u16) });
491    tg0.lactconfig().modify(|_, w| {
492        w.increase().bit(true);
493        w.autoreload().bit(true);
494        w.en().bit(true)
495    });
496}