esp_lp_hal/
delay.rs

1//! # Delay driver
2//!
3//! ## Overview
4//!
5//! The delay driver provides blocking delay functionality. The driver
6//! implements the relevant traits from `embedded-hal`.
7//!
8//! ## Examples
9//!
10//! ```rust
11//! esp_lp_hal::delay::Delay.delay_millis(500);
12//! ```
13
14/// Delay driver
15#[derive(Debug, Clone, Copy)]
16pub struct Delay;
17
18impl Delay {
19    /// Delay for at least the number of specific milliseconds.
20    pub fn delay_millis(&self, mut ms: u32) {
21        const MICROS_PER_MILLI: u32 = 1_000;
22        const MAX_MILLIS: u32 = u32::MAX / MICROS_PER_MILLI;
23
24        // Avoid potential overflow if milli -> micro conversion is too large
25        while ms > MAX_MILLIS {
26            ms -= MAX_MILLIS;
27            self.delay_micros(MAX_MILLIS * MICROS_PER_MILLI);
28        }
29
30        self.delay_micros(ms * MICROS_PER_MILLI);
31    }
32
33    /// Delay for at least the number of specific microseconds.
34    pub fn delay_micros(&self, mut us: u32) {
35        const NANOS_PER_MICRO: u32 = 1_000;
36        const MAX_MICROS: u32 = u32::MAX / NANOS_PER_MICRO;
37
38        // Avoid potential overflow if micro -> nano conversion is too large
39        while us > MAX_MICROS {
40            us -= MAX_MICROS;
41            self.delay_nanos(MAX_MICROS * NANOS_PER_MICRO);
42        }
43
44        self.delay_nanos(us * NANOS_PER_MICRO);
45    }
46
47    /// Delay for at least the number of specific nanoseconds.
48    pub fn delay_nanos(&self, ns: u32) {
49        let ticks_seconds = unsafe { crate::CPU_CLOCK };
50        let clock = (ns as u64 * (ticks_seconds as u64)) / 1_000_000_000u64;
51        let t0 = cycles();
52
53        while cycles().wrapping_sub(t0) <= clock {}
54    }
55}
56
57#[cfg(feature = "esp32c6")]
58#[inline(always)]
59fn cycles() -> u64 {
60    riscv::register::mcycle::read64()
61}
62
63#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
64#[inline(always)]
65fn cycles() -> u64 {
66    let mut cycles: u32;
67    unsafe {
68        core::arch::asm!(
69            "rdcycle {cycles}",
70            cycles = out(reg) cycles,
71        )
72    }
73
74    cycles as u64
75}
76
77#[cfg(feature = "embedded-hal")]
78impl embedded_hal::delay::DelayNs for Delay {
79    #[inline(always)]
80    fn delay_ns(&mut self, ns: u32) {
81        self.delay_nanos(ns);
82    }
83}