Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add initial support for ASSIST_DEBUG in ESP32-H2 (#566)
- Add all `SPI` examples for the ESP32-H2 (#549)
- Add initial support for ADC in ESP32-H2 (#564)
- Simplify the `Delay` driver, derive `Clone` and `Copy` (#568)

### Changed

Expand Down
59 changes: 28 additions & 31 deletions esp-hal-common/src/delay.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
//! Delay driver
//! Delay driver implement the blocking [DelayMs] and [DelayUs] traits from
//! [embedded-hal].
//!
//! Implement the `DelayMs` and `DelayUs` traits from [embedded-hal].
//! The delays are implemented in a "best-effort" way, meaning that the CPU will
//! block for at least the amount of time specified, but accuracy can be
//! affected by many factors, including interrupt usage.
//!
//! [DelayMs]: embedded_hal::blocking::delay::DelayMs
//! [DelayUs]: embedded_hal::blocking::delay::DelayUs
//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/

pub use self::delay::Delay;
use fugit::HertzU64;

/// Delay driver
///
/// Uses the `SYSTIMER` peripheral internally for RISC-V devices, and the
/// built-in Xtensa timer for Xtensa devices.
#[derive(Clone, Copy)]
pub struct Delay {
freq: HertzU64,
}

impl<T> embedded_hal::blocking::delay::DelayMs<T> for Delay
where
Expand Down Expand Up @@ -35,33 +49,24 @@ impl embedded_hal_1::delay::DelayUs for Delay {

#[cfg(riscv)]
mod delay {
use fugit::HertzU64;

use super::*;
use crate::{clock::Clocks, systimer::SystemTimer};

/// Uses the `SYSTIMER` peripheral for counting clock cycles, as
/// unfortunately the ESP32-C3 does NOT implement the `mcycle` CSR, which is
/// how we would normally do this.
pub struct Delay {
freq: HertzU64,
}

impl Delay {
/// Create a new Delay instance
/// Create a new `Delay` instance
pub fn new(clocks: &Clocks) -> Self {
// The counters and comparators are driven using `XTAL_CLK`. The average clock
// frequency is fXTAL_CLK/2.5, which is 16 MHz. The timer counting is
// incremented by 1/16 μs on each `CNT_CLK` cycle.

// The counters and comparators are driven using `XTAL_CLK`.
// The average clock frequency is fXTAL_CLK/2.5, which is 16 MHz.
// The timer counting is incremented by 1/16 μs on each `CNT_CLK` cycle.
Self {
freq: HertzU64::MHz((clocks.xtal_clock.to_MHz() * 10 / 25) as u64),
freq: HertzU64::MHz(clocks.xtal_clock.to_MHz() as u64 * 10 / 25),
}
}

/// Delay for the specified number of microseconds
pub fn delay(&self, us: u32) {
let t0 = SystemTimer::now();
let clocks = (us as u64 * self.freq.raw()) / HertzU64::MHz(1).raw();
let clocks = us as u64 * (self.freq / HertzU64::MHz(1));

while SystemTimer::now().wrapping_sub(t0) & SystemTimer::BIT_MASK <= clocks {}
}
Expand All @@ -70,28 +75,20 @@ mod delay {

#[cfg(xtensa)]
mod delay {
use fugit::HertzU64;

use super::*;
use crate::clock::Clocks;

/// Delay driver
///
/// Uses the built-in Xtensa timer from the `xtensa_lx` crate.
pub struct Delay {
freq: HertzU64,
}

impl Delay {
/// Instantiate the `Delay` driver
/// Create a new `Delay` instance
pub fn new(clocks: &Clocks) -> Self {
Self {
freq: HertzU64::MHz(clocks.cpu_clock.to_MHz() as u64),
freq: clocks.cpu_clock.into(),
}
}

/// Delay for the specified number of microseconds
pub fn delay(&self, us: u32) {
let clocks = (us as u64 * self.freq.raw()) / HertzU64::MHz(1).raw();
let clocks = us as u64 * (self.freq / HertzU64::MHz(1));
xtensa_lx::timer::delay(clocks as u32);
}
}
Expand Down