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    #[procmacros::doc_replace]
51    /// Shorthand for creating a rate which represents hertz.
52    ///
53    /// ## Example
54    ///
55    /// ```rust, no_run
56    /// # {before_snippet}
57    /// use esp_hal::time::Rate;
58    /// let rate = Rate::from_hz(1000);
59    /// # {after_snippet}
60    /// ```
61    #[inline]
62    pub const fn from_hz(val: u32) -> Self {
63        Self(InnerRate::Hz(val))
64    }
65
66    #[procmacros::doc_replace]
67    /// Shorthand for creating a rate which represents kilohertz.
68    ///
69    /// ## Example
70    ///
71    /// ```rust, no_run
72    /// # {before_snippet}
73    /// use esp_hal::time::Rate;
74    /// let rate = Rate::from_khz(1000);
75    /// # {after_snippet}
76    /// ```
77    #[inline]
78    pub const fn from_khz(val: u32) -> Self {
79        Self(InnerRate::kHz(val))
80    }
81
82    #[procmacros::doc_replace]
83    /// Shorthand for creating a rate which represents megahertz.
84    ///
85    /// ## Example
86    ///
87    /// ```rust, no_run
88    /// # {before_snippet}
89    /// use esp_hal::time::Rate;
90    /// let rate = Rate::from_mhz(1000);
91    /// # {after_snippet}
92    /// ```
93    #[inline]
94    pub const fn from_mhz(val: u32) -> Self {
95        Self(InnerRate::MHz(val))
96    }
97
98    #[procmacros::doc_replace]
99    /// Convert the `Rate` to an interger number of Hz.
100    ///
101    /// ## Example
102    ///
103    /// ```rust, no_run
104    /// # {before_snippet}
105    /// use esp_hal::time::Rate;
106    /// let rate = Rate::from_hz(1000);
107    /// let hz = rate.as_hz();
108    /// # {after_snippet}
109    /// ```
110    #[inline]
111    pub const fn as_hz(&self) -> u32 {
112        self.0.to_Hz()
113    }
114
115    #[procmacros::doc_replace]
116    /// Convert the `Rate` to an interger number of kHz.
117    ///
118    /// ## Example
119    ///
120    /// ```rust, no_run
121    /// # {before_snippet}
122    /// use esp_hal::time::Rate;
123    /// let rate = Rate::from_khz(1000);
124    /// let khz = rate.as_khz();
125    /// # {after_snippet}
126    /// ```
127    #[inline]
128    pub const fn as_khz(&self) -> u32 {
129        self.0.to_kHz()
130    }
131
132    #[procmacros::doc_replace]
133    /// Convert the `Rate` to an interger number of MHz.
134    ///
135    /// ## Example
136    ///
137    /// ```rust, no_run
138    /// # {before_snippet}
139    /// use esp_hal::time::Rate;
140    /// let rate = Rate::from_mhz(1000);
141    /// let mhz = rate.as_mhz();
142    /// # {after_snippet}
143    /// ```
144    #[inline]
145    pub const fn as_mhz(&self) -> u32 {
146        self.0.to_MHz()
147    }
148
149    #[procmacros::doc_replace]
150    /// Convert the `Rate` to a `Duration`.
151    ///
152    /// ## Example
153    ///
154    /// ```rust, no_run
155    /// # {before_snippet}
156    /// use esp_hal::time::Rate;
157    /// let rate = Rate::from_hz(1000);
158    /// let duration = rate.as_duration();
159    /// # {after_snippet}
160    /// ```
161    #[inline]
162    pub const fn as_duration(&self) -> Duration {
163        Duration::from_micros(1_000_000 / self.as_hz() as u64)
164    }
165}
166
167impl core::ops::Div for Rate {
168    type Output = u32;
169
170    #[inline]
171    fn div(self, rhs: Self) -> Self::Output {
172        self.0 / rhs.0
173    }
174}
175
176impl core::ops::Mul<u32> for Rate {
177    type Output = Rate;
178
179    #[inline]
180    fn mul(self, rhs: u32) -> Self::Output {
181        Rate(self.0 * rhs)
182    }
183}
184
185impl core::ops::Div<u32> for Rate {
186    type Output = Rate;
187
188    #[inline]
189    fn div(self, rhs: u32) -> Self::Output {
190        Rate(self.0 / rhs)
191    }
192}
193
194/// Represents an instant in time.
195#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
196pub struct Instant(InnerInstant);
197
198impl Debug for Instant {
199    #[inline]
200    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
201        write!(
202            f,
203            "Instant({} µs since epoch)",
204            self.duration_since_epoch().as_micros()
205        )
206    }
207}
208
209impl Display for Instant {
210    #[inline]
211    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
212        write!(
213            f,
214            "{} µs since epoch",
215            self.duration_since_epoch().as_micros()
216        )
217    }
218}
219
220#[cfg(feature = "defmt")]
221impl defmt::Format for Instant {
222    #[inline]
223    fn format(&self, f: defmt::Formatter<'_>) {
224        defmt::write!(
225            f,
226            "{=u64} µs since epoch",
227            self.duration_since_epoch().as_micros()
228        )
229    }
230}
231
232impl core::hash::Hash for Instant {
233    #[inline]
234    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
235        self.duration_since_epoch().hash(state);
236    }
237}
238
239impl Instant {
240    /// Represents the moment the system booted.
241    pub const EPOCH: Instant = Instant(InnerInstant::from_ticks(0));
242
243    #[procmacros::doc_replace(
244        "wrap_after" => {
245            cfg(esp32) => "36_558 years",
246            cfg(esp32s2) => "7_311 years",
247            _ => "more than 7 years"
248        }
249    )]
250    /// Returns the current instant.
251    ///
252    /// The counter won’t measure time in sleep-mode.
253    ///
254    /// The timer has a 1 microsecond resolution and will wrap after
255    /// # {wrap_after}
256    ///
257    /// ## Example
258    ///
259    /// ```rust, no_run
260    /// # {before_snippet}
261    /// use esp_hal::time::Instant;
262    /// let now = Instant::now();
263    /// # {after_snippet}
264    /// ```
265    #[inline]
266    pub fn now() -> Self {
267        now()
268    }
269
270    #[inline]
271    pub(crate) fn from_ticks(ticks: u64) -> Self {
272        Instant(InnerInstant::from_ticks(ticks))
273    }
274
275    #[procmacros::doc_replace]
276    /// Returns the elapsed `Duration` since boot.
277    ///
278    /// ## Example
279    ///
280    /// ```rust, no_run
281    /// # {before_snippet}
282    /// use esp_hal::time::Instant;
283    /// let now = Instant::now();
284    /// let duration = now.duration_since_epoch();
285    /// # {after_snippet}
286    /// ```
287    #[inline]
288    pub fn duration_since_epoch(&self) -> Duration {
289        *self - Self::EPOCH
290    }
291
292    #[procmacros::doc_replace]
293    /// Returns the elapsed `Duration` since this `Instant` was created.
294    ///
295    /// ## Example
296    ///
297    /// ```rust, no_run
298    /// # {before_snippet}
299    /// use esp_hal::time::Instant;
300    /// let now = Instant::now();
301    /// let duration = now.elapsed();
302    /// # {after_snippet}
303    /// ```
304    #[inline]
305    pub fn elapsed(&self) -> Duration {
306        Self::now() - *self
307    }
308}
309
310impl core::ops::Add<Duration> for Instant {
311    type Output = Self;
312
313    #[inline]
314    fn add(self, rhs: Duration) -> Self::Output {
315        Instant(self.0 + rhs.0)
316    }
317}
318
319impl core::ops::AddAssign<Duration> for Instant {
320    #[inline]
321    fn add_assign(&mut self, rhs: Duration) {
322        self.0 += rhs.0;
323    }
324}
325
326impl core::ops::Sub for Instant {
327    type Output = Duration;
328
329    #[inline]
330    fn sub(self, rhs: Self) -> Self::Output {
331        Duration(self.0 - rhs.0)
332    }
333}
334
335impl core::ops::Sub<Duration> for Instant {
336    type Output = Self;
337
338    #[inline]
339    fn sub(self, rhs: Duration) -> Self::Output {
340        Instant(self.0 - rhs.0)
341    }
342}
343
344impl core::ops::SubAssign<Duration> for Instant {
345    #[inline]
346    fn sub_assign(&mut self, rhs: Duration) {
347        self.0 -= rhs.0;
348    }
349}
350
351/// Represents a duration of time.
352#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
353pub struct Duration(InnerDuration);
354
355impl Debug for Duration {
356    #[inline]
357    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
358        write!(f, "Duration({} µs)", self.as_micros())
359    }
360}
361
362impl Display for Duration {
363    #[inline]
364    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
365        write!(f, "{} µs", self.as_micros())
366    }
367}
368
369#[cfg(feature = "defmt")]
370impl defmt::Format for Duration {
371    #[inline]
372    fn format(&self, f: defmt::Formatter<'_>) {
373        defmt::write!(f, "{=u64} µs", self.as_micros())
374    }
375}
376
377impl core::hash::Hash for Duration {
378    #[inline]
379    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
380        self.as_micros().hash(state);
381    }
382}
383
384impl Duration {
385    /// A duration of zero time.
386    pub const ZERO: Self = Self(InnerDuration::from_ticks(0));
387
388    /// A duration representing the maximum possible time.
389    pub const MAX: Self = Self(InnerDuration::from_ticks(u64::MAX));
390
391    #[procmacros::doc_replace]
392    /// Creates a duration which represents microseconds.
393    ///
394    /// ## Example
395    ///
396    /// ```rust, no_run
397    /// # {before_snippet}
398    /// use esp_hal::time::Duration;
399    /// let duration = Duration::from_micros(1000);
400    /// # {after_snippet}
401    /// ```
402    #[inline]
403    pub const fn from_micros(val: u64) -> Self {
404        Self(InnerDuration::micros(val))
405    }
406
407    #[procmacros::doc_replace]
408    /// Creates a duration which represents milliseconds.
409    ///
410    /// ## Example
411    ///
412    /// ```rust, no_run
413    /// # {before_snippet}
414    /// use esp_hal::time::Duration;
415    /// let duration = Duration::from_millis(100);
416    /// # {after_snippet}
417    /// ```
418    #[inline]
419    pub const fn from_millis(val: u64) -> Self {
420        Self(InnerDuration::millis(val))
421    }
422
423    #[procmacros::doc_replace]
424    /// Creates a duration which represents seconds.
425    ///
426    /// ## Example
427    ///
428    /// ```rust, no_run
429    /// # {before_snippet}
430    /// use esp_hal::time::Duration;
431    /// let duration = Duration::from_secs(1);
432    /// # {after_snippet}
433    /// ```
434    #[inline]
435    pub const fn from_secs(val: u64) -> Self {
436        Self(InnerDuration::secs(val))
437    }
438
439    #[procmacros::doc_replace]
440    /// Creates a duration which represents minutes.
441    ///
442    /// ## Example
443    ///
444    /// ```rust, no_run
445    /// # {before_snippet}
446    /// use esp_hal::time::Duration;
447    /// let duration = Duration::from_minutes(1);
448    /// # {after_snippet}
449    /// ```
450    #[inline]
451    pub const fn from_minutes(val: u64) -> Self {
452        Self(InnerDuration::minutes(val))
453    }
454
455    #[procmacros::doc_replace]
456    /// Creates a duration which represents hours.
457    ///
458    /// ## Example
459    ///
460    /// ```rust, no_run
461    /// # {before_snippet}
462    /// use esp_hal::time::Duration;
463    /// let duration = Duration::from_hours(1);
464    /// # {after_snippet}
465    /// ```
466    #[inline]
467    pub const fn from_hours(val: u64) -> Self {
468        Self(InnerDuration::hours(val))
469    }
470
471    delegate::delegate! {
472        #[inline]
473        to self.0 {
474            #[procmacros::doc_replace]
475            /// Convert the `Duration` to an interger number of microseconds.
476            ///
477            /// ## Example
478            ///
479            /// ```rust, no_run
480            /// # {before_snippet}
481            /// use esp_hal::time::Duration;
482            /// let duration = Duration::from_micros(1000);
483            /// let micros = duration.as_micros();
484            /// # {after_snippet}
485            /// ```
486            #[call(to_micros)]
487            pub const fn as_micros(&self) -> u64;
488
489            #[procmacros::doc_replace]
490            /// Convert the `Duration` to an interger number of milliseconds.
491            ///
492            /// ## Example
493            ///
494            /// ```rust, no_run
495            /// # {before_snippet}
496            /// use esp_hal::time::Duration;
497            /// let duration = Duration::from_millis(100);
498            /// let millis = duration.as_millis();
499            /// # {after_snippet}
500            /// ```
501            #[call(to_millis)]
502            pub const fn as_millis(&self) -> u64;
503
504            #[procmacros::doc_replace]
505            /// Convert the `Duration` to an interger number of seconds.
506            ///
507            /// ## Example
508            ///
509            /// ```rust, no_run
510            /// # {before_snippet}
511            /// use esp_hal::time::Duration;
512            /// let duration = Duration::from_secs(1);
513            /// let secs = duration.as_secs();
514            /// # {after_snippet}
515            /// ```
516            #[call(to_secs)]
517            pub const fn as_secs(&self) -> u64;
518
519            #[procmacros::doc_replace]
520            /// Convert the `Duration` to an interger number of minutes.
521            ///
522            /// ## Example
523            ///
524            /// ```rust, no_run
525            /// # {before_snippet}
526            /// use esp_hal::time::Duration;
527            /// let duration = Duration::from_minutes(1);
528            /// let minutes = duration.as_minutes();
529            /// # {after_snippet}
530            /// ```
531            #[call(to_minutes)]
532            pub const fn as_minutes(&self) -> u64;
533
534            #[procmacros::doc_replace]
535            /// Convert the `Duration` to an interger number of hours.
536            ///
537            /// ## Example
538            ///
539            /// ```rust, no_run
540            /// # {before_snippet}
541            /// use esp_hal::time::Duration;
542            /// let duration = Duration::from_hours(1);
543            /// let hours = duration.as_hours();
544            /// # {after_snippet}
545            /// ```
546            #[call(to_hours)]
547            pub const fn as_hours(&self) -> u64;
548        }
549    }
550
551    #[procmacros::doc_replace]
552    /// Add two durations while checking for overflow.
553    ///
554    /// ## Example
555    ///
556    /// ```rust, no_run
557    /// # {before_snippet}
558    /// use esp_hal::time::Duration;
559    /// let duration = Duration::from_secs(1);
560    /// let duration2 = Duration::from_secs(2);
561    ///
562    /// if let Some(sum) = duration.checked_add(duration2) {
563    ///     println!("Sum: {}", sum);
564    /// } else {
565    ///     println!("Overflow occurred");
566    /// }
567    /// # {after_snippet}
568    /// ```
569    #[inline]
570    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
571        if let Some(val) = self.0.checked_add(rhs.0) {
572            Some(Duration(val))
573        } else {
574            None
575        }
576    }
577
578    #[procmacros::doc_replace]
579    /// Subtract two durations while checking for overflow.
580    ///
581    /// ## Example
582    ///
583    /// ```rust, no_run
584    /// # {before_snippet}
585    /// use esp_hal::time::Duration;
586    /// let duration = Duration::from_secs(3);
587    /// let duration2 = Duration::from_secs(1);
588    ///
589    /// if let Some(diff) = duration.checked_sub(duration2) {
590    ///     println!("Difference: {}", diff);
591    /// } else {
592    ///     println!("Underflow occurred");
593    /// }
594    /// # {after_snippet}
595    /// ```
596    #[inline]
597    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
598        if let Some(val) = self.0.checked_sub(rhs.0) {
599            Some(Duration(val))
600        } else {
601            None
602        }
603    }
604
605    #[procmacros::doc_replace]
606    /// Add two durations, returning the maximum value if overflow occurred.
607    ///
608    /// ## Example
609    ///
610    /// ```rust, no_run
611    /// # {before_snippet}
612    /// use esp_hal::time::Duration;
613    /// let duration = Duration::from_secs(1);
614    /// let duration2 = Duration::from_secs(2);
615    ///
616    /// let sum = duration.saturating_add(duration2);
617    /// # {after_snippet}
618    /// ```
619    #[inline]
620    pub const fn saturating_add(self, rhs: Self) -> Self {
621        if let Some(val) = self.checked_add(rhs) {
622            val
623        } else {
624            Self::MAX
625        }
626    }
627
628    #[procmacros::doc_replace]
629    /// Subtract two durations, returning the minimum value if the result would
630    /// be negative.
631    ///
632    /// ## Example
633    ///
634    /// ```rust, no_run
635    /// # {before_snippet}
636    /// use esp_hal::time::Duration;
637    /// let duration = Duration::from_secs(3);
638    /// let duration2 = Duration::from_secs(1);
639    ///
640    /// let diff = duration.saturating_sub(duration2);
641    /// # {after_snippet}
642    /// ```
643    #[inline]
644    pub const fn saturating_sub(self, rhs: Self) -> Self {
645        if let Some(val) = self.checked_sub(rhs) {
646            val
647        } else {
648            Self::ZERO
649        }
650    }
651}
652
653impl core::ops::Add for Duration {
654    type Output = Self;
655
656    #[inline]
657    fn add(self, rhs: Self) -> Self::Output {
658        Duration(self.0 + rhs.0)
659    }
660}
661
662impl core::ops::AddAssign for Duration {
663    #[inline]
664    fn add_assign(&mut self, rhs: Self) {
665        self.0 += rhs.0;
666    }
667}
668
669impl core::ops::Sub for Duration {
670    type Output = Self;
671
672    #[inline]
673    fn sub(self, rhs: Self) -> Self::Output {
674        Duration(self.0 - rhs.0)
675    }
676}
677
678impl core::ops::SubAssign for Duration {
679    #[inline]
680    fn sub_assign(&mut self, rhs: Self) {
681        self.0 -= rhs.0;
682    }
683}
684
685impl core::ops::Mul<u32> for Duration {
686    type Output = Self;
687
688    #[inline]
689    fn mul(self, rhs: u32) -> Self::Output {
690        Duration(self.0 * rhs)
691    }
692}
693
694impl core::ops::Div<u32> for Duration {
695    type Output = Self;
696
697    #[inline]
698    fn div(self, rhs: u32) -> Self::Output {
699        Duration(self.0 / rhs)
700    }
701}
702
703impl core::ops::Div<Duration> for Duration {
704    type Output = u64;
705
706    #[inline]
707    fn div(self, rhs: Duration) -> Self::Output {
708        self.0 / rhs.0
709    }
710}
711
712#[inline]
713fn now() -> Instant {
714    #[cfg(esp32)]
715    let (ticks, div) = {
716        // on ESP32 use LACT
717        let tg0 = TIMG0::regs();
718        tg0.lactupdate().write(|w| unsafe { w.update().bits(1) });
719
720        // The peripheral doesn't have a bit to indicate that the update is done, so we
721        // poll the lower 32 bit part of the counter until it changes, or a timeout
722        // expires.
723        let lo_initial = tg0.lactlo().read().bits();
724        let mut div = tg0.lactconfig().read().divider().bits();
725        let lo = loop {
726            let lo = tg0.lactlo().read().bits();
727            if lo != lo_initial || div == 0 {
728                break lo;
729            }
730            div -= 1;
731        };
732        let hi = tg0.lacthi().read().bits();
733
734        let ticks = ((hi as u64) << 32u64) | lo as u64;
735        (ticks, 16)
736    };
737
738    #[cfg(not(esp32))]
739    let (ticks, div) = {
740        use crate::timer::systimer::{SystemTimer, Unit};
741        // otherwise use SYSTIMER
742        let ticks = SystemTimer::unit_value(Unit::Unit0);
743        (ticks, (SystemTimer::ticks_per_second() / 1_000_000))
744    };
745
746    Instant::from_ticks(ticks / div)
747}
748
749#[cfg(all(esp32, feature = "rt"))]
750pub(crate) fn time_init() {
751    let apb = crate::Clocks::get().apb_clock.as_hz();
752    // we assume 80MHz APB clock source - there is no way to configure it in a
753    // different way currently
754    assert_eq!(apb, 80_000_000u32);
755
756    let tg0 = TIMG0::regs();
757
758    tg0.lactconfig().write(|w| unsafe { w.bits(0) });
759    tg0.lactalarmhi().write(|w| unsafe { w.bits(u32::MAX) });
760    tg0.lactalarmlo().write(|w| unsafe { w.bits(u32::MAX) });
761    tg0.lactload().write(|w| unsafe { w.load().bits(1) });
762
763    // 16 MHz counter
764    tg0.lactconfig()
765        .modify(|_, w| unsafe { w.divider().bits((apb / 16_000_000u32) as u16) });
766    tg0.lactconfig().modify(|_, w| {
767        w.increase().bit(true);
768        w.autoreload().bit(true);
769        w.en().bit(true)
770    });
771}