Simplify the Delay driver, derive Clone and Copy (#568)

* Simplify the `Delay` driver, derive `Clone` and `Copy`

The RISC-V and Xtensa implementations of the delay functionality are both safe to access from multiple contexts, and the `Delay` struct does not take ownership of any peripheral struct, so `Delay` is safe to clone/copy

* Update the CHANGELOG
This commit is contained in:
Jesse Braham 2023-05-31 06:45:53 -07:00 committed by GitHub
parent b1630db5d2
commit 67e9c60a23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 31 deletions

View File

@ -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

View File

@ -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
@ -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 {}
}
@ -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);
}
}