Skip to content

Commit

Permalink
Newtype fugit Rate, Instant and Duration (#3083)
Browse files Browse the repository at this point in the history
* Newtype fugit Rate, Instant and Duration

* Document, remove time::now

* Fix perf

* Tweak docs
  • Loading branch information
bugadani authored Feb 4, 2025
1 parent fe53061 commit 8c69e8c
Show file tree
Hide file tree
Showing 115 changed files with 1,053 additions and 681 deletions.
11 changes: 5 additions & 6 deletions esp-hal-embassy/src/time_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use embassy_time_driver::Driver;
use esp_hal::{
interrupt::{InterruptHandler, Priority},
sync::Locked,
time::{now, ExtU64},
time::{Duration, Instant},
timer::OneShotTimer,
Blocking,
};
Expand Down Expand Up @@ -203,11 +203,10 @@ impl EmbassyTimer {
/// Returns `true` if the timer was armed, `false` if the timestamp is in
/// the past.
fn arm(timer: &mut Timer, timestamp: u64) -> bool {
let now = now().duration_since_epoch();
let ts = timestamp.micros();
let now = Instant::now().duration_since_epoch().as_micros();

if ts > now {
let timeout = ts - now;
if timestamp > now {
let timeout = Duration::from_micros(timestamp - now);
unwrap!(timer.schedule(timeout));
true
} else {
Expand Down Expand Up @@ -295,7 +294,7 @@ impl EmbassyTimer {

impl Driver for EmbassyTimer {
fn now(&self) -> u64 {
now().ticks()
Instant::now().duration_since_epoch().as_micros()
}

fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
Expand Down
4 changes: 3 additions & 1 deletion esp-hal-embassy/src/timer_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ impl TimerQueue {
}

pub fn dispatch(&self) {
let now = esp_hal::time::now().ticks();
let now = esp_hal::time::Instant::now()
.duration_since_epoch()
.as_micros();
self.arm_alarm(now);
}

Expand Down
4 changes: 4 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added

- SPI: Added support for 3-wire SPI (#2919)
- UART: Add separate config for Rx and Tx (#2965)
- Added accessor methods to config structs (#3011)
- `esp_hal::time::{Rate, Duration, Instant}` (#3083)
- Async support for ADC oneshot reads for ESP32C2, ESP32C3, ESP32C6 and ESP32H2 (#2925, #3082)

### Changed
Expand All @@ -33,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `flip-link` feature is now a config option (`ESP_HAL_CONFIG_FLIP_LINK`) (#3001)
- Migrate AES driver to DMA move API (#3084)
- Removed features `psram-quad` and `psram-octal` - replaced by `psram` and the `ESP_HAL_CONFIG_PSRAM_MODE` (`quad`/`octal`) (#3001)
- The `esp_hal::time` module no longer reexports `fugit` types (#3083)

- I2C: Async functions are postfixed with `_async`, non-async functions are available in async-mode (#3056)

Expand All @@ -48,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- OutputOpenDrain has been removed (#3029)
- The fields of config structs are no longer public (#3011)
- Removed the dysfunctional `DmaChannel::set_priority` function (#3088)
- `esp_hal::time::now()`, which has been replaced by `esp_hal::time::Instant::now()` (#3083)

## [0.23.1] - 2025-01-15

Expand Down
15 changes: 15 additions & 0 deletions esp-hal/MIGRATING-0.23.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ All async functions now include the `_async` postfix. Additionally the non-async
```diff
- let result = i2c.write_read(0x77, &[0xaa], &mut data).await;
+ let result = i2c.write_read_async(0x77, &[0xaa], &mut data).await;
```

## ADC Changes

Expand All @@ -277,3 +278,17 @@ NOTE: Async support is only supported in ESP32C3 and ESP32C6 for now
- Adc<'d, ADC>
+ Adc<'d, ADC, Blocking>
```

## time API changes

ESP-HAL no longer publicly exposes `fugit` and no longer exposes the concept of a `tick`.
This comes with a number of changes:

- The `RateExtU32` and similar traits are no longer used, which means `.kHz()` and similar suffix
conversions are no longer available. A number of matching constructors are available. For example,
instead of `1.MHz()` you need to write `Rate::from_mhz(1)`.
- Methods on `esp_hal::time` types are named differently.
- Getters are prefixed with `as_`, e.g. `Duration::as_secs`.
- Constructors are prefixed with `from`, e.g. `Rate::from_mhz`.
- A number of functions that convert from a number into a time type (e.g. `Duration::from_ticks`)
are not available. Use conversions from physical units of time, like `Duration::from_millis`.
1 change: 1 addition & 0 deletions esp-hal/src/clock/clocks_ll/esp32s2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub(crate) fn set_cpu_clock(cpu_clock_speed: CpuClock) {
} as u8)
});

// FIXME untangle this
let value = (((80 * MHZ) >> 12) & UINT16_MAX) | ((((80 * MHZ) >> 12) & UINT16_MAX) << 16);
rtc_cntl.store5().modify(|_, w| w.scratch5().bits(value));
}
Expand Down
5 changes: 1 addition & 4 deletions esp-hal/src/clock/clocks_ll/esp32s3.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use core::ops::Div;

use crate::{
clock::{Clock, CpuClock},
rom,
Expand All @@ -24,6 +22,5 @@ pub(crate) fn set_cpu_clock(cpu_clock_speed: CpuClock) {
});
}

let ticks_per_us = cpu_clock_speed.frequency().div(1_000_000);
rom::ets_update_cpu_frequency_rom(ticks_per_us.raw());
rom::ets_update_cpu_frequency_rom(cpu_clock_speed.frequency().as_mhz());
}
100 changes: 50 additions & 50 deletions esp-hal/src/clock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@
//! # }
//! ```
use fugit::HertzU32;

#[cfg(any(esp32, esp32c2))]
use crate::rtc_cntl::RtcClock;
use crate::time::Rate;

#[cfg_attr(esp32, path = "clocks_ll/esp32.rs")]
#[cfg_attr(esp32c2, path = "clocks_ll/esp32c2.rs")]
Expand All @@ -61,17 +60,17 @@ pub(crate) mod clocks_ll;
/// Clock properties
#[doc(hidden)]
pub trait Clock {
/// Frequency of the clock in [Hertz](fugit::HertzU32), using [fugit] types.
fn frequency(&self) -> HertzU32;
/// Frequency of the clock in [Rate].
fn frequency(&self) -> Rate;

/// Frequency of the clock in Megahertz
fn mhz(&self) -> u32 {
self.frequency().to_MHz()
self.frequency().as_mhz()
}

/// Frequency of the clock in Hertz
fn hz(&self) -> u32 {
self.frequency().to_Hz()
self.frequency().as_hz()
}
}

Expand Down Expand Up @@ -136,8 +135,8 @@ impl CpuClock {
}

impl Clock for CpuClock {
fn frequency(&self) -> HertzU32 {
HertzU32::MHz(*self as u32)
fn frequency(&self) -> Rate {
Rate::from_mhz(*self as u32)
}
}

Expand All @@ -160,15 +159,15 @@ pub enum XtalClock {
}

impl Clock for XtalClock {
fn frequency(&self) -> HertzU32 {
fn frequency(&self) -> Rate {
match self {
#[cfg(any(esp32, esp32c2))]
XtalClock::_26M => HertzU32::MHz(26),
XtalClock::_26M => Rate::from_mhz(26),
#[cfg(any(esp32c3, esp32h2, esp32s3))]
XtalClock::_32M => HertzU32::MHz(32),
XtalClock::_32M => Rate::from_mhz(32),
#[cfg(not(esp32h2))]
XtalClock::_40M => HertzU32::MHz(40),
XtalClock::Other(mhz) => HertzU32::MHz(*mhz),
XtalClock::_40M => Rate::from_mhz(40),
XtalClock::Other(mhz) => Rate::from_mhz(*mhz),
}
}
}
Expand Down Expand Up @@ -199,28 +198,28 @@ pub(crate) enum PllClock {
}

impl Clock for PllClock {
fn frequency(&self) -> HertzU32 {
fn frequency(&self) -> Rate {
match self {
#[cfg(esp32h2)]
Self::Pll8MHz => HertzU32::MHz(8),
Self::Pll8MHz => Rate::from_mhz(8),
#[cfg(any(esp32c6, esp32h2))]
Self::Pll48MHz => HertzU32::MHz(48),
Self::Pll48MHz => Rate::from_mhz(48),
#[cfg(esp32h2)]
Self::Pll64MHz => HertzU32::MHz(64),
Self::Pll64MHz => Rate::from_mhz(64),
#[cfg(esp32c6)]
Self::Pll80MHz => HertzU32::MHz(80),
Self::Pll80MHz => Rate::from_mhz(80),
#[cfg(esp32h2)]
Self::Pll96MHz => HertzU32::MHz(96),
Self::Pll96MHz => Rate::from_mhz(96),
#[cfg(esp32c6)]
Self::Pll120MHz => HertzU32::MHz(120),
Self::Pll120MHz => Rate::from_mhz(120),
#[cfg(esp32c6)]
Self::Pll160MHz => HertzU32::MHz(160),
Self::Pll160MHz => Rate::from_mhz(160),
#[cfg(esp32c6)]
Self::Pll240MHz => HertzU32::MHz(240),
Self::Pll240MHz => Rate::from_mhz(240),
#[cfg(not(any(esp32c2, esp32c6, esp32h2)))]
Self::Pll320MHz => HertzU32::MHz(320),
Self::Pll320MHz => Rate::from_mhz(320),
#[cfg(not(esp32h2))]
Self::Pll480MHz => HertzU32::MHz(480),
Self::Pll480MHz => Rate::from_mhz(480),
}
}
}
Expand All @@ -238,15 +237,15 @@ pub(crate) enum ApbClock {
}

impl Clock for ApbClock {
fn frequency(&self) -> HertzU32 {
fn frequency(&self) -> Rate {
match self {
#[cfg(esp32h2)]
ApbClock::ApbFreq32MHz => HertzU32::MHz(32),
ApbClock::ApbFreq32MHz => Rate::from_mhz(32),
#[cfg(not(esp32h2))]
ApbClock::ApbFreq40MHz => HertzU32::MHz(40),
ApbClock::ApbFreq40MHz => Rate::from_mhz(40),
#[cfg(not(esp32h2))]
ApbClock::ApbFreq80MHz => HertzU32::MHz(80),
ApbClock::ApbFreqOther(mhz) => HertzU32::MHz(*mhz),
ApbClock::ApbFreq80MHz => Rate::from_mhz(80),
ApbClock::ApbFreqOther(mhz) => Rate::from_mhz(*mhz),
}
}
}
Expand All @@ -258,37 +257,37 @@ impl Clock for ApbClock {
#[doc(hidden)]
pub struct Clocks {
/// CPU clock frequency
pub cpu_clock: HertzU32,
pub cpu_clock: Rate,

/// APB clock frequency
pub apb_clock: HertzU32,
pub apb_clock: Rate,

/// XTAL clock frequency
pub xtal_clock: HertzU32,
pub xtal_clock: Rate,

/// I2C clock frequency
#[cfg(esp32)]
pub i2c_clock: HertzU32,
pub i2c_clock: Rate,

/// PWM clock frequency
#[cfg(esp32)]
pub pwm_clock: HertzU32,
pub pwm_clock: Rate,

/// Crypto PWM clock frequency
#[cfg(esp32s3)]
pub crypto_pwm_clock: HertzU32,
pub crypto_pwm_clock: Rate,

/// Crypto clock frequency
#[cfg(any(esp32c6, esp32h2))]
pub crypto_clock: HertzU32,
pub crypto_clock: Rate,

/// PLL 48M clock frequency (fixed)
#[cfg(esp32h2)]
pub pll_48m_clock: HertzU32,
pub pll_48m_clock: Rate,

/// PLL 96M clock frequency (fixed)
#[cfg(esp32h2)]
pub pll_96m_clock: HertzU32,
pub pll_96m_clock: Rate,
}

static mut ACTIVE_CLOCKS: Option<Clocks> = None;
Expand Down Expand Up @@ -318,7 +317,8 @@ impl Clocks {
/// This function will run the frequency estimation if called before
/// [`crate::init()`].
#[cfg(systimer)]
pub(crate) fn xtal_freq() -> HertzU32 {
#[inline]
pub(crate) fn xtal_freq() -> Rate {
if let Some(clocks) = Self::try_get() {
clocks.xtal_clock
} else {
Expand Down Expand Up @@ -356,13 +356,13 @@ impl Clocks {

Self {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: HertzU32::MHz(80),
xtal_clock: HertzU32::MHz(xtal_freq.mhz()),
i2c_clock: HertzU32::MHz(80),
apb_clock: Rate::from_mhz(80),
xtal_clock: Rate::from_mhz(xtal_freq.mhz()),
i2c_clock: Rate::from_mhz(80),
// The docs are unclear here. pwm_clock seems to be tied to clocks.apb_clock
// while simultaneously being fixed at 160 MHz.
// Testing showed 160 MHz to be correct for current clock configurations.
pwm_clock: HertzU32::MHz(160),
pwm_clock: Rate::from_mhz(160),
}
}
}
Expand Down Expand Up @@ -476,7 +476,7 @@ impl Clocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: apb_freq.frequency(),
xtal_clock: xtal_freq.frequency(),
crypto_clock: HertzU32::MHz(160),
crypto_clock: Rate::from_mhz(160),
}
}
}
Expand Down Expand Up @@ -513,9 +513,9 @@ impl Clocks {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: apb_freq.frequency(),
xtal_clock: xtal_freq.frequency(),
pll_48m_clock: HertzU32::MHz(48),
crypto_clock: HertzU32::MHz(96),
pll_96m_clock: HertzU32::MHz(96),
pll_48m_clock: Rate::from_mhz(48),
crypto_clock: Rate::from_mhz(96),
pll_96m_clock: Rate::from_mhz(96),
}
}
}
Expand All @@ -536,7 +536,7 @@ impl Clocks {

Self {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: HertzU32::MHz(80),
apb_clock: Rate::from_mhz(80),
xtal_clock: xtal_freq.frequency(),
}
}
Expand All @@ -558,9 +558,9 @@ impl Clocks {

Self {
cpu_clock: cpu_clock_speed.frequency(),
apb_clock: HertzU32::MHz(80),
apb_clock: Rate::from_mhz(80),
xtal_clock: xtal_freq.frequency(),
crypto_pwm_clock: HertzU32::MHz(160),
crypto_pwm_clock: Rate::from_mhz(160),
}
}
}
7 changes: 5 additions & 2 deletions esp-hal/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,24 @@
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! use esp_hal::clock::CpuClock;
//! use esp_hal::time::Duration;
//!
//! let config =
//! esp_hal::Config::default().with_cpu_clock(CpuClock::max()).
//! with_watchdog(esp_hal::config::WatchdogConfig::default().
//! with_rwdt(esp_hal::config::WatchdogStatus::Enabled(fugit::MicrosDurationU64::millis(1000u64))));
//! with_rwdt(esp_hal::config::WatchdogStatus::Enabled(Duration::from_millis(1000u64))));
//! let peripherals = esp_hal::init(config);
//! # Ok(())
//! # }
//! ```
use crate::time::Duration;

/// Watchdog status.
#[derive(Default, PartialEq, Clone, Copy)]
pub enum WatchdogStatus {
/// Enables a watchdog timer with the specified timeout.
Enabled(fugit::MicrosDurationU64),
Enabled(Duration),
/// Disables the watchdog timer.
#[default]
Disabled,
Expand Down
Loading

0 comments on commit 8c69e8c

Please sign in to comment.