Skip to main content

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
9type InnerRate = fugit::Rate<u32, 1, 1>;
10type InnerInstant = fugit::Instant<u64, 1, 1_000_000, fugit::kind::Monotonic>;
11type InnerDuration = fugit::Duration<u64, 1, 1_000_000>;
12
13/// Represents a rate or frequency of events.
14#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
15pub struct Rate(InnerRate);
16
17impl core::hash::Hash for Rate {
18    #[inline]
19    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
20        self.as_hz().hash(state);
21    }
22}
23
24impl Display for Rate {
25    #[inline]
26    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
27        write!(f, "{} Hz", self.as_hz())
28    }
29}
30
31impl Debug for Rate {
32    #[inline]
33    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
34        write!(f, "Rate({} Hz)", self.as_hz())
35    }
36}
37
38#[cfg(feature = "defmt")]
39impl defmt::Format for Rate {
40    #[inline]
41    fn format(&self, f: defmt::Formatter<'_>) {
42        defmt::write!(f, "{=u32} Hz", self.as_hz())
43    }
44}
45
46impl Rate {
47    #[procmacros::doc_replace]
48    /// Shorthand for creating a rate which represents hertz.
49    ///
50    /// ## Example
51    ///
52    /// ```rust, no_run
53    /// # {before_snippet}
54    /// use esp_hal::time::Rate;
55    /// let rate = Rate::from_hz(1000);
56    /// # {after_snippet}
57    /// ```
58    #[inline]
59    pub const fn from_hz(val: u32) -> Self {
60        Self(InnerRate::Hz(val))
61    }
62
63    #[procmacros::doc_replace]
64    /// Shorthand for creating a rate which represents kilohertz.
65    ///
66    /// ## Example
67    ///
68    /// ```rust, no_run
69    /// # {before_snippet}
70    /// use esp_hal::time::Rate;
71    /// let rate = Rate::from_khz(1000);
72    /// # {after_snippet}
73    /// ```
74    #[inline]
75    pub const fn from_khz(val: u32) -> Self {
76        Self(InnerRate::kHz(val))
77    }
78
79    #[procmacros::doc_replace]
80    /// Shorthand for creating a rate which represents megahertz.
81    ///
82    /// ## Example
83    ///
84    /// ```rust, no_run
85    /// # {before_snippet}
86    /// use esp_hal::time::Rate;
87    /// let rate = Rate::from_mhz(1000);
88    /// # {after_snippet}
89    /// ```
90    #[inline]
91    pub const fn from_mhz(val: u32) -> Self {
92        Self(InnerRate::MHz(val))
93    }
94
95    #[procmacros::doc_replace]
96    /// Convert the `Rate` to an integer number of Hz.
97    ///
98    /// ## Example
99    ///
100    /// ```rust, no_run
101    /// # {before_snippet}
102    /// use esp_hal::time::Rate;
103    /// let rate = Rate::from_hz(1000);
104    /// let hz = rate.as_hz();
105    /// # {after_snippet}
106    /// ```
107    #[inline]
108    pub const fn as_hz(&self) -> u32 {
109        self.0.to_Hz()
110    }
111
112    #[procmacros::doc_replace]
113    /// Convert the `Rate` to an integer number of kHz.
114    ///
115    /// ## Example
116    ///
117    /// ```rust, no_run
118    /// # {before_snippet}
119    /// use esp_hal::time::Rate;
120    /// let rate = Rate::from_khz(1000);
121    /// let khz = rate.as_khz();
122    /// # {after_snippet}
123    /// ```
124    #[inline]
125    pub const fn as_khz(&self) -> u32 {
126        self.0.to_kHz()
127    }
128
129    #[procmacros::doc_replace]
130    /// Convert the `Rate` to an integer number of MHz.
131    ///
132    /// ## Example
133    ///
134    /// ```rust, no_run
135    /// # {before_snippet}
136    /// use esp_hal::time::Rate;
137    /// let rate = Rate::from_mhz(1000);
138    /// let mhz = rate.as_mhz();
139    /// # {after_snippet}
140    /// ```
141    #[inline]
142    pub const fn as_mhz(&self) -> u32 {
143        self.0.to_MHz()
144    }
145
146    #[procmacros::doc_replace]
147    /// Convert the `Rate` to a `Duration`.
148    ///
149    /// ## Example
150    ///
151    /// ```rust, no_run
152    /// # {before_snippet}
153    /// use esp_hal::time::Rate;
154    /// let rate = Rate::from_hz(1000);
155    /// let duration = rate.as_duration();
156    /// # {after_snippet}
157    /// ```
158    #[inline]
159    pub const fn as_duration(&self) -> Duration {
160        Duration::from_micros(1_000_000 / self.as_hz() as u64)
161    }
162}
163
164impl core::ops::Div for Rate {
165    type Output = u32;
166
167    #[inline]
168    fn div(self, rhs: Self) -> Self::Output {
169        self.0 / rhs.0
170    }
171}
172
173impl core::ops::Mul<u32> for Rate {
174    type Output = Rate;
175
176    #[inline]
177    fn mul(self, rhs: u32) -> Self::Output {
178        Rate(self.0 * rhs)
179    }
180}
181
182impl core::ops::Div<u32> for Rate {
183    type Output = Rate;
184
185    #[inline]
186    fn div(self, rhs: u32) -> Self::Output {
187        Rate(self.0 / rhs)
188    }
189}
190
191/// Represents an instant in time.
192#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
193pub struct Instant(InnerInstant);
194
195impl Debug for Instant {
196    #[inline]
197    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
198        write!(
199            f,
200            "Instant({} µs since epoch)",
201            self.duration_since_epoch().as_micros()
202        )
203    }
204}
205
206impl Display for Instant {
207    #[inline]
208    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
209        write!(
210            f,
211            "{} µs since epoch",
212            self.duration_since_epoch().as_micros()
213        )
214    }
215}
216
217#[cfg(feature = "defmt")]
218impl defmt::Format for Instant {
219    #[inline]
220    fn format(&self, f: defmt::Formatter<'_>) {
221        defmt::write!(
222            f,
223            "{=u64} µs since epoch",
224            self.duration_since_epoch().as_micros()
225        )
226    }
227}
228
229impl core::hash::Hash for Instant {
230    #[inline]
231    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
232        self.duration_since_epoch().hash(state);
233    }
234}
235
236impl Instant {
237    /// Represents the moment the system booted.
238    pub const EPOCH: Instant = Instant(InnerInstant::from_ticks(0));
239
240    #[procmacros::doc_replace(
241        "wrap_after" => {
242            cfg(esp32) => "36_558 years",
243            cfg(esp32s2) => "7_311 years",
244            _ => "more than 7 years"
245        }
246    )]
247    /// Returns the current instant.
248    ///
249    /// The counter won’t measure time in sleep-mode.
250    ///
251    /// The timer has a 1 microsecond resolution and will wrap after __wrap_after__.
252    ///
253    /// <section class="warning">
254    /// Note that this function returns an unreliable value before <code>esp_hal::init()</code> is
255    /// called. </section>
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 Default for Duration {
385    #[inline]
386    fn default() -> Self {
387        Self::ZERO
388    }
389}
390
391impl Duration {
392    /// A duration of zero time.
393    pub const ZERO: Self = Self(InnerDuration::from_ticks(0));
394
395    /// A duration representing the maximum possible time.
396    pub const MAX: Self = Self(InnerDuration::from_ticks(u64::MAX));
397
398    #[procmacros::doc_replace]
399    /// Creates a duration which represents microseconds.
400    ///
401    /// ## Example
402    ///
403    /// ```rust, no_run
404    /// # {before_snippet}
405    /// use esp_hal::time::Duration;
406    /// let duration = Duration::from_micros(1000);
407    /// # {after_snippet}
408    /// ```
409    #[inline]
410    pub const fn from_micros(val: u64) -> Self {
411        Self(InnerDuration::from_micros(val))
412    }
413
414    #[procmacros::doc_replace]
415    /// Creates a duration which represents milliseconds.
416    ///
417    /// ## Example
418    ///
419    /// ```rust, no_run
420    /// # {before_snippet}
421    /// use esp_hal::time::Duration;
422    /// let duration = Duration::from_millis(100);
423    /// # {after_snippet}
424    /// ```
425    #[inline]
426    pub const fn from_millis(val: u64) -> Self {
427        Self(InnerDuration::from_millis(val))
428    }
429
430    #[procmacros::doc_replace]
431    /// Creates a duration which represents seconds.
432    ///
433    /// ## Example
434    ///
435    /// ```rust, no_run
436    /// # {before_snippet}
437    /// use esp_hal::time::Duration;
438    /// let duration = Duration::from_secs(1);
439    /// # {after_snippet}
440    /// ```
441    #[inline]
442    pub const fn from_secs(val: u64) -> Self {
443        Self(InnerDuration::from_secs(val))
444    }
445
446    #[procmacros::doc_replace]
447    /// Creates a duration which represents minutes.
448    ///
449    /// ## Example
450    ///
451    /// ```rust, no_run
452    /// # {before_snippet}
453    /// use esp_hal::time::Duration;
454    /// let duration = Duration::from_minutes(1);
455    /// # {after_snippet}
456    /// ```
457    #[inline]
458    pub const fn from_minutes(val: u64) -> Self {
459        Self(InnerDuration::from_minutes(val))
460    }
461
462    #[procmacros::doc_replace]
463    /// Creates a duration which represents hours.
464    ///
465    /// ## Example
466    ///
467    /// ```rust, no_run
468    /// # {before_snippet}
469    /// use esp_hal::time::Duration;
470    /// let duration = Duration::from_hours(1);
471    /// # {after_snippet}
472    /// ```
473    #[inline]
474    pub const fn from_hours(val: u64) -> Self {
475        Self(InnerDuration::from_hours(val))
476    }
477
478    delegate::delegate! {
479        #[inline]
480        to self.0 {
481            #[procmacros::doc_replace]
482            /// Convert the `Duration` to an integer number of microseconds.
483            ///
484            /// ## Example
485            ///
486            /// ```rust, no_run
487            /// # {before_snippet}
488            /// use esp_hal::time::Duration;
489            /// let duration = Duration::from_micros(1000);
490            /// let micros = duration.as_micros();
491            /// # {after_snippet}
492            /// ```
493            pub const fn as_micros(&self) -> u64;
494
495            #[procmacros::doc_replace]
496            /// Convert the `Duration` to an integer number of milliseconds.
497            ///
498            /// ## Example
499            ///
500            /// ```rust, no_run
501            /// # {before_snippet}
502            /// use esp_hal::time::Duration;
503            /// let duration = Duration::from_millis(100);
504            /// let millis = duration.as_millis();
505            /// # {after_snippet}
506            /// ```
507            pub const fn as_millis(&self) -> u64;
508
509            #[procmacros::doc_replace]
510            /// Convert the `Duration` to an integer number of seconds.
511            ///
512            /// ## Example
513            ///
514            /// ```rust, no_run
515            /// # {before_snippet}
516            /// use esp_hal::time::Duration;
517            /// let duration = Duration::from_secs(1);
518            /// let secs = duration.as_secs();
519            /// # {after_snippet}
520            /// ```
521            pub const fn as_secs(&self) -> u64;
522
523            #[procmacros::doc_replace]
524            /// Convert the `Duration` to an integer number of minutes.
525            ///
526            /// ## Example
527            ///
528            /// ```rust, no_run
529            /// # {before_snippet}
530            /// use esp_hal::time::Duration;
531            /// let duration = Duration::from_minutes(1);
532            /// let minutes = duration.as_minutes();
533            /// # {after_snippet}
534            /// ```
535            pub const fn as_minutes(&self) -> u64;
536
537            #[procmacros::doc_replace]
538            /// Convert the `Duration` to an integer number of hours.
539            ///
540            /// ## Example
541            ///
542            /// ```rust, no_run
543            /// # {before_snippet}
544            /// use esp_hal::time::Duration;
545            /// let duration = Duration::from_hours(1);
546            /// let hours = duration.as_hours();
547            /// # {after_snippet}
548            /// ```
549            pub const fn as_hours(&self) -> u64;
550        }
551    }
552
553    #[procmacros::doc_replace]
554    /// Add two durations while checking for overflow.
555    ///
556    /// ## Example
557    ///
558    /// ```rust, no_run
559    /// # {before_snippet}
560    /// use esp_hal::time::Duration;
561    /// let duration = Duration::from_secs(1);
562    /// let duration2 = Duration::from_secs(2);
563    ///
564    /// if let Some(sum) = duration.checked_add(duration2) {
565    ///     println!("Sum: {}", sum);
566    /// } else {
567    ///     println!("Overflow occurred");
568    /// }
569    /// # {after_snippet}
570    /// ```
571    #[inline]
572    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
573        if let Some(val) = self.0.checked_add(rhs.0) {
574            Some(Duration(val))
575        } else {
576            None
577        }
578    }
579
580    #[procmacros::doc_replace]
581    /// Subtract two durations while checking for overflow.
582    ///
583    /// ## Example
584    ///
585    /// ```rust, no_run
586    /// # {before_snippet}
587    /// use esp_hal::time::Duration;
588    /// let duration = Duration::from_secs(3);
589    /// let duration2 = Duration::from_secs(1);
590    ///
591    /// if let Some(diff) = duration.checked_sub(duration2) {
592    ///     println!("Difference: {}", diff);
593    /// } else {
594    ///     println!("Underflow occurred");
595    /// }
596    /// # {after_snippet}
597    /// ```
598    #[inline]
599    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
600        if let Some(val) = self.0.checked_sub(rhs.0) {
601            Some(Duration(val))
602        } else {
603            None
604        }
605    }
606
607    #[procmacros::doc_replace]
608    /// Add two durations, returning the maximum value if overflow occurred.
609    ///
610    /// ## Example
611    ///
612    /// ```rust, no_run
613    /// # {before_snippet}
614    /// use esp_hal::time::Duration;
615    /// let duration = Duration::from_secs(1);
616    /// let duration2 = Duration::from_secs(2);
617    ///
618    /// let sum = duration.saturating_add(duration2);
619    /// # {after_snippet}
620    /// ```
621    #[inline]
622    pub const fn saturating_add(self, rhs: Self) -> Self {
623        if let Some(val) = self.checked_add(rhs) {
624            val
625        } else {
626            Self::MAX
627        }
628    }
629
630    #[procmacros::doc_replace]
631    /// Subtract two durations, returning the minimum value if the result would
632    /// be negative.
633    ///
634    /// ## Example
635    ///
636    /// ```rust, no_run
637    /// # {before_snippet}
638    /// use esp_hal::time::Duration;
639    /// let duration = Duration::from_secs(3);
640    /// let duration2 = Duration::from_secs(1);
641    ///
642    /// let diff = duration.saturating_sub(duration2);
643    /// # {after_snippet}
644    /// ```
645    #[inline]
646    pub const fn saturating_sub(self, rhs: Self) -> Self {
647        if let Some(val) = self.checked_sub(rhs) {
648            val
649        } else {
650            Self::ZERO
651        }
652    }
653}
654
655impl core::ops::Add for Duration {
656    type Output = Self;
657
658    #[inline]
659    fn add(self, rhs: Self) -> Self::Output {
660        Duration(self.0 + rhs.0)
661    }
662}
663
664impl core::ops::AddAssign for Duration {
665    #[inline]
666    fn add_assign(&mut self, rhs: Self) {
667        self.0 += rhs.0;
668    }
669}
670
671impl core::ops::Sub for Duration {
672    type Output = Self;
673
674    #[inline]
675    fn sub(self, rhs: Self) -> Self::Output {
676        Duration(self.0 - rhs.0)
677    }
678}
679
680impl core::ops::SubAssign for Duration {
681    #[inline]
682    fn sub_assign(&mut self, rhs: Self) {
683        self.0 -= rhs.0;
684    }
685}
686
687impl core::ops::Mul<u32> for Duration {
688    type Output = Self;
689
690    #[inline]
691    fn mul(self, rhs: u32) -> Self::Output {
692        Duration(self.0 * rhs)
693    }
694}
695
696impl core::ops::Div<u32> for Duration {
697    type Output = Self;
698
699    #[inline]
700    fn div(self, rhs: u32) -> Self::Output {
701        Duration(self.0 / rhs)
702    }
703}
704
705impl core::ops::Div<Duration> for Duration {
706    type Output = u64;
707
708    #[inline]
709    fn div(self, rhs: Duration) -> Self::Output {
710        self.0 / rhs.0
711    }
712}
713
714#[inline]
715pub(crate) fn now() -> Instant {
716    let ticks = implem::raw_counter();
717    let micros = implem::ticks_to_us(ticks);
718
719    Instant::from_ticks(micros)
720}
721
722#[cfg(esp32)]
723pub(crate) mod implem {
724    use crate::peripherals::TIMG0;
725
726    #[cfg(feature = "rt")]
727    pub(crate) fn time_init() {
728        // FIXME: does this imply that clock management needs to be "rt", too?
729        let apb = crate::soc::clocks::apb_clk_frequency();
730
731        let tg0 = TIMG0::regs();
732
733        tg0.lactconfig().write(|w| unsafe { w.bits(0) });
734        tg0.lactalarmhi().write(|w| unsafe { w.bits(u32::MAX) });
735        tg0.lactalarmlo().write(|w| unsafe { w.bits(u32::MAX) });
736        tg0.lactload().write(|w| unsafe { w.load().bits(1) });
737
738        // 16 MHz counter
739        tg0.lactconfig().write(|w| {
740            unsafe { w.divider().bits((apb / 16_000_000u32) as u16) };
741            w.increase().bit(true);
742            w.autoreload().bit(true);
743            w.en().bit(true)
744        });
745    }
746
747    #[inline]
748    pub(crate) fn raw_counter() -> u64 {
749        // on ESP32 use LACT
750        let tg0 = TIMG0::regs();
751        tg0.lactupdate().write(|w| unsafe { w.update().bits(1) });
752
753        // The peripheral doesn't have a bit to indicate that the update is done, so we
754        // poll the lower 32 bit part of the counter until it changes, or a timeout
755        // expires.
756        let lo_initial = tg0.lactlo().read().bits();
757        let mut div = tg0.lactconfig().read().divider().bits();
758        let lo = loop {
759            let lo = tg0.lactlo().read().bits();
760            if lo != lo_initial || div == 0 {
761                break lo;
762            }
763            div -= 1;
764        };
765        let hi = tg0.lacthi().read().bits();
766
767        ((hi as u64) << 32u64) | lo as u64
768    }
769
770    #[inline]
771    pub(crate) fn ticks_to_us(ticks: u64) -> u64 {
772        ticks / 16
773    }
774
775    #[inline]
776    #[cfg(sleep_light_sleep)]
777    pub(crate) fn us_to_ticks(counter: u64) -> u64 {
778        counter * 16
779    }
780
781    /// Callers must ensure this function is not called concurrently.
782    #[inline]
783    #[cfg(sleep_light_sleep)]
784    pub(crate) unsafe fn update_counter(counter: u64) {
785        // On ESP32 the monotonic counter is the LACT timer of TIMG0. To set its
786        // value we stage the new 64-bit count in the load registers and then
787        // trigger a software reload, which copies the staged value into the
788        // counter immediately.
789        //
790        // A manual `LACTLOAD` while the timer is running (`en = 1`) is silently
791        // dropped when executed from the AppCpu, leaving the monotonic clock stuck
792        // (this is why the post-light-sleep time correction is lost on AppCpu). We
793        // therefore disable the timer around the load (preserving the divider) and
794        // re-enable it afterwards, mirroring `time_init`. Callers run this with
795        // interrupts disabled and the other core parked, so the brief disable is
796        // safe from concurrent reads.
797        let tg0 = TIMG0::regs();
798
799        let divider = tg0.lactconfig().read().divider().bits();
800        tg0.lactconfig().write(|w| unsafe { w.bits(0) });
801
802        tg0.lactloadhi()
803            .write(|w| unsafe { w.load_hi().bits((counter >> 32) as u32) });
804        tg0.lactloadlo()
805            .write(|w| unsafe { w.load_lo().bits(counter as u32) });
806        tg0.lactload().write(|w| unsafe { w.load().bits(1) });
807
808        tg0.lactconfig().write(|w| {
809            unsafe { w.divider().bits(divider) };
810            w.increase().bit(true);
811            w.autoreload().bit(true);
812            w.en().bit(true)
813        });
814    }
815}
816
817#[cfg(systimer_driver_supported)]
818pub(crate) mod implem {
819    use crate::timer::systimer::{SystemTimer, Unit};
820
821    #[cfg(feature = "rt")]
822    pub(crate) fn time_init() {
823        SystemTimer::init_timestamp_scaler();
824    }
825
826    #[inline]
827    pub(crate) fn raw_counter() -> u64 {
828        SystemTimer::unit_value(Unit::Unit0)
829    }
830
831    #[inline]
832    pub(crate) fn ticks_to_us(ticks: u64) -> u64 {
833        SystemTimer::ticks_to_us(ticks)
834    }
835
836    #[inline]
837    #[cfg(sleep_light_sleep)]
838    pub(crate) fn us_to_ticks(counter: u64) -> u64 {
839        SystemTimer::us_to_ticks(counter)
840    }
841
842    /// Callers must ensure this function is not called concurrently.
843    #[inline]
844    #[cfg(sleep_light_sleep)]
845    pub(crate) unsafe fn update_counter(counter: u64) {
846        unsafe {
847            SystemTimer::set_unit_value(Unit::Unit0, counter);
848        }
849    }
850}