From c6b1a796f7b8dd815ab22ae1cdddbe69b6d5f5cb Mon Sep 17 00:00:00 2001 From: Dominic Fischer Date: Sun, 28 Jul 2024 17:18:22 +0100 Subject: [PATCH] Improve SYSTIMER API --- esp-hal/CHANGELOG.md | 2 +- esp-hal/src/timer/mod.rs | 36 +- esp-hal/src/timer/systimer.rs | 928 ++++++++++++------ examples/src/bin/etm_blinky_systimer.rs | 3 +- examples/src/bin/systimer.rs | 29 +- examples/src/bin/wifi_embassy_access_point.rs | 3 +- .../bin/wifi_embassy_access_point_with_sta.rs | 3 +- examples/src/bin/wifi_embassy_bench.rs | 3 +- examples/src/bin/wifi_embassy_ble.rs | 3 +- examples/src/bin/wifi_embassy_dhcp.rs | 3 +- examples/src/bin/wifi_embassy_esp_now.rs | 3 +- .../src/bin/wifi_embassy_esp_now_duplex.rs | 3 +- 12 files changed, 690 insertions(+), 329 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 593a808ff83..1ad69f6685d 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Peripheral driver constructors don't take `InterruptHandler`s anymore. Use `set_interrupt_handler` to explicitly set the interrupt handler now. (#1819) - Use the peripheral ref pattern for `OneShotTimer` and `PeriodicTimer` (#1855) - +- Improve SYSTIMER API (#1870) - Allow DMA to/from psram for esp32s3 (#1827) - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) diff --git a/esp-hal/src/timer/mod.rs b/esp-hal/src/timer/mod.rs index 5cf4391105f..58f581fd3a7 100644 --- a/esp-hal/src/timer/mod.rs +++ b/esp-hal/src/timer/mod.rs @@ -376,17 +376,17 @@ pub enum ErasedTimer { #[cfg(all(timg1, timg_timer1))] Timg1Timer1(timg::Timer, Blocking>), #[cfg(systimer)] - SystimerAlarm0Periodic(systimer::Alarm), + SystimerAlarm0Periodic(systimer::Alarm<'static, systimer::Periodic, Blocking, 0, 0>), #[cfg(systimer)] - SystimerAlarm1Periodic(systimer::Alarm), + SystimerAlarm1Periodic(systimer::Alarm<'static, systimer::Periodic, Blocking, 1, 0>), #[cfg(systimer)] - SystimerAlarm2Periodic(systimer::Alarm), + SystimerAlarm2Periodic(systimer::Alarm<'static, systimer::Periodic, Blocking, 2, 0>), #[cfg(systimer)] - SystimerAlarm0Target(systimer::Alarm), + SystimerAlarm0Target(systimer::Alarm<'static, systimer::Target, Blocking, 0, 0>), #[cfg(systimer)] - SystimerAlarm1Target(systimer::Alarm), + SystimerAlarm1Target(systimer::Alarm<'static, systimer::Target, Blocking, 1, 0>), #[cfg(systimer)] - SystimerAlarm2Target(systimer::Alarm), + SystimerAlarm2Target(systimer::Alarm<'static, systimer::Target, Blocking, 2, 0>), } impl crate::private::Sealed for ErasedTimer {} @@ -419,43 +419,43 @@ impl From, Blocking>> for Er } #[cfg(systimer)] -impl From> for ErasedTimer { - fn from(value: systimer::Alarm) -> Self { +impl From> for ErasedTimer { + fn from(value: systimer::Alarm<'static, systimer::Periodic, Blocking, 0, 0>) -> Self { Self::SystimerAlarm0Periodic(value) } } #[cfg(systimer)] -impl From> for ErasedTimer { - fn from(value: systimer::Alarm) -> Self { +impl From> for ErasedTimer { + fn from(value: systimer::Alarm<'static, systimer::Periodic, Blocking, 1, 0>) -> Self { Self::SystimerAlarm1Periodic(value) } } #[cfg(systimer)] -impl From> for ErasedTimer { - fn from(value: systimer::Alarm) -> Self { +impl From> for ErasedTimer { + fn from(value: systimer::Alarm<'static, systimer::Periodic, Blocking, 2, 0>) -> Self { Self::SystimerAlarm2Periodic(value) } } #[cfg(systimer)] -impl From> for ErasedTimer { - fn from(value: systimer::Alarm) -> Self { +impl From> for ErasedTimer { + fn from(value: systimer::Alarm<'static, systimer::Target, Blocking, 0, 0>) -> Self { Self::SystimerAlarm0Target(value) } } #[cfg(systimer)] -impl From> for ErasedTimer { - fn from(value: systimer::Alarm) -> Self { +impl From> for ErasedTimer { + fn from(value: systimer::Alarm<'static, systimer::Target, Blocking, 1, 0>) -> Self { Self::SystimerAlarm1Target(value) } } #[cfg(systimer)] -impl From> for ErasedTimer { - fn from(value: systimer::Alarm) -> Self { +impl From> for ErasedTimer { + fn from(value: systimer::Alarm<'static, systimer::Target, Blocking, 2, 0>) -> Self { Self::SystimerAlarm2Target(value) } } diff --git a/esp-hal/src/timer/systimer.rs b/esp-hal/src/timer/systimer.rs index aac957bfe81..9507c48ea7e 100644 --- a/esp-hal/src/timer/systimer.rs +++ b/esp-hal/src/timer/systimer.rs @@ -68,40 +68,51 @@ //! } //! ``` -use core::marker::PhantomData; +use core::{ + cell::Cell, + fmt::{Debug, Formatter}, + marker::PhantomData, + ptr::addr_of_mut, +}; +use critical_section::Mutex; use fugit::{Instant, MicrosDurationU32, MicrosDurationU64}; use super::{Error, Timer as _}; use crate::{ interrupt::{self, InterruptHandler}, peripheral::Peripheral, - peripherals::{ - systimer::{TARGET_CONF, TRGT}, - Interrupt, - SYSTIMER, - }, + peripherals::{Interrupt, SYSTIMER}, Async, Blocking, + Cpu, InterruptConfigurable, Mode, }; /// System Timer driver. -pub struct SystemTimer<'d, DM> -where - DM: Mode, -{ - _phantom: PhantomData<&'d ()>, - /// Alarm 0. - pub alarm0: Alarm, - /// Alarm 1. - pub alarm1: Alarm, - /// Alarm 2. - pub alarm2: Alarm, +pub struct SystemTimer<'d> { + /// Shared configuration + pub config: Config<'d>, + + /// Unit 0 + pub unit0: Unit<'d, 0>, + + #[cfg(not(esp32s2))] + /// Unit 1 + pub unit1: Unit<'d, 1>, + + /// Comparator 0. + pub comparator0: Comparator<'d, 0>, + + /// Comparator 1. + pub comparator1: Comparator<'d, 1>, + + /// Comparator 2. + pub comparator2: Comparator<'d, 2>, } -impl<'d> SystemTimer<'d, Blocking> { +impl<'d> SystemTimer<'d> { cfg_if::cfg_if! { if #[cfg(esp32s2)] { /// Bitmask to be applied to the raw register value. @@ -120,16 +131,19 @@ impl<'d> SystemTimer<'d, Blocking> { } } - /// Create a new instance in [crate::Blocking] mode. + /// Create a new instance. pub fn new(_systimer: impl Peripheral

+ 'd) -> Self { #[cfg(soc_etm)] etm::enable_etm(); Self { - _phantom: PhantomData, - alarm0: Alarm::new(), - alarm1: Alarm::new(), - alarm2: Alarm::new(), + config: Config::new(), + unit0: Unit::new(), + #[cfg(not(esp32s2))] + unit1: Unit::new(), + comparator0: Comparator::new(), + comparator1: Comparator::new(), + comparator2: Comparator::new(), } } @@ -138,150 +152,551 @@ impl<'d> SystemTimer<'d, Blocking> { // This should be safe to access from multiple contexts // worst case scenario the second accessor ends up reading // an older time stamp - let systimer = unsafe { &*SYSTIMER::ptr() }; - systimer.unit0_op().modify(|_, w| w.update().set_bit()); - - while !systimer.unit0_op().read().value_valid().bit_is_set() {} - let value_lo = systimer.unit0_value().lo().read().bits(); - let value_hi = systimer.unit0_value().hi().read().bits(); + let unit = unsafe { Unit::<'_, 0>::conjure() }; - ((value_hi as u64) << 32) | value_lo as u64 + unit.update(); + loop { + if let Some(value) = unit.poll_count() { + break value; + } + } } } -impl<'d> SystemTimer<'d, Async> { - /// Create a new instance in [crate::Async] mode. - pub fn new_async(_systimer: impl Peripheral

+ 'd) -> Self { - #[cfg(soc_etm)] - etm::enable_etm(); +impl SystemTimer<'static> { + /// Split the System Timer into three alarms. + /// + /// This is a convenience method to create `'static` alarms of the same + /// type. You are encouraged to use [Alarm::new] over this very specific + /// helper. + pub fn split(self) -> SysTimerAlarms { + static CONFIG: Mutex>> = Mutex::new(Cell::new(None)); + static mut UNIT0: Option> = None; + let unit0 = unsafe { &mut *addr_of_mut!(UNIT0) }; + + critical_section::with(|cs| CONFIG.borrow(cs).set(Some(self.config))); + + let unit0 = unit0.insert(self.unit0); + let unit = FrozenUnit::new(unit0); + + SysTimerAlarms { + alarm0: Alarm::new(self.comparator0, &unit, &CONFIG), + alarm1: Alarm::new(self.comparator1, &unit, &CONFIG), + alarm2: Alarm::new(self.comparator2, &unit, &CONFIG), + #[cfg(not(esp32s2))] + unit1: self.unit1, + } + } - Self { - alarm0: Alarm::new(), - alarm1: Alarm::new(), - alarm2: Alarm::new(), - _phantom: PhantomData, + /// Split the System Timer into three alarms. + /// + /// This is a convenience method to create `'static` alarms of the same + /// type. You are encouraged to use [Alarm::new_async] over this very + /// specific helper. + pub fn split_async(self) -> SysTimerAlarms { + static CONFIG: Mutex>> = Mutex::new(Cell::new(None)); + static mut UNIT0: Option> = None; + let unit0 = unsafe { &mut *addr_of_mut!(UNIT0) }; + + critical_section::with(|cs| CONFIG.borrow(cs).set(Some(self.config))); + + let unit0 = unit0.insert(self.unit0); + let unit = FrozenUnit::new(unit0); + + SysTimerAlarms { + alarm0: Alarm::new_async(self.comparator0, &unit, &CONFIG), + alarm1: Alarm::new_async(self.comparator1, &unit, &CONFIG), + alarm2: Alarm::new_async(self.comparator2, &unit, &CONFIG), + #[cfg(not(esp32s2))] + unit1: self.unit1, } } } -/// A marker for a [Alarm] in target mode. +/// Represents the shared configuration between the units and comparators. #[derive(Debug)] -pub struct Target; +pub struct Config<'d>(PhantomData<&'d ()>); -/// A marker for a [Alarm] in periodic mode. -#[derive(Debug)] -pub struct Periodic; +impl<'d> Config<'d> { + fn new() -> Self { + Self(PhantomData) + } +} -/// A single alarm. +/// A +#[cfg_attr(esp32s2, doc = "64-bit")] +#[cfg_attr(not(esp32s2), doc = "52-bit")] +/// counter. #[derive(Debug)] -pub struct Alarm -where - DM: Mode, -{ - _pd: PhantomData<(MODE, DM)>, +pub struct Unit<'d, const CHANNEL: u8>(PhantomData<&'d ()>); + +impl<'d, const CHANNEL: u8> Unit<'d, CHANNEL> { + fn new() -> Self { + Self(PhantomData) + } + + #[cfg(not(esp32s2))] + /// Configures when this counter can run. + /// It can be configured to stall or continue running when CPU stalls + /// or enters on-chip-debugging mode + pub fn configure(&self, _config: &mut Config, config: UnitConfig) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + let conf = systimer.conf(); + + conf.modify(|_, w| match config { + UnitConfig::Disabled => match CHANNEL { + 0 => w.timer_unit0_work_en().clear_bit(), + 1 => w.timer_unit1_work_en().clear_bit(), + _ => unreachable!(), + }, + UnitConfig::DisabledIfCpuIsStalled(cpu) => match CHANNEL { + 0 => w + .timer_unit0_work_en() + .set_bit() + .timer_unit0_core0_stall_en() + .bit(cpu == Cpu::ProCpu) + .timer_unit0_core1_stall_en() + .bit(cpu != Cpu::ProCpu), + 1 => w + .timer_unit1_work_en() + .set_bit() + .timer_unit1_core0_stall_en() + .bit(cpu == Cpu::ProCpu) + .timer_unit1_core1_stall_en() + .bit(cpu != Cpu::ProCpu), + _ => unreachable!(), + }, + UnitConfig::Enabled => match CHANNEL { + 0 => w + .timer_unit0_work_en() + .set_bit() + .timer_unit0_core0_stall_en() + .clear_bit() + .timer_unit0_core1_stall_en() + .clear_bit(), + 1 => w + .timer_unit1_work_en() + .set_bit() + .timer_unit1_core0_stall_en() + .clear_bit() + .timer_unit1_core1_stall_en() + .clear_bit(), + _ => unreachable!(), + }, + }); + } + + /// Set the value of the counter immediately. If the unit is at work, + /// the counter will continue to count up from the new reloaded value. + /// + /// This can be used to load back the sleep time recorded by RTC timer + /// via software after Light-sleep + pub fn set_count(&self, value: u64) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + #[cfg(not(esp32s2))] + { + let unitload = systimer.unitload(CHANNEL as _); + let unit_load = systimer.unit_load(CHANNEL as _); + + unitload.hi().write(|w| w.load_hi().set((value << 32) as _)); + unitload + .lo() + .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _)); + + unit_load.write(|w| w.load().set_bit()); + } + #[cfg(esp32s2)] + { + systimer + .load_hi() + .write(|w| w.load_hi().set((value << 32) as _)); + systimer + .load_lo() + .write(|w| w.load_lo().set((value & 0xFFFF_FFFF) as _)); + + systimer.load().write(|w| w.load().set_bit()); + } + } + + /// Update the value returned by [Self::poll_count] to be the current value + /// of the counter. + /// + /// This can be used to read the current value of the timer. + pub fn update(&self) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + systimer + .unit_op(CHANNEL as _) + .modify(|_, w| w.update().set_bit()); + } + + /// Return the count value at the time of the last call to [Self::update]. + /// + /// Returns None if the update isn't ready to read if update has never been + /// called. + pub fn poll_count(&self) -> Option { + let systimer = unsafe { &*SYSTIMER::ptr() }; + if systimer + .unit_op(CHANNEL as _) + .read() + .value_valid() + .bit_is_set() + { + let unit_value = systimer.unit_value(CHANNEL as _); + + let lo = unit_value.lo().read().bits(); + let hi = unit_value.hi().read().bits(); + + Some(((hi as u64) << 32) | lo as u64) + } else { + None + } + } + + /// Convenience method to call [Self::update] and [Self::poll_count]. + pub fn read_count(&self) -> u64 { + // This can be a shared reference as long as this type isn't Sync. + + self.update(); + loop { + if let Some(count) = self.poll_count() { + break count; + } + } + } } -impl Alarm -where - DM: Mode, -{ +/// A comparator that can generate alarms/interrupts based on values of a unit. +#[derive(Debug)] +pub struct Comparator<'d, const CHANNEL: u8>(PhantomData<&'d ()>); + +impl<'d, const CHANNEL: u8> Comparator<'d, CHANNEL> { fn new() -> Self { - Self { _pd: PhantomData } + Self(PhantomData) } - fn configure(&self, conf: impl FnOnce(&TARGET_CONF, &TRGT)) { - unsafe { - let systimer = &*SYSTIMER::ptr(); - let tconf = systimer.target_conf(CHANNEL as usize); - let target = systimer.trgt(CHANNEL as usize); + /// Enables/disables the comparator. If enabled, this means + /// it will generate interrupt based on its configuration. + /// + /// Note: This requires an exclusive reference to config as the register + /// is shared between all units and comparators. + #[cfg(not(esp32s2))] + pub fn set_enable(&self, _config: &mut Config<'d>, enable: bool) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + systimer.conf().modify(|_, w| match CHANNEL { + 0 => w.target0_work_en().bit(enable), + 1 => w.target1_work_en().bit(enable), + 2 => w.target2_work_en().bit(enable), + _ => unreachable!(), + }); + } - #[cfg(esp32s2)] - systimer.step().write(|w| w.xtal_step().bits(0x1)); // run at XTAL freq, not 80 * XTAL freq + /// Enables/disables the comparator. If enabled, this means + /// it will generate interrupt based on its configuration. + #[cfg(esp32s2)] + pub fn set_enable(&self, enable: bool) { + let tconf = unsafe { + let systimer = &*SYSTIMER::ptr(); + systimer.target_conf(CHANNEL as usize) + }; + tconf.modify(|_r, w| w.work_en().bit(enable)); + } - #[cfg(not(esp32s2))] - { - tconf.write(|w| w.timer_unit_sel().clear_bit()); // default, use unit 0 - systimer - .conf() - .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit()); + /// Returns true if the comparator has been enabled. This means + /// it will generate interrupt based on its configuration. + pub fn is_enabled(&self) -> bool { + #[cfg(not(esp32s2))] + { + let systimer = unsafe { &*SYSTIMER::ptr() }; + let conf = systimer.conf().read(); + match CHANNEL { + 0 => conf.target0_work_en().bit(), + 1 => conf.target1_work_en().bit(), + 2 => conf.target2_work_en().bit(), + _ => unreachable!(), } + } - conf(tconf, target); + #[cfg(esp32s2)] + { + let tconf = unsafe { + let systimer = &*SYSTIMER::ptr(); + systimer.target_conf(CHANNEL as usize) + }; + tconf.read().work_en().bit() + } + } + /// Sets the unit this comparator uses as a reference count. + #[cfg(not(esp32s2))] + pub fn set_unit(&self, is_unit0: bool) { + let tconf = unsafe { + let systimer = &*SYSTIMER::ptr(); + systimer.target_conf(CHANNEL as usize) + }; + tconf.modify(|_, w| w.timer_unit_sel().bit(is_unit0)); + } + + /// Set the mode of the comparator to be either target or periodic. + pub fn set_mode(&self, mode: ComparatorMode) { + let tconf = unsafe { + let systimer = &*SYSTIMER::ptr(); + systimer.target_conf(CHANNEL as usize) + }; + let is_period_mode = match mode { + ComparatorMode::Period => true, + ComparatorMode::Target => false, + }; + tconf.modify(|_, w| w.period_mode().bit(is_period_mode)); + } + + /// Get the current mode of the comparator, which is either target or + /// periodic. + pub fn get_mode(&self) -> ComparatorMode { + let tconf = unsafe { + let systimer = &*SYSTIMER::ptr(); + systimer.target_conf(CHANNEL as usize) + }; + if tconf.read().period_mode().bit() { + ComparatorMode::Period + } else { + ComparatorMode::Target + } + } + + /// Set how often the comparator should generate an interrupt when in + /// periodic mode. + pub fn set_period(&self, value: u32) { + unsafe { + let systimer = &*SYSTIMER::ptr(); + let tconf = systimer.target_conf(CHANNEL as usize); + tconf.modify(|_, w| w.period().bits(value)); #[cfg(not(esp32s2))] { - systimer - .comp_load(CHANNEL as usize) - .write(|w| w.load().set_bit()); - - systimer.conf().modify(|_r, w| match CHANNEL { - 0 => w.target0_work_en().set_bit(), - 1 => w.target1_work_en().set_bit(), - 2 => w.target2_work_en().set_bit(), - _ => unreachable!(), - }); + let comp_load = systimer.comp_load(CHANNEL as usize); + comp_load.write(|w| w.load().set_bit()); } + } + } - #[cfg(esp32s2)] - tconf.modify(|_r, w| w.work_en().set_bit()); + /// Set when the comparator should generate an interrupt in target mode. + pub fn set_target(&self, value: u64) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + let target = systimer.trgt(CHANNEL as usize); + target.hi().write(|w| w.hi().set((value >> 32) as u32)); + target + .lo() + .write(|w| w.lo().set((value & 0xFFFF_FFFF) as u32)); + #[cfg(not(esp32s2))] + { + let comp_load = systimer.comp_load(CHANNEL as usize); + comp_load.write(|w| w.load().set_bit()); } } - fn set_interrupt_handler_internal(&self, handler: InterruptHandler) { - match CHANNEL { - 0 => unsafe { - interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET0, handler.handler()); - unwrap!(interrupt::enable( - Interrupt::SYSTIMER_TARGET0, - handler.priority(), - )); - }, - 1 => unsafe { - interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET1, handler.handler()); - unwrap!(interrupt::enable( - Interrupt::SYSTIMER_TARGET1, - handler.priority(), - )); - }, - 2 => unsafe { - interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET2, handler.handler()); - unwrap!(interrupt::enable( - Interrupt::SYSTIMER_TARGET2, - handler.priority(), - )); - }, + /// Get the actual target value of the comparator. + pub fn get_actual_target(&self) -> u64 { + let target = unsafe { + let systimer = &*SYSTIMER::ptr(); + systimer.trgt(CHANNEL as usize) + }; + let hi = target.hi().read().hi().bits(); + let lo = target.lo().read().lo().bits(); + + ((hi as u64) << 32) | (lo as u64) + } + + /// Set the interrupt handler for this comparator. + pub fn set_interrupt_handler(&self, handler: InterruptHandler) { + let interrupt = match CHANNEL { + 0 => Interrupt::SYSTIMER_TARGET0, + 1 => Interrupt::SYSTIMER_TARGET1, + 2 => Interrupt::SYSTIMER_TARGET2, _ => unreachable!(), + }; + unsafe { + interrupt::bind_interrupt(interrupt, handler.handler()); } + unwrap!(interrupt::enable(interrupt, handler.priority())); } } -impl Alarm { - /// Set the interrupt handler for this alarm. - pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - self.set_interrupt_handler_internal(handler) +/// The configuration of a unit. +#[derive(Copy, Clone)] +pub enum UnitConfig { + /// Unit is not counting. + Disabled, + + /// Unit is counting unless the Cpu is stalled. + DisabledIfCpuIsStalled(Cpu), + + /// Unit is counting. + Enabled, +} + +/// The modes of a comparator. +#[derive(Copy, Clone)] +pub enum ComparatorMode { + /// The comparator will generate interrupts periodically. + Period, + + /// The comparator will generate an interrupt when the unit reaches the + /// target. + Target, +} + +impl Unit<'static, 0> { + /// Conjure a system timer unit out of thin air. + /// + /// # Safety + /// + /// Users must take care to ensure that only one reference to the unit is + /// in scope at any given time. + pub const unsafe fn conjure() -> Self { + Self(PhantomData) + } +} + +#[cfg(not(esp32s2))] +impl Unit<'static, 1> { + /// Conjure a system timer unit out of thin air. + /// + /// # Safety + /// + /// Users must take care to ensure that only one reference to the unit is + /// in scope at any given time. + pub const unsafe fn conjure() -> Self { + Self(PhantomData) } } -impl InterruptConfigurable for Alarm { +/// A unit whose value cannot be updated. +pub struct FrozenUnit<'d, const CHANNEL: u8>(&'d Unit<'d, CHANNEL>); + +impl<'d, const CHANNEL: u8> FrozenUnit<'d, CHANNEL> { + /// Creates a frozen unit. You will no longer be allowed + /// direct access to this unit until all the alarms created + /// from the unit are dropped. + pub fn new(unit: &'d mut Unit<'d, CHANNEL>) -> Self { + Self(unit) + } + + fn borrow(&self) -> &'d Unit<'d, CHANNEL> { + self.0 + } +} + +/// Alarms created from the System Timer peripheral. +pub struct SysTimerAlarms { + /// Alarm 0 + pub alarm0: Alarm<'static, MODE, DM, 0, 0>, + /// Alarm 1 + pub alarm1: Alarm<'static, MODE, DM, 1, 0>, + /// Alarm 2 + pub alarm2: Alarm<'static, MODE, DM, 2, 0>, + + /// Unit 1 + /// + /// Leftover unit which wasn't used to create the three alarms. + #[cfg(not(esp32s2))] + pub unit1: Unit<'static, 1>, +} + +/// A marker for a [Alarm] in target mode. +#[derive(Debug)] +pub struct Target; + +/// A marker for a [Alarm] in periodic mode. +#[derive(Debug)] +pub struct Periodic; + +/// A single alarm. +pub struct Alarm<'d, MODE, DM, const COMP: u8, const UNIT: u8> +where + DM: Mode, +{ + comparator: Comparator<'d, COMP>, + unit: &'d Unit<'d, UNIT>, + config: &'d Mutex>>>, + _pd: PhantomData<(MODE, DM)>, +} + +impl<'d, T, DM, const COMP: u8, const UNIT: u8> Debug for Alarm<'d, T, DM, COMP, UNIT> +where + DM: Mode, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Alarm") + .field("comparator", &COMP) + .field("unit", &UNIT) + .finish() + } +} + +impl<'d, T, const COMP: u8, const UNIT: u8> Alarm<'d, T, Blocking, COMP, UNIT> { + /// Creates a new alarm from a comparator and unit, in blocking mode. + pub fn new( + comparator: Comparator<'d, COMP>, + unit: &FrozenUnit<'d, UNIT>, + config: &'d Mutex>>>, + ) -> Self { + Self { + comparator, + unit: unit.borrow(), + config, + _pd: PhantomData, + } + } +} + +impl<'d, T, const COMP: u8, const UNIT: u8> Alarm<'d, T, Async, COMP, UNIT> { + /// Creates a new alarm from a comparator and unit, in async mode. + pub fn new_async( + comparator: Comparator<'d, COMP>, + unit: &FrozenUnit<'d, UNIT>, + config: &'d Mutex>>>, + ) -> Self { + Self { + comparator, + unit: unit.0, + config, + _pd: PhantomData, + } + } +} + +impl<'d, T, const COMP: u8, const UNIT: u8> InterruptConfigurable + for Alarm<'d, T, Blocking, COMP, UNIT> +{ fn set_interrupt_handler(&mut self, handler: InterruptHandler) { - self.set_interrupt_handler_internal(handler) + self.comparator.set_interrupt_handler(handler) } } -impl Alarm +impl<'d, DM, const COMP: u8, const UNIT: u8> Alarm<'d, Target, DM, COMP, UNIT> where DM: Mode, { /// Set the target value of this [Alarm] pub fn set_target(&self, timestamp: u64) { - self.configure(|tconf, target| unsafe { - tconf.write(|w| w.period_mode().clear_bit()); // target mode - target.hi().write(|w| w.hi().bits((timestamp >> 32) as u32)); - target - .lo() - .write(|w| w.lo().set((timestamp & 0xFFFF_FFFF) as u32)); + #[cfg(esp32s2)] + unsafe { + let systimer = &*SYSTIMER::ptr(); + // run at XTAL freq, not 80 * XTAL freq + systimer.step().write(|w| w.xtal_step().bits(0x1)); + } + + self.comparator.set_mode(ComparatorMode::Target); + self.comparator.set_target(timestamp); + #[cfg(not(esp32s2))] + critical_section::with(|cs| { + let config_cell = self.config.borrow(cs); + let mut config = config_cell.take().unwrap(); + self.comparator.set_enable(&mut config, true); + config_cell.set(Some(config)); }); + #[cfg(esp32s2)] + self.comparator.set_enable(true); } /// Block waiting until the timer reaches the `timestamp` @@ -291,123 +706,97 @@ where let r = unsafe { &*crate::peripherals::SYSTIMER::PTR }.int_raw(); loop { - if r.read().target(CHANNEL).bit_is_set() { + if r.read().target(COMP).bit_is_set() { break; } } } /// Converts this [Alarm] into [Periodic] mode - pub fn into_periodic(self) -> Alarm { - Alarm { _pd: PhantomData } + pub fn into_periodic(self) -> Alarm<'d, Periodic, DM, COMP, UNIT> { + Alarm { + comparator: self.comparator, + unit: self.unit, + config: self.config, + _pd: PhantomData, + } } } -impl Alarm +impl<'d, DM, const COMP: u8, const UNIT: u8> Alarm<'d, Periodic, DM, COMP, UNIT> where DM: Mode, { /// Set the period of this [Alarm] pub fn set_period(&self, period: MicrosDurationU32) { + #[cfg(esp32s2)] + unsafe { + let systimer = &*SYSTIMER::ptr(); + // run at XTAL freq, not 80 * XTAL freq + systimer.step().write(|w| w.xtal_step().bits(0x1)); + } + let us = period.ticks(); let ticks = us * (SystemTimer::TICKS_PER_SECOND / 1_000_000) as u32; - self.configure(|tconf, target| { - tconf.write(|w| unsafe { w.period_mode().set_bit().period().bits(ticks) }); - target.hi().write(|w| w.hi().set(0)); - target.lo().write(|w| w.lo().set(0)); + self.comparator.set_mode(ComparatorMode::Period); + self.comparator.set_period(ticks); + + #[cfg(not(esp32s2))] + critical_section::with(|cs| { + let config_cell = self.config.borrow(cs); + let mut config = config_cell.take().unwrap(); + self.comparator.set_enable(&mut config, true); + config_cell.set(Some(config)); }); + #[cfg(esp32s2)] + self.comparator.set_enable(true); } /// Converts this [Alarm] into [Target] mode - pub fn into_target(self) -> Alarm { - Alarm { _pd: PhantomData } - } -} - -impl Alarm -where - DM: Mode, -{ - /// Conjure an alarm out of thin air. - /// - /// # Safety - /// - /// Users must take care to ensure that only one reference to the timer is - /// in scope at any given time. - pub const unsafe fn conjure() -> Self { - Self { _pd: PhantomData } + pub fn into_target(self) -> Alarm<'d, Target, DM, COMP, UNIT> { + Alarm { + comparator: self.comparator, + unit: self.unit, + config: self.config, + _pd: PhantomData, + } } } -impl Alarm +impl<'d, T, DM, const COMP: u8, const UNIT: u8> crate::private::Sealed + for Alarm<'d, T, DM, COMP, UNIT> where DM: Mode, { - /// Conjure an alarm out of thin air. - /// - /// # Safety - /// - /// Users must take care to ensure that only one reference to the timer is - /// in scope at any given time. - pub const unsafe fn conjure() -> Self { - Self { _pd: PhantomData } - } } -impl Alarm -where - DM: Mode, -{ - /// Conjure an alarm out of thin air. - /// - /// # Safety - /// - /// Users must take care to ensure that only one reference to the timer is - /// in scope at any given time. - pub const unsafe fn conjure() -> Self { - Self { _pd: PhantomData } - } -} - -impl crate::private::Sealed for Alarm where DM: Mode {} - -impl super::Timer for Alarm +impl<'d, T, DM, const COMP: u8, const UNIT: u8> super::Timer for Alarm<'d, T, DM, COMP, UNIT> where DM: Mode, { fn start(&self) { - let systimer = unsafe { &*SYSTIMER::PTR }; - - #[cfg(esp32s2)] - systimer - .target_conf(CHANNEL as usize) - .modify(|_, w| w.work_en().set_bit()); - #[cfg(not(esp32s2))] - systimer.conf().modify(|_, w| match CHANNEL { - 0 => w.target0_work_en().set_bit(), - 1 => w.target1_work_en().set_bit(), - 2 => w.target2_work_en().set_bit(), - _ => unreachable!(), + critical_section::with(|cs| { + let config_cell = self.config.borrow(cs); + let mut config = config_cell.take().unwrap(); + self.comparator.set_enable(&mut config, true); + config_cell.set(Some(config)); }); + #[cfg(esp32s2)] + self.comparator.set_enable(true); } fn stop(&self) { - let systimer = unsafe { &*SYSTIMER::PTR }; - - #[cfg(esp32s2)] - systimer - .target_conf(CHANNEL as usize) - .modify(|_, w| w.work_en().clear_bit()); - #[cfg(not(esp32s2))] - systimer.conf().modify(|_, w| match CHANNEL { - 0 => w.target0_work_en().clear_bit(), - 1 => w.target1_work_en().clear_bit(), - 2 => w.target2_work_en().clear_bit(), - _ => unreachable!(), + critical_section::with(|cs| { + let config_cell = self.config.borrow(cs); + let mut config = config_cell.take().unwrap(); + self.comparator.set_enable(&mut config, false); + config_cell.set(Some(config)); }); + #[cfg(esp32s2)] + self.comparator.set_enable(false); } fn reset(&self) { @@ -421,9 +810,6 @@ where #[cfg(not(esp32s2))] { - systimer - .target_conf(CHANNEL as usize) - .modify(|_, w| w.timer_unit_sel().clear_bit()); // default, use unit 0 systimer .conf() .modify(|_, w| w.timer_unit0_core0_stall_en().clear_bit()); @@ -431,59 +817,33 @@ where } fn is_running(&self) -> bool { - let systimer = unsafe { &*SYSTIMER::PTR }; - - #[cfg(esp32s2)] - { - systimer - .target_conf(CHANNEL as usize) - .read() - .work_en() - .bit_is_set() - } - - #[cfg(not(esp32s2))] - match CHANNEL { - 0 => systimer.conf().read().target0_work_en().bit_is_set(), - 1 => systimer.conf().read().target1_work_en().bit_is_set(), - 2 => systimer.conf().read().target2_work_en().bit_is_set(), - _ => unreachable!(), - } + self.comparator.is_enabled() } fn now(&self) -> Instant { // This should be safe to access from multiple contexts; worst case // scenario the second accessor ends up reading an older time stamp. - let systimer = unsafe { &*SYSTIMER::PTR }; + self.unit.update(); - systimer.unit0_op().modify(|_, w| w.update().set_bit()); - while !systimer.unit0_op().read().value_valid().bit_is_set() { - // Wait - } - - let value_lo = systimer.unit0_value().lo().read().bits(); - let value_hi = systimer.unit0_value().hi().read().bits(); + let ticks = loop { + if let Some(value) = self.unit.poll_count() { + break value; + } + }; - let ticks = ((value_hi as u64) << 32) | value_lo as u64; let us = ticks / (SystemTimer::TICKS_PER_SECOND / 1_000_000); Instant::::from_ticks(us) } fn load_value(&self, value: MicrosDurationU64) -> Result<(), Error> { - let systimer = unsafe { &*SYSTIMER::PTR }; - - let auto_reload = systimer - .target_conf(CHANNEL as usize) - .read() - .period_mode() - .bit_is_set(); + let mode = self.comparator.get_mode(); let us = value.ticks(); let ticks = us * (SystemTimer::TICKS_PER_SECOND / 1_000_000); - if auto_reload { + if matches!(mode, ComparatorMode::Period) { // Period mode // The `SYSTIMER_TARGETx_PERIOD` field is 26-bits wide (or @@ -493,28 +853,17 @@ where return Err(Error::InvalidTimeout); } - systimer - .target_conf(CHANNEL as usize) - .modify(|_, w| unsafe { w.period().bits(ticks as u32) }); - - #[cfg(not(esp32s2))] - systimer - .comp_load(CHANNEL as usize) - .write(|w| w.load().set_bit()); + self.comparator.set_period(ticks as u32); // Clear and then set SYSTIMER_TARGETx_PERIOD_MODE to configure COMPx into // period mode - systimer - .target_conf(CHANNEL as usize) - .modify(|_, w| w.period_mode().clear_bit()); - systimer - .target_conf(CHANNEL as usize) - .modify(|_, w| w.period_mode().set_bit()); + self.comparator.set_mode(ComparatorMode::Target); + self.comparator.set_mode(ComparatorMode::Period); } else { // Target mode - systimer.unit0_op().modify(|_, w| w.update().set_bit()); - while !systimer.unit0_op().read().value_valid().bit_is_set() { + self.unit.update(); + while self.unit.poll_count().is_none() { // Wait for value registers to update } @@ -526,25 +875,10 @@ where return Err(Error::InvalidTimeout); } - let hi = systimer.unit0_value().hi().read().bits(); - let lo = systimer.unit0_value().lo().read().bits(); - - let v = (((hi & 0xF_FFFF) as u64) << 32) | lo as u64; + let v = self.unit.poll_count().unwrap(); let t = v + ticks; - systimer - .trgt(CHANNEL as usize) - .hi() - .write(|w| unsafe { w.hi().bits((t >> 32) as u32) }); - systimer - .trgt(CHANNEL as usize) - .lo() - .write(|w| unsafe { w.lo().bits(t as u32) }); - - #[cfg(not(esp32s2))] - systimer - .comp_load(CHANNEL as usize) - .write(|w| w.load().set_bit()); + self.comparator.set_target(t); } Ok(()) @@ -552,28 +886,31 @@ where fn enable_auto_reload(&self, auto_reload: bool) { // If `auto_reload` is true use Period Mode, otherwise use Target Mode: - unsafe { &*SYSTIMER::PTR } - .target_conf(CHANNEL as usize) - .modify(|_, w| w.period_mode().bit(auto_reload)); + let mode = if auto_reload { + ComparatorMode::Period + } else { + ComparatorMode::Target + }; + self.comparator.set_mode(mode) } fn enable_interrupt(&self, state: bool) { unsafe { &*SYSTIMER::PTR } .int_ena() - .modify(|_, w| w.target(CHANNEL).bit(state)); + .modify(|_, w| w.target(COMP).bit(state)); } fn clear_interrupt(&self) { unsafe { &*SYSTIMER::PTR } .int_clr() - .write(|w| w.target(CHANNEL).clear_bit_by_one()); + .write(|w| w.target(COMP).clear_bit_by_one()); } fn is_interrupt_set(&self) -> bool { unsafe { &*SYSTIMER::PTR } .int_raw() .read() - .target(CHANNEL) + .target(COMP) .bit_is_set() } @@ -582,11 +919,11 @@ where } fn set_interrupt_handler(&self, handler: InterruptHandler) { - Alarm::set_interrupt_handler_internal(self, handler); + self.comparator.set_interrupt_handler(handler); } } -impl Peripheral for Alarm +impl<'d, T, DM, const COMP: u8, const UNIT: u8> Peripheral for Alarm<'d, T, DM, COMP, UNIT> where DM: Mode, { @@ -617,15 +954,15 @@ mod asynch { const INIT: AtomicWaker = AtomicWaker::new(); static WAKERS: [AtomicWaker; NUM_ALARMS] = [INIT; NUM_ALARMS]; - pub(crate) struct AlarmFuture<'a, const N: u8> { - phantom: PhantomData<&'a Alarm>, + pub(crate) struct AlarmFuture<'a, const COMP: u8, const UNIT: u8> { + phantom: PhantomData<&'a Alarm<'a, Periodic, crate::Async, COMP, UNIT>>, } - impl<'a, const N: u8> AlarmFuture<'a, N> { - pub(crate) fn new(alarm: &'a Alarm) -> Self { + impl<'a, const COMP: u8, const UNIT: u8> AlarmFuture<'a, COMP, UNIT> { + pub(crate) fn new(alarm: &'a Alarm) -> Self { alarm.clear_interrupt(); - let (interrupt, handler) = match N { + let (interrupt, handler) = match COMP { 0 => (Interrupt::SYSTIMER_TARGET0, target0_handler), 1 => (Interrupt::SYSTIMER_TARGET1, target1_handler), _ => (Interrupt::SYSTIMER_TARGET2, target2_handler), @@ -647,16 +984,16 @@ mod asynch { unsafe { &*crate::peripherals::SYSTIMER::PTR } .int_ena() .read() - .target(N) + .target(COMP) .bit_is_clear() } } - impl<'a, const N: u8> core::future::Future for AlarmFuture<'a, N> { + impl<'a, const COMP: u8, const UNIT: u8> core::future::Future for AlarmFuture<'a, COMP, UNIT> { type Output = (); fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll { - WAKERS[N as usize].register(ctx.waker()); + WAKERS[COMP as usize].register(ctx.waker()); if self.event_bit_is_clear() { Poll::Ready(()) @@ -666,8 +1003,8 @@ mod asynch { } } - impl embedded_hal_async::delay::DelayNs - for Alarm + impl<'d, const COMP: u8, const UNIT: u8> embedded_hal_async::delay::DelayNs + for Alarm<'d, Periodic, crate::Async, COMP, UNIT> { async fn delay_ns(&mut self, ns: u32) { let period = MicrosDurationU32::from_ticks(ns / 1000); @@ -731,7 +1068,8 @@ pub mod etm { //! # use esp_hal::timer::systimer::{etm::SysTimerEtmEvent, SystemTimer}; //! # use fugit::ExtU32; //! let syst = SystemTimer::new(peripherals.SYSTIMER); - //! let mut alarm0 = syst.alarm0.into_periodic(); + //! let syst_alarms = syst.split(); + //! let mut alarm0 = syst_alarms.alarm0.into_periodic(); //! alarm0.set_period(1.secs()); //! //! let timer_event = SysTimerEtmEvent::new(&mut alarm0); @@ -741,31 +1079,33 @@ pub mod etm { use super::*; /// An ETM controlled SYSTIMER event - pub struct SysTimerEtmEvent<'a, M, DM: crate::Mode, const N: u8> { - alarm: &'a mut Alarm, + pub struct SysTimerEtmEvent<'a, 'd, M, DM: crate::Mode, const COMP: u8> { + alarm: &'a mut Alarm<'d, M, DM, COMP, 0>, } - impl<'a, M, DM: crate::Mode, const N: u8> SysTimerEtmEvent<'a, M, DM, N> { + impl<'a, 'd, M, DM: crate::Mode, const COMP: u8> SysTimerEtmEvent<'a, 'd, M, DM, COMP> { /// Creates an ETM event from the given [Alarm] - pub fn new(alarm: &'a mut Alarm) -> Self { + pub fn new(alarm: &'a mut Alarm<'d, M, DM, COMP, 0>) -> Self { Self { alarm } } /// Execute closure f with mutable access to the wrapped [Alarm]. - pub fn with(&self, f: impl FnOnce(&&'a mut Alarm) -> R) -> R { + pub fn with(&self, f: impl FnOnce(&&'a mut Alarm<'d, M, DM, COMP, 0>) -> R) -> R { let alarm = &self.alarm; f(alarm) } } - impl<'a, M, DM: crate::Mode, const N: u8> crate::private::Sealed - for SysTimerEtmEvent<'a, M, DM, N> + impl<'a, 'd, M, DM: crate::Mode, const COMP: u8> crate::private::Sealed + for SysTimerEtmEvent<'a, 'd, M, DM, COMP> { } - impl<'a, M, DM: crate::Mode, const N: u8> crate::etm::EtmEvent for SysTimerEtmEvent<'a, M, DM, N> { + impl<'a, 'd, M, DM: crate::Mode, const COMP: u8> crate::etm::EtmEvent + for SysTimerEtmEvent<'a, 'd, M, DM, COMP> + { fn id(&self) -> u8 { - 50 + N + 50 + COMP } } diff --git a/examples/src/bin/etm_blinky_systimer.rs b/examples/src/bin/etm_blinky_systimer.rs index b72ea29ea43..7d89cb391ac 100644 --- a/examples/src/bin/etm_blinky_systimer.rs +++ b/examples/src/bin/etm_blinky_systimer.rs @@ -28,7 +28,8 @@ fn main() -> ! { let peripherals = Peripherals::take(); let syst = SystemTimer::new(peripherals.SYSTIMER); - let mut alarm0 = syst.alarm0.into_periodic(); + let syst_alarms = syst.split(); + let mut alarm0 = syst_alarms.alarm0.into_periodic(); alarm0.set_period(1u32.secs()); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/systimer.rs b/examples/src/bin/systimer.rs index 8c738033ac5..650d84c773a 100644 --- a/examples/src/bin/systimer.rs +++ b/examples/src/bin/systimer.rs @@ -7,7 +7,7 @@ #![no_std] #![no_main] -use core::cell::RefCell; +use core::cell::{Cell, RefCell}; use critical_section::Mutex; use esp_backtrace as _; @@ -18,16 +18,19 @@ use esp_hal::{ peripherals::{Interrupt, Peripherals}, prelude::*, system::SystemControl, - timer::systimer::{Alarm, Periodic, SystemTimer, Target}, + timer::systimer::{Alarm, Config, FrozenUnit, Periodic, SystemTimer, Target, Unit}, Blocking, }; use esp_println::println; use fugit::ExtU32; +use static_cell::StaticCell; -static ALARM0: Mutex>>> = +static ALARM0: Mutex>>> = + Mutex::new(RefCell::new(None)); +static ALARM1: Mutex>>> = + Mutex::new(RefCell::new(None)); +static ALARM2: Mutex>>> = Mutex::new(RefCell::new(None)); -static ALARM1: Mutex>>> = Mutex::new(RefCell::new(None)); -static ALARM2: Mutex>>> = Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { @@ -38,18 +41,28 @@ fn main() -> ! { let systimer = SystemTimer::new(peripherals.SYSTIMER); println!("SYSTIMER Current value = {}", SystemTimer::now()); + static CONFIG: Mutex>> = Mutex::new(Cell::new(None)); + static UNIT0: StaticCell> = StaticCell::new(); + + let unit0 = UNIT0.init(systimer.unit0); + critical_section::with(|cs| CONFIG.borrow(cs).set(Some(systimer.config))); + + let frozen_unit = FrozenUnit::new(unit0); + + let alarm0 = Alarm::new(systimer.comparator0, &frozen_unit, &CONFIG); + let alarm1 = Alarm::new(systimer.comparator1, &frozen_unit, &CONFIG); + let alarm2 = Alarm::new(systimer.comparator2, &frozen_unit, &CONFIG); + critical_section::with(|cs| { - let alarm0 = systimer.alarm0.into_periodic(); + let alarm0 = alarm0.into_periodic(); alarm0.set_interrupt_handler(systimer_target0); alarm0.set_period(1u32.secs()); alarm0.enable_interrupt(true); - let alarm1 = systimer.alarm1; alarm1.set_interrupt_handler(systimer_target1); alarm1.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 2)); alarm1.enable_interrupt(true); - let alarm2 = systimer.alarm2; alarm2.set_interrupt_handler(systimer_target2); alarm2.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 3)); alarm2.enable_interrupt(true); diff --git a/examples/src/bin/wifi_embassy_access_point.rs b/examples/src/bin/wifi_embassy_access_point.rs index 9d1f9f1c800..16a4edd1aa8 100644 --- a/examples/src/bin/wifi_embassy_access_point.rs +++ b/examples/src/bin/wifi_embassy_access_point.rs @@ -96,7 +96,8 @@ async fn main(spawner: Spawner) -> ! { #[cfg(not(feature = "esp32"))] { - let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER); + let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER) + .split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timers = [OneShotTimer::new(alarm0)]; let timers = mk_static!([OneShotTimer; 1], timers); diff --git a/examples/src/bin/wifi_embassy_access_point_with_sta.rs b/examples/src/bin/wifi_embassy_access_point_with_sta.rs index 360a2d60a0e..b7fdb2b9bf7 100644 --- a/examples/src/bin/wifi_embassy_access_point_with_sta.rs +++ b/examples/src/bin/wifi_embassy_access_point_with_sta.rs @@ -104,7 +104,8 @@ async fn main(spawner: Spawner) -> ! { #[cfg(not(feature = "esp32"))] { - let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER); + let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER) + .split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timers = [OneShotTimer::new(alarm0)]; let timers = mk_static!([OneShotTimer; 1], timers); diff --git a/examples/src/bin/wifi_embassy_bench.rs b/examples/src/bin/wifi_embassy_bench.rs index bebb4795695..09f306c5fad 100644 --- a/examples/src/bin/wifi_embassy_bench.rs +++ b/examples/src/bin/wifi_embassy_bench.rs @@ -108,7 +108,8 @@ async fn main(spawner: Spawner) -> ! { #[cfg(not(feature = "esp32"))] { - let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER); + let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER) + .split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timers = [OneShotTimer::new(alarm0)]; let timers = mk_static!([OneShotTimer; 1], timers); diff --git a/examples/src/bin/wifi_embassy_ble.rs b/examples/src/bin/wifi_embassy_ble.rs index 606e18eda28..76eb5d2fffa 100644 --- a/examples/src/bin/wifi_embassy_ble.rs +++ b/examples/src/bin/wifi_embassy_ble.rs @@ -91,7 +91,8 @@ async fn main(_spawner: Spawner) -> ! { #[cfg(not(feature = "esp32"))] { - let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER); + let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER) + .split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timers = [OneShotTimer::new(alarm0)]; let timers = mk_static!([OneShotTimer; 1], timers); diff --git a/examples/src/bin/wifi_embassy_dhcp.rs b/examples/src/bin/wifi_embassy_dhcp.rs index 66636de046a..6e72eb7af49 100644 --- a/examples/src/bin/wifi_embassy_dhcp.rs +++ b/examples/src/bin/wifi_embassy_dhcp.rs @@ -89,7 +89,8 @@ async fn main(spawner: Spawner) -> ! { #[cfg(not(feature = "esp32"))] { - let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER); + let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER) + .split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timers = [OneShotTimer::new(alarm0)]; let timers = mk_static!([OneShotTimer; 1], timers); diff --git a/examples/src/bin/wifi_embassy_esp_now.rs b/examples/src/bin/wifi_embassy_esp_now.rs index c3d42f881de..2d30dda13d0 100644 --- a/examples/src/bin/wifi_embassy_esp_now.rs +++ b/examples/src/bin/wifi_embassy_esp_now.rs @@ -75,7 +75,8 @@ async fn main(_spawner: Spawner) -> ! { #[cfg(not(feature = "esp32"))] { - let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER); + let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER) + .split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timers = [OneShotTimer::new(alarm0)]; let timers = mk_static!([OneShotTimer; 1], timers); diff --git a/examples/src/bin/wifi_embassy_esp_now_duplex.rs b/examples/src/bin/wifi_embassy_esp_now_duplex.rs index 5ef0efe17fe..f03d7428730 100644 --- a/examples/src/bin/wifi_embassy_esp_now_duplex.rs +++ b/examples/src/bin/wifi_embassy_esp_now_duplex.rs @@ -75,7 +75,8 @@ async fn main(spawner: Spawner) -> ! { #[cfg(not(feature = "esp32"))] { - let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER); + let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER) + .split::(); let alarm0: ErasedTimer = systimer.alarm0.into(); let timers = [OneShotTimer::new(alarm0)]; let timers = mk_static!([OneShotTimer; 1], timers);