esp_hal/
delay.rs

1//! # Delay
2//!
3//! ## Overview
4//!
5//! The Delay driver provides blocking delay functionalities using the
6//! [now] function.
7//!
8//! ## Configuration
9//!
10//! The delays are implemented in a "best-effort" way, meaning that the CPU will
11//! block for at least the amount of time specified, but accuracy can be
12//! affected by many factors, including interrupt usage.
13//!
14//! ## Usage
15//!
16//! This module implements the blocking [DelayNs] trait from [embedded-hal].
17//!
18//! ## Examples
19//! ### Delay for 1 second
20//! ```rust, no_run
21#![doc = crate::before_snippet!()]
22//! # use esp_hal::delay::Delay;
23//! # use embedded_hal::delay::DelayNs;
24//! let mut delay = Delay::new();
25//!
26//! delay.delay_ms(1000 as u32);
27//! # }
28//! ```
29//! 
30//! [DelayNs]: https://docs.rs/embedded-hal/1.0.0/embedded_hal/delay/trait.DelayNs.html
31//! [embedded-hal]: https://docs.rs/embedded-hal/1.0.0/embedded_hal/delay/index.html
32//! [now]: crate::time::now
33
34pub use fugit::MicrosDurationU64;
35
36/// Delay driver
37///
38/// Uses the `SYSTIMER` peripheral internally for RISC-V devices, and the
39/// built-in Xtensa timer for Xtensa devices.
40#[derive(Clone, Copy, Default)]
41#[non_exhaustive]
42pub struct Delay;
43
44impl embedded_hal::delay::DelayNs for Delay {
45    fn delay_ns(&mut self, ns: u32) {
46        self.delay_nanos(ns);
47    }
48}
49
50impl Delay {
51    /// Creates a new `Delay` instance.
52    pub const fn new() -> Self {
53        Self {}
54    }
55
56    /// Delay for the specified time
57    pub fn delay(&self, delay: MicrosDurationU64) {
58        let start = crate::time::now();
59
60        while elapsed_since(start) < delay {}
61    }
62
63    /// Delay for the specified number of milliseconds
64    pub fn delay_millis(&self, ms: u32) {
65        for _ in 0..ms {
66            self.delay_micros(1000);
67        }
68    }
69
70    /// Delay for the specified number of microseconds
71    pub fn delay_micros(&self, us: u32) {
72        let delay = MicrosDurationU64::micros(us as u64);
73        self.delay(delay);
74    }
75
76    /// Delay for the specified number of nanoseconds
77    pub fn delay_nanos(&self, ns: u32) {
78        let delay = MicrosDurationU64::nanos(ns as u64);
79        self.delay(delay);
80    }
81}
82
83fn elapsed_since(start: fugit::Instant<u64, 1, 1_000_000>) -> MicrosDurationU64 {
84    let now = crate::time::now();
85
86    if start.ticks() <= now.ticks() {
87        now - start
88    } else {
89        // now specifies at least 7 happy years, let's ignore this issue for
90        // now.
91        panic!("Time has wrapped around, which we currently don't handle");
92    }
93}