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}