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}