diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index c171d65bf..6c42c8afc 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -49,6 +49,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Runtime ISR binding for SHA,ECC and RSA (#1354) - Runtime ISR binding for I2C (#1376) - `UsbSerialJtag` can be created in async or blocking mode. The blocking constructor takes an optional interrupt handler argument (#1377) +- SYSTIMER and TIMG instances can now be created in async or blocking mode. The blocking constructor takes an optional argument to set interrupt handlers. The constructors are named `create`/`create_async` (#1348) +- SYSTIMER and TIMG instances can now be created in async or blocking mode (#1348) ### Removed diff --git a/esp-hal/src/embassy/time_driver_systimer.rs b/esp-hal/src/embassy/time_driver_systimer.rs index 9fe293b6d..ec93e343d 100644 --- a/esp-hal/src/embassy/time_driver_systimer.rs +++ b/esp-hal/src/embassy/time_driver_systimer.rs @@ -1,4 +1,5 @@ use critical_section::{CriticalSection, Mutex}; +use procmacros::handler; use super::AlarmState; use crate::{ @@ -9,22 +10,22 @@ use crate::{ pub const ALARM_COUNT: usize = 3; -pub type TimerType = SystemTimer<'static>; +pub type TimerType = SystemTimer<'static, crate::Async>; pub struct EmbassyTimer { pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>, - pub(crate) alarm0: Alarm, - pub(crate) alarm1: Alarm, - pub(crate) alarm2: Alarm, + pub(crate) alarm0: Alarm, + pub(crate) alarm1: Alarm, + pub(crate) alarm2: Alarm, } const ALARM_STATE_NONE: AlarmState = AlarmState::new(); embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer { alarms: Mutex::new([ALARM_STATE_NONE; ALARM_COUNT]), - alarm0: unsafe { Alarm::<_, 0>::conjure() }, - alarm1: unsafe { Alarm::<_, 1>::conjure() }, - alarm2: unsafe { Alarm::<_, 2>::conjure() }, + alarm0: unsafe { Alarm::<_, crate::Async, 0>::conjure() }, + alarm1: unsafe { Alarm::<_, crate::Async, 1>::conjure() }, + alarm2: unsafe { Alarm::<_, crate::Async, 2>::conjure() }, }); impl EmbassyTimer { @@ -42,9 +43,9 @@ impl EmbassyTimer { pub(super) fn on_alarm_allocated(&self, n: usize) { match n { - 0 => self.alarm0.enable_interrupt(true), - 1 => self.alarm1.enable_interrupt(true), - 2 => self.alarm2.enable_interrupt(true), + 0 => self.alarm0.enable_interrupt_internal(true), + 1 => self.alarm1.enable_interrupt_internal(true), + 2 => self.alarm2.enable_interrupt_internal(true), _ => {} } } @@ -57,31 +58,47 @@ impl EmbassyTimer { } pub fn init(_clocks: &Clocks, _systimer: TimerType) { - use crate::{interrupt, interrupt::Priority, macros::interrupt}; + unsafe { + crate::interrupt::bind_interrupt( + peripherals::Interrupt::SYSTIMER_TARGET0, + target0_handler.handler(), + ); + unwrap!(crate::interrupt::enable( + peripherals::Interrupt::SYSTIMER_TARGET0, + target0_handler.priority() + )); - unwrap!(interrupt::enable( - peripherals::Interrupt::SYSTIMER_TARGET0, - Priority::max() - )); - unwrap!(interrupt::enable( - peripherals::Interrupt::SYSTIMER_TARGET1, - Priority::max() - )); - unwrap!(interrupt::enable( - peripherals::Interrupt::SYSTIMER_TARGET2, - Priority::max() - )); + crate::interrupt::bind_interrupt( + peripherals::Interrupt::SYSTIMER_TARGET1, + target1_handler.handler(), + ); + unwrap!(crate::interrupt::enable( + peripherals::Interrupt::SYSTIMER_TARGET1, + target1_handler.priority() + )); - #[interrupt] - fn SYSTIMER_TARGET0() { + crate::interrupt::bind_interrupt( + peripherals::Interrupt::SYSTIMER_TARGET2, + target2_handler.handler(), + ); + unwrap!(crate::interrupt::enable( + peripherals::Interrupt::SYSTIMER_TARGET2, + target2_handler.priority() + )); + } + + #[handler] + fn target0_handler() { DRIVER.on_interrupt(0); } - #[interrupt] - fn SYSTIMER_TARGET1() { + + #[handler] + fn target1_handler() { DRIVER.on_interrupt(1); } - #[interrupt] - fn SYSTIMER_TARGET2() { + + #[handler] + fn target2_handler() { DRIVER.on_interrupt(2); } } @@ -109,9 +126,9 @@ impl EmbassyTimer { fn clear_interrupt(&self, id: usize) { match id { - 0 => self.alarm0.clear_interrupt(), - 1 => self.alarm1.clear_interrupt(), - 2 => self.alarm2.clear_interrupt(), + 0 => self.alarm0.clear_interrupt_internal(), + 1 => self.alarm1.clear_interrupt_internal(), + 2 => self.alarm2.clear_interrupt_internal(), _ => {} } } diff --git a/esp-hal/src/embassy/time_driver_timg.rs b/esp-hal/src/embassy/time_driver_timg.rs index e0df9fe8a..6af43d990 100644 --- a/esp-hal/src/embassy/time_driver_timg.rs +++ b/esp-hal/src/embassy/time_driver_timg.rs @@ -16,7 +16,7 @@ pub const ALARM_COUNT: usize = 1; #[cfg(any(esp32, esp32s2, esp32s3))] pub const ALARM_COUNT: usize = 2; -pub type TimerType = TimerGroup<'static, TIMG0>; +pub type TimerType = TimerGroup<'static, TIMG0, crate::Async>; pub struct EmbassyTimer { pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>, @@ -51,8 +51,6 @@ impl EmbassyTimer { } pub fn init(clocks: &Clocks, mut timer: TimerType) { - use crate::{interrupt, interrupt::Priority}; - // set divider to get a 1mhz clock. APB (80mhz) / 80 = 1mhz... // TODO: assert APB clock is the source and its at the correct speed for the // divider @@ -65,25 +63,39 @@ impl EmbassyTimer { timer.timer1.set_counter_active(true); } - unwrap!(interrupt::enable( - peripherals::Interrupt::TG0_T0_LEVEL, - Priority::max() - )); + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG0_T0_LEVEL, + tg0_t0_level.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG0_T0_LEVEL, + tg0_t0_level.priority(), + ) + .unwrap(); + } #[cfg(any(esp32, esp32s2, esp32s3))] - unwrap!(interrupt::enable( - peripherals::Interrupt::TG0_T1_LEVEL, - Priority::max() - )); + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG0_T1_LEVEL, + tg0_t1_level.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG0_T1_LEVEL, + tg0_t1_level.priority(), + ) + .unwrap(); + } - #[interrupt] - fn TG0_T0_LEVEL() { + #[handler(priority = crate::interrupt::Priority::max())] + fn tg0_t0_level() { let timer = unsafe { Timer0::::steal() }; DRIVER.on_interrupt(0, timer); } #[cfg(any(esp32, esp32s2, esp32s3))] - #[interrupt] - fn TG0_T1_LEVEL() { + #[handler(priority = crate::interrupt::Priority::max())] + fn tg0_t1_level() { let timer = unsafe { Timer1::::steal() }; DRIVER.on_interrupt(1, timer); } diff --git a/esp-hal/src/soc/esp32/mod.rs b/esp-hal/src/soc/esp32/mod.rs index 18861d524..3ea1b95d9 100644 --- a/esp-hal/src/soc/esp32/mod.rs +++ b/esp-hal/src/soc/esp32/mod.rs @@ -96,6 +96,6 @@ unsafe fn post_init() { let mut rtc = Rtc::new(LPWR::steal()); rtc.rwdt.disable(); - Wdt::::set_wdt_enabled(false); - Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); } diff --git a/esp-hal/src/soc/esp32c2/mod.rs b/esp-hal/src/soc/esp32c2/mod.rs index 808fc0421..a26ebcb19 100644 --- a/esp-hal/src/soc/esp32c2/mod.rs +++ b/esp-hal/src/soc/esp32c2/mod.rs @@ -31,5 +31,5 @@ unsafe fn post_init() { rtc.swd.disable(); rtc.rwdt.disable(); - Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); } diff --git a/esp-hal/src/soc/esp32c3/mod.rs b/esp-hal/src/soc/esp32c3/mod.rs index 41c58ddd3..36119240a 100644 --- a/esp-hal/src/soc/esp32c3/mod.rs +++ b/esp-hal/src/soc/esp32c3/mod.rs @@ -43,6 +43,6 @@ unsafe fn post_init() { rtc.swd.disable(); rtc.rwdt.disable(); - Wdt::::set_wdt_enabled(false); - Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); } diff --git a/esp-hal/src/soc/esp32c6/mod.rs b/esp-hal/src/soc/esp32c6/mod.rs index 96e22cf7c..ff722aa6c 100644 --- a/esp-hal/src/soc/esp32c6/mod.rs +++ b/esp-hal/src/soc/esp32c6/mod.rs @@ -49,6 +49,6 @@ unsafe fn post_init() { rtc.swd.disable(); rtc.rwdt.disable(); - Wdt::::set_wdt_enabled(false); - Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); } diff --git a/esp-hal/src/soc/esp32h2/mod.rs b/esp-hal/src/soc/esp32h2/mod.rs index 9fd954003..cddfd2ec9 100644 --- a/esp-hal/src/soc/esp32h2/mod.rs +++ b/esp-hal/src/soc/esp32h2/mod.rs @@ -48,6 +48,6 @@ unsafe fn post_init() { rtc.swd.disable(); rtc.rwdt.disable(); - Wdt::::set_wdt_enabled(false); - Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); } diff --git a/esp-hal/src/soc/esp32s2/mod.rs b/esp-hal/src/soc/esp32s2/mod.rs index a38cc2dfd..b6f0bdab8 100644 --- a/esp-hal/src/soc/esp32s2/mod.rs +++ b/esp-hal/src/soc/esp32s2/mod.rs @@ -100,6 +100,6 @@ unsafe fn post_init() { let mut rtc = Rtc::new(LPWR::steal()); rtc.rwdt.disable(); - Wdt::::set_wdt_enabled(false); - Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); } diff --git a/esp-hal/src/soc/esp32s3/mod.rs b/esp-hal/src/soc/esp32s3/mod.rs index 98ffae6a8..d1e120f4d 100644 --- a/esp-hal/src/soc/esp32s3/mod.rs +++ b/esp-hal/src/soc/esp32s3/mod.rs @@ -134,6 +134,6 @@ unsafe fn post_init() { let mut rtc = Rtc::new(LPWR::steal()); rtc.rwdt.disable(); - Wdt::::set_wdt_enabled(false); - Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); + Wdt::::set_wdt_enabled(false); } diff --git a/esp-hal/src/systimer.rs b/esp-hal/src/systimer.rs index d3125cf57..4ff1a1e9a 100644 --- a/esp-hal/src/systimer.rs +++ b/esp-hal/src/systimer.rs @@ -31,7 +31,8 @@ use core::{marker::PhantomData, mem::transmute}; use fugit::MicrosDurationU32; use crate::{ - peripheral::{Peripheral, PeripheralRef}, + interrupt::InterruptHandler, + peripheral::Peripheral, peripherals::{ generic::Reg, systimer::{ @@ -45,42 +46,45 @@ use crate::{ // TODO this only handles unit0 of the systimer -pub struct SystemTimer<'d> { - _inner: PeripheralRef<'d, SYSTIMER>, - pub alarm0: Alarm, - pub alarm1: Alarm, - pub alarm2: Alarm, +/// The SystemTimer +pub struct SystemTimer<'d, DM: crate::Mode> { + pub alarm0: Alarm, + pub alarm1: Alarm, + pub alarm2: Alarm, + _phantom: &'d PhantomData<()>, } -impl<'d> SystemTimer<'d> { +impl<'d> SystemTimer<'d, crate::Blocking> { + /// Bitmask to be applied to the raw register value #[cfg(esp32s2)] pub const BIT_MASK: u64 = u64::MAX; #[cfg(not(esp32s2))] pub const BIT_MASK: u64 = 0xF_FFFF_FFFF_FFFF; + /// The ticks per second the underlying peripheral uses #[cfg(esp32s2)] pub const TICKS_PER_SECOND: u64 = 80_000_000; // TODO this can change when we have support for changing APB frequency #[cfg(not(esp32s2))] pub const TICKS_PER_SECOND: u64 = 16_000_000; - pub fn new(p: impl Peripheral

+ 'd) -> Self { - crate::into_ref!(p); - + /// Create a new instance in [crate::Blocking] mode. + pub fn new(_p: impl Peripheral

+ 'd) -> Self { #[cfg(soc_etm)] etm::enable_etm(); Self { - _inner: p, alarm0: Alarm::new(), alarm1: Alarm::new(), alarm2: Alarm::new(), + _phantom: &PhantomData, } } // TODO use fugit types + /// Get the current count of the system-timer. pub fn now() -> u64 { // This should be safe to access from multiple contexts - // worst case scenario the second accesor ends up reading + // worst case scenario the second accessor ends up reading // an older time stamp let systimer = unsafe { &*SYSTIMER::ptr() }; systimer @@ -101,43 +105,41 @@ impl<'d> SystemTimer<'d> { } } +impl<'d> SystemTimer<'d, crate::Async> { + /// Create a new instance in [crate::Async] mode. + pub fn new_async(_p: impl Peripheral

+ 'd) -> Self { + #[cfg(soc_etm)] + etm::enable_etm(); + + Self { + alarm0: Alarm::new(), + alarm1: Alarm::new(), + alarm2: Alarm::new(), + _phantom: &PhantomData, + } + } +} + +/// 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; // TODO, also impl e-h timer traits +/// A single alarm. #[derive(Debug)] -pub struct Alarm { - _pd: PhantomData, +pub struct Alarm { + _pd: PhantomData<(MODE, DM)>, } -impl Alarm { +impl Alarm { // private constructor fn new() -> Self { Self { _pd: PhantomData } } - pub fn enable_interrupt(&self, val: bool) { - let systimer = unsafe { &*SYSTIMER::ptr() }; - match CHANNEL { - 0 => systimer.int_ena().modify(|_, w| w.target0().bit(val)), - 1 => systimer.int_ena().modify(|_, w| w.target1().bit(val)), - 2 => systimer.int_ena().modify(|_, w| w.target2().bit(val)), - _ => unreachable!(), - } - } - - pub fn clear_interrupt(&self) { - let systimer = unsafe { &*SYSTIMER::ptr() }; - match CHANNEL { - 0 => systimer.int_clr().write(|w| w.target0().clear_bit_by_one()), - 1 => systimer.int_clr().write(|w| w.target1().clear_bit_by_one()), - 2 => systimer.int_clr().write(|w| w.target2().clear_bit_by_one()), - _ => unreachable!(), - } - } - fn configure( &self, conf: impl FnOnce(&Reg, &Reg, &Reg), @@ -212,9 +214,78 @@ impl Alarm { }); } } + + pub(crate) fn enable_interrupt_internal(&self, val: bool) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + match CHANNEL { + 0 => systimer.int_ena().modify(|_, w| w.target0().bit(val)), + 1 => systimer.int_ena().modify(|_, w| w.target1().bit(val)), + 2 => systimer.int_ena().modify(|_, w| w.target2().bit(val)), + _ => unreachable!(), + } + } + + pub(crate) fn clear_interrupt_internal(&self) { + let systimer = unsafe { &*SYSTIMER::ptr() }; + match CHANNEL { + 0 => systimer.int_clr().write(|w| w.target0().clear_bit_by_one()), + 1 => systimer.int_clr().write(|w| w.target1().clear_bit_by_one()), + 2 => systimer.int_clr().write(|w| w.target2().clear_bit_by_one()), + _ => unreachable!(), + } + } } -impl Alarm { +impl Alarm { + /// Set the interrupt handler for this alarm. + pub fn set_interrupt_handler(&self, handler: InterruptHandler) { + match CHANNEL { + 0 => unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::SYSTIMER_TARGET0, + handler.handler(), + ); + unwrap!(crate::interrupt::enable( + crate::peripherals::Interrupt::SYSTIMER_TARGET0, + handler.priority(), + )); + }, + 1 => unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::SYSTIMER_TARGET1, + handler.handler(), + ); + unwrap!(crate::interrupt::enable( + crate::peripherals::Interrupt::SYSTIMER_TARGET1, + handler.priority(), + )); + }, + 2 => unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::SYSTIMER_TARGET2, + handler.handler(), + ); + unwrap!(crate::interrupt::enable( + crate::peripherals::Interrupt::SYSTIMER_TARGET2, + handler.priority(), + )); + }, + _ => unreachable!(), + } + } + + /// Enable the interrupt for this alarm. + pub fn enable_interrupt(&self, val: bool) { + self.enable_interrupt_internal(val); + } + + /// Enable the interrupt pending status for this alarm. + pub fn clear_interrupt(&self) { + self.clear_interrupt_internal(); + } +} +impl Alarm { + /// Set the target value of this [Alarm] pub fn set_target(&self, timestamp: u64) { self.configure(|tconf, hi, lo| unsafe { tconf.write(|w| w.target0_period_mode().clear_bit()); // target mode @@ -223,12 +294,14 @@ impl Alarm { }) } - pub fn into_periodic(self) -> Alarm { + /// Converts this [Alarm] into [Periodic] mode + pub fn into_periodic(self) -> Alarm { Alarm { _pd: PhantomData } } } -impl Alarm { +impl Alarm { + /// Set the period of this [Alarm] pub fn set_period(&self, period: MicrosDurationU32) { let us = period.ticks(); let ticks = us * (SystemTimer::TICKS_PER_SECOND / 1_000_000) as u32; @@ -245,12 +318,13 @@ impl Alarm { }); } - pub fn into_target(self) -> Alarm { + /// Converts this [Alarm] into [Target] mode + pub fn into_target(self) -> Alarm { Alarm { _pd: PhantomData } } } -impl Alarm { +impl Alarm { /// Conjure an alarm out of thin air. /// /// # Safety @@ -262,7 +336,7 @@ impl Alarm { } } -impl Alarm { +impl Alarm { /// Conjure an alarm out of thin air. /// /// # Safety @@ -274,7 +348,7 @@ impl Alarm { } } -impl Alarm { +impl Alarm { /// Conjure an alarm out of thin air. /// /// # Safety @@ -286,13 +360,8 @@ impl Alarm { } } -// FIXME: The `embedded_hal_async::delay::DelayUs` trait implementation -// interferes with the embassy time driver, which also uses the -// `SYSTIMER` peripheral. Until we come up with a solution, do not -// implement this trait if the `embassy-time-systick` feature is enabled. -// #[cfg(all(feature = "async", not(feature = "embassy-time-systick")))] -// HACK: disable `asynch` module *always* until we come up with a solution -#[cfg(not(systimer))] +// Async functionality of the system timer. +#[cfg(feature = "async")] mod asynch { use core::{ pin::Pin, @@ -300,7 +369,7 @@ mod asynch { }; use embassy_sync::waitqueue::AtomicWaker; - use procmacros::interrupt; + use procmacros::handler; use super::*; @@ -310,13 +379,34 @@ mod asynch { static WAKERS: [AtomicWaker; NUM_ALARMS] = [INIT; NUM_ALARMS]; pub(crate) struct AlarmFuture<'a, const N: u8> { - phantom: PhantomData<&'a Alarm>, + phantom: PhantomData<&'a Alarm>, } impl<'a, const N: u8> AlarmFuture<'a, N> { - pub(crate) fn new(alarm: &'a Alarm) -> Self { - alarm.clear_interrupt(); - alarm.enable_interrupt(true); + pub(crate) fn new(alarm: &'a Alarm) -> Self { + alarm.clear_interrupt_internal(); + + let (interrupt, handler) = match N { + 0 => ( + crate::peripherals::Interrupt::SYSTIMER_TARGET0, + target0_handler, + ), + 1 => ( + crate::peripherals::Interrupt::SYSTIMER_TARGET1, + target1_handler, + ), + _ => ( + crate::peripherals::Interrupt::SYSTIMER_TARGET2, + target2_handler, + ), + }; + + unsafe { + crate::interrupt::bind_interrupt(interrupt, handler.handler()); + crate::interrupt::enable(interrupt, handler.priority()).unwrap(); + } + + alarm.enable_interrupt_internal(true); Self { phantom: PhantomData, @@ -325,7 +415,7 @@ mod asynch { fn event_bit_is_clear(&self) -> bool { let r = unsafe { &*crate::peripherals::SYSTIMER::PTR } - .int_ena + .int_ena() .read(); match N { @@ -351,9 +441,11 @@ mod asynch { } } - impl embedded_hal_async::delay::DelayUs for Alarm { - async fn delay_us(&mut self, us: u32) { - let period = MicrosDurationU32::from_ticks(us); + impl embedded_hal_async::delay::DelayNs + for Alarm + { + async fn delay_ns(&mut self, ns: u32) { + let period = MicrosDurationU32::from_ticks(ns / 1000); self.set_period(period); AlarmFuture::new(self).await; @@ -366,28 +458,28 @@ mod asynch { } } - #[interrupt] - fn SYSTIMER_TARGET0() { + #[handler] + fn target0_handler() { unsafe { &*crate::peripherals::SYSTIMER::PTR } - .int_ena + .int_ena() .modify(|_, w| w.target0().clear_bit()); WAKERS[0].wake(); } - #[interrupt] - fn SYSTIMER_TARGET1() { + #[handler] + fn target1_handler() { unsafe { &*crate::peripherals::SYSTIMER::PTR } - .int_ena + .int_ena() .modify(|_, w| w.target1().clear_bit()); WAKERS[1].wake(); } - #[interrupt] - fn SYSTIMER_TARGET2() { + #[handler] + fn target2_handler() { unsafe { &*crate::peripherals::SYSTIMER::PTR } - .int_ena + .int_ena() .modify(|_, w| w.target2().clear_bit()); WAKERS[2].wake(); @@ -420,26 +512,29 @@ pub mod etm { use super::*; /// An ETM controlled SYSTIMER event - pub struct SysTimerEtmEvent<'a, M, const N: u8> { - alarm: &'a mut Alarm, + pub struct SysTimerEtmEvent<'a, M, DM: crate::Mode, const N: u8> { + alarm: &'a mut Alarm, } - impl<'a, M, const N: u8> SysTimerEtmEvent<'a, M, N> { + impl<'a, M, DM: crate::Mode, const N: u8> SysTimerEtmEvent<'a, M, DM, N> { /// Creates an ETM event from the given [Alarm] - pub fn new(alarm: &'a mut Alarm) -> Self { + pub fn new(alarm: &'a mut Alarm) -> 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) -> R) -> R { let alarm = &self.alarm; f(alarm) } } - impl<'a, M, const N: u8> crate::private::Sealed for SysTimerEtmEvent<'a, M, N> {} + impl<'a, M, DM: crate::Mode, const N: u8> crate::private::Sealed + for SysTimerEtmEvent<'a, M, DM, N> + { + } - impl<'a, M, const N: u8> crate::etm::EtmEvent for SysTimerEtmEvent<'a, M, N> { + impl<'a, M, DM: crate::Mode, const N: u8> crate::etm::EtmEvent for SysTimerEtmEvent<'a, M, DM, N> { fn id(&self) -> u8 { 50 + N } diff --git a/esp-hal/src/timer.rs b/esp-hal/src/timer.rs index 92d787db3..2a5cfbba6 100644 --- a/esp-hal/src/timer.rs +++ b/esp-hal/src/timer.rs @@ -47,6 +47,7 @@ use crate::peripherals::TIMG1; use crate::soc::constants::TIMG_DEFAULT_CLK_SRC; use crate::{ clock::Clocks, + interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::{timg0::RegisterBlock, TIMG0}, system::PeripheralClockControl, @@ -61,17 +62,32 @@ pub enum Error { AlarmInactive, } +/// Interrupts which can be registered in [crate::Blocking] mode +#[derive(Debug, Default)] +pub struct TimerInterrupts { + pub timer0_t0: Option, + pub timer0_t1: Option, + pub timer0_wdt: Option, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + pub timer1_t0: Option, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + pub timer1_t1: Option, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + pub timer1_wdt: Option, +} + // A timergroup consisting of up to 2 timers (chip dependent) and a watchdog // timer -pub struct TimerGroup<'d, T> +pub struct TimerGroup<'d, T, DM> where T: TimerGroupInstance, + DM: crate::Mode, { _timer_group: PeripheralRef<'d, T>, - pub timer0: Timer>, + pub timer0: Timer, DM>, #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] - pub timer1: Timer>, - pub wdt: Wdt, + pub timer1: Timer, DM>, + pub wdt: Wdt, } pub trait TimerGroupInstance { @@ -181,11 +197,144 @@ impl TimerGroupInstance for TIMG1 { } } -impl<'d, T> TimerGroup<'d, T> +impl<'d, T> TimerGroup<'d, T, crate::Blocking> where T: TimerGroupInstance, { - pub fn new(timer_group: impl Peripheral

+ 'd, clocks: &Clocks) -> Self { + pub fn new( + timer_group: impl Peripheral

+ 'd, + clocks: &Clocks, + isr: Option, + ) -> Self { + crate::into_ref!(timer_group); + + T::configure_src_clk(); + + // ESP32-H2 is using PLL_48M_CLK source instead of APB_CLK + let timer0 = Timer::new( + Timer0 { + phantom: PhantomData, + }, + #[cfg(not(esp32h2))] + clocks.apb_clock, + #[cfg(esp32h2)] + clocks.pll_48m_clock, + ); + + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + let timer1 = Timer::new( + Timer1 { + phantom: PhantomData, + }, + clocks.apb_clock, + ); + + if let Some(isr) = isr { + if let Some(handler) = isr.timer0_t0 { + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG0_T0_LEVEL, + handler.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG0_T0_LEVEL, + handler.priority(), + ) + .unwrap(); + } + } + + #[cfg(any(esp32, esp32s2, esp32s3))] + if let Some(handler) = isr.timer0_t1 { + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG0_T1_LEVEL, + handler.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG0_T1_LEVEL, + handler.priority(), + ) + .unwrap(); + } + } + + if let Some(handler) = isr.timer0_wdt { + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG0_WDT_LEVEL, + handler.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG0_WDT_LEVEL, + handler.priority(), + ) + .unwrap(); + } + } + + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + { + if let Some(handler) = isr.timer1_t0 { + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG1_T0_LEVEL, + handler.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG1_T0_LEVEL, + handler.priority(), + ) + .unwrap(); + } + } + + #[cfg(any(esp32, esp32s2, esp32s3))] + if let Some(handler) = isr.timer1_t1 { + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG1_T1_LEVEL, + handler.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG1_T1_LEVEL, + handler.priority(), + ) + .unwrap(); + } + } + + if let Some(handler) = isr.timer1_wdt { + unsafe { + crate::interrupt::bind_interrupt( + crate::peripherals::Interrupt::TG1_WDT_LEVEL, + handler.handler(), + ); + crate::interrupt::enable( + crate::peripherals::Interrupt::TG1_WDT_LEVEL, + handler.priority(), + ) + .unwrap(); + } + } + } + } + + Self { + _timer_group: timer_group, + timer0, + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] + timer1, + wdt: Wdt::new(), + } + } +} + +impl<'d, T> TimerGroup<'d, T, crate::Async> +where + T: TimerGroupInstance, +{ + pub fn new_async(timer_group: impl Peripheral

+ 'd, clocks: &Clocks) -> Self { crate::into_ref!(timer_group); T::configure_src_clk(); @@ -220,12 +369,13 @@ where } /// General-purpose Timer driver -pub struct Timer { +pub struct Timer { timg: T, apb_clk_freq: HertzU32, + phantom: PhantomData, } -impl Timer +impl Timer where T: Instance, { @@ -236,7 +386,11 @@ where timg.enable_peripheral(); - Self { timg, apb_clk_freq } + Self { + timg, + apb_clk_freq, + phantom: PhantomData, + } } /// Start the timer with the given time period. @@ -278,14 +432,9 @@ where pub fn wait(&mut self) { while !self.has_elapsed() {} } - - /// Return the raw interface to the underlying timer instance - pub fn free(self) -> T { - self.timg - } } -impl Deref for Timer +impl Deref for Timer where T: Instance, { @@ -296,7 +445,7 @@ where } } -impl DerefMut for Timer +impl DerefMut for Timer where T: Instance, { @@ -531,9 +680,10 @@ where } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::timer::CountDown for Timer +impl embedded_hal_02::timer::CountDown for Timer where T: Instance, + DM: crate::Mode, { type Time = MicrosDurationU64; @@ -554,9 +704,10 @@ where } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::timer::Cancel for Timer +impl embedded_hal_02::timer::Cancel for Timer where T: Instance, + DM: crate::Mode, { type Error = Error; @@ -574,17 +725,23 @@ where } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::timer::Periodic for Timer where T: Instance {} +impl embedded_hal_02::timer::Periodic for Timer +where + T: Instance, + DM: crate::Mode, +{ +} /// Watchdog timer -pub struct Wdt { - phantom: PhantomData, +pub struct Wdt { + phantom: PhantomData<(TG, DM)>, } /// Watchdog driver -impl Wdt +impl Wdt where TG: TimerGroupInstance, + DM: crate::Mode, { /// Create a new watchdog timer instance pub fn new() -> Self { @@ -697,9 +854,10 @@ where } } -impl Default for Wdt +impl Default for Wdt where TG: TimerGroupInstance, + DM: crate::Mode, { fn default() -> Self { Self::new() @@ -707,9 +865,10 @@ where } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::watchdog::WatchdogDisable for Wdt +impl embedded_hal_02::watchdog::WatchdogDisable for Wdt where TG: TimerGroupInstance, + DM: crate::Mode, { fn disable(&mut self) { self.disable(); @@ -717,9 +876,10 @@ where } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::watchdog::WatchdogEnable for Wdt +impl embedded_hal_02::watchdog::WatchdogEnable for Wdt where TG: TimerGroupInstance, + DM: crate::Mode, { type Time = MicrosDurationU64; @@ -733,9 +893,10 @@ where } #[cfg(feature = "embedded-hal-02")] -impl embedded_hal_02::watchdog::Watchdog for Wdt +impl embedded_hal_02::watchdog::Watchdog for Wdt where TG: TimerGroupInstance, + DM: crate::Mode, { fn feed(&mut self) { self.feed(); diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 7821dd531..3886fe230 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -63,6 +63,7 @@ embassy = ["esp-hal/embassy"] embassy-executor-thread = ["esp-hal/embassy-executor-thread"] embassy-executor-interrupt = ["esp-hal/embassy-executor-interrupt"] +embassy-time-systick-16mhz = ["esp-hal/embassy-time-systick-16mhz"] embassy-time-timg0 = ["esp-hal/embassy-time-timg0"] embassy-generic-timers = ["embassy-time/generic-queue-8"] diff --git a/examples/src/bin/embassy_hello_world.rs b/examples/src/bin/embassy_hello_world.rs index 90c16e2e5..bd92de2fc 100644 --- a/examples/src/bin/embassy_hello_world.rs +++ b/examples/src/bin/embassy_hello_world.rs @@ -36,7 +36,7 @@ async fn main(spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); spawner.spawn(run()).ok(); diff --git a/examples/src/bin/embassy_hello_world_systimer.rs b/examples/src/bin/embassy_hello_world_systimer.rs new file mode 100644 index 000000000..d3ecb4f41 --- /dev/null +++ b/examples/src/bin/embassy_hello_world_systimer.rs @@ -0,0 +1,50 @@ +//! embassy hello world systimer +//! +//! This is an example of running the embassy executor with multiple tasks +//! concurrently using the systimer time driver. +//! +//! It's not supported on ESP32, on ESP32-S2 the frequency of the systimer is different (so it's left out here) + +//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s3 +//% FEATURES: embassy embassy-time-systick-16mhz embassy-executor-thread embassy-generic-timers + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Spawner; +use embassy_time::{Duration, Timer}; +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, + embassy, + peripherals::Peripherals, + prelude::*, + systimer::SystemTimer, +}; + +#[embassy_executor::task] +async fn run() { + loop { + esp_println::println!("Hello world from embassy using esp-hal-async!"); + Timer::after(Duration::from_millis(1_000)).await; + } +} + +#[main] +async fn main(spawner: Spawner) { + esp_println::println!("Init!"); + let peripherals = Peripherals::take(); + let system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let systimer = SystemTimer::new_async(peripherals.SYSTIMER); + embassy::init(&clocks, systimer); + + spawner.spawn(run()).ok(); + + loop { + esp_println::println!("Bing!"); + Timer::after(Duration::from_millis(5_000)).await; + } +} diff --git a/examples/src/bin/embassy_i2c.rs b/examples/src/bin/embassy_i2c.rs index 9932bc3bc..e83f398d0 100644 --- a/examples/src/bin/embassy_i2c.rs +++ b/examples/src/bin/embassy_i2c.rs @@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_i2s_read.rs b/examples/src/bin/embassy_i2s_read.rs index c3559d287..e5687d5d0 100644 --- a/examples/src/bin/embassy_i2s_read.rs +++ b/examples/src/bin/embassy_i2s_read.rs @@ -40,7 +40,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_i2s_sound.rs b/examples/src/bin/embassy_i2s_sound.rs index 6bc875ab4..24a782822 100644 --- a/examples/src/bin/embassy_i2s_sound.rs +++ b/examples/src/bin/embassy_i2s_sound.rs @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_multicore.rs b/examples/src/bin/embassy_multicore.rs index 4a2c11e37..ac4f068ee 100644 --- a/examples/src/bin/embassy_multicore.rs +++ b/examples/src/bin/embassy_multicore.rs @@ -57,7 +57,7 @@ async fn main(_spawner: Spawner) { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let mut cpu_control = CpuControl::new(system.cpu_control); diff --git a/examples/src/bin/embassy_multicore_interrupt.rs b/examples/src/bin/embassy_multicore_interrupt.rs index 93760e769..118f561fd 100644 --- a/examples/src/bin/embassy_multicore_interrupt.rs +++ b/examples/src/bin/embassy_multicore_interrupt.rs @@ -92,7 +92,7 @@ fn main() -> ! { let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let mut cpu_control = CpuControl::new(system.cpu_control); diff --git a/examples/src/bin/embassy_multiprio.rs b/examples/src/bin/embassy_multiprio.rs index ba26af899..51f480798 100644 --- a/examples/src/bin/embassy_multiprio.rs +++ b/examples/src/bin/embassy_multiprio.rs @@ -84,7 +84,7 @@ async fn main(low_prio_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let spawner = INT_EXECUTOR_0.start(Priority::Priority2); diff --git a/examples/src/bin/embassy_parl_io_rx.rs b/examples/src/bin/embassy_parl_io_rx.rs index 6115d4130..c700821b7 100644 --- a/examples/src/bin/embassy_parl_io_rx.rs +++ b/examples/src/bin/embassy_parl_io_rx.rs @@ -33,7 +33,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_parl_io_tx.rs b/examples/src/bin/embassy_parl_io_tx.rs index c0cff0cc0..aa6e4c9db 100644 --- a/examples/src/bin/embassy_parl_io_tx.rs +++ b/examples/src/bin/embassy_parl_io_tx.rs @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_rmt_rx.rs b/examples/src/bin/embassy_rmt_rx.rs index d5e6637e8..8ace5f8a8 100644 --- a/examples/src/bin/embassy_rmt_rx.rs +++ b/examples/src/bin/embassy_rmt_rx.rs @@ -45,7 +45,7 @@ async fn main(spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timer_group0 = esp_hal::timer::TimerGroup::new(peripherals.TIMG0, &clocks); + let timer_group0 = esp_hal::timer::TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timer_group0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_rmt_tx.rs b/examples/src/bin/embassy_rmt_tx.rs index ded064cb9..f7a8ec6f0 100644 --- a/examples/src/bin/embassy_rmt_tx.rs +++ b/examples/src/bin/embassy_rmt_tx.rs @@ -30,7 +30,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_serial.rs b/examples/src/bin/embassy_serial.rs index 2bfe840a7..87f8fae1f 100644 --- a/examples/src/bin/embassy_serial.rs +++ b/examples/src/bin/embassy_serial.rs @@ -80,7 +80,7 @@ async fn main(spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let mut uart0 = Uart::new_async(peripherals.UART0, &clocks); diff --git a/examples/src/bin/embassy_spi.rs b/examples/src/bin/embassy_spi.rs index d64fca512..744534c5d 100644 --- a/examples/src/bin/embassy_spi.rs +++ b/examples/src/bin/embassy_spi.rs @@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_systimer_delay.rs b/examples/src/bin/embassy_systimer_delay.rs new file mode 100644 index 000000000..c9dfc7e2b --- /dev/null +++ b/examples/src/bin/embassy_systimer_delay.rs @@ -0,0 +1,42 @@ +//! embassy systimer delay +//! +//! This is an example of using the `DelayNs` trait implementation + +//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 +//% FEATURES: embassy embassy-time-timg0 embassy-executor-thread embassy-generic-timers async + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Spawner; +use embedded_hal_async::delay::DelayNs; +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, + embassy, + peripherals::Peripherals, + prelude::*, + systimer::SystemTimer, + timer::TimerGroup, +}; + +#[main] +async fn main(_spawner: Spawner) { + esp_println::println!("Init!"); + let peripherals = Peripherals::take(); + let system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); + embassy::init(&clocks, timg0); + + let mut alarm0 = SystemTimer::new_async(peripherals.SYSTIMER) + .alarm0 + .into_periodic(); + + loop { + esp_println::println!("Bing!"); + alarm0.delay_ms(1000).await; + } +} diff --git a/examples/src/bin/embassy_twai.rs b/examples/src/bin/embassy_twai.rs index a700fa064..92f4e3d67 100644 --- a/examples/src/bin/embassy_twai.rs +++ b/examples/src/bin/embassy_twai.rs @@ -80,7 +80,7 @@ async fn main(spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/embassy_usb_serial_jtag.rs b/examples/src/bin/embassy_usb_serial_jtag.rs index 9ed524d01..d89171708 100644 --- a/examples/src/bin/embassy_usb_serial_jtag.rs +++ b/examples/src/bin/embassy_usb_serial_jtag.rs @@ -71,7 +71,7 @@ async fn main(spawner: Spawner) -> () { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - embassy::init(&clocks, TimerGroup::new(peripherals.TIMG0, &clocks)); + embassy::init(&clocks, TimerGroup::new_async(peripherals.TIMG0, &clocks)); let (tx, rx) = UsbSerialJtag::new_async(peripherals.USB_DEVICE).split(); diff --git a/examples/src/bin/embassy_wait.rs b/examples/src/bin/embassy_wait.rs index 9824007e9..3e84db2d3 100644 --- a/examples/src/bin/embassy_wait.rs +++ b/examples/src/bin/embassy_wait.rs @@ -29,7 +29,7 @@ async fn main(_spawner: Spawner) { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/examples/src/bin/etm_timer.rs b/examples/src/bin/etm_timer.rs index 391e08942..371db9a33 100644 --- a/examples/src/bin/etm_timer.rs +++ b/examples/src/bin/etm_timer.rs @@ -14,18 +14,19 @@ use esp_hal::{ clock::ClockControl, delay::Delay, etm::Etm, - interrupt::{self, Priority}, - peripherals::{Interrupt, Peripherals, TIMG0}, + peripherals::{Peripherals, TIMG0}, prelude::*, timer::{ etm::{TimerEtmEvents, TimerEtmTasks}, Timer, Timer0, TimerGroup, + TimerInterrupts, }, }; -static TIMER0: Mutex>>>> = Mutex::new(RefCell::new(None)); +static TIMER0: Mutex, esp_hal::Blocking>>>> = + Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { @@ -33,7 +34,14 @@ fn main() -> ! { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new( + peripherals.TIMG0, + &clocks, + Some(TimerInterrupts { + timer0_t0: Some(tg0_t0_level), + ..Default::default() + }), + ); let mut timer0 = timg0.timer0; // Configure ETM to stop timer0 when alarm is triggered @@ -50,14 +58,10 @@ fn main() -> ! { // 80 / 2 (default divider) timer clock cycles == 1 us timer0.load_alarm_value(100 * 1_000 * 40); timer0.set_alarm_active(true); - - // Enable interrupt that will be triggered by the alarm - interrupt::enable(Interrupt::TG0_T0_LEVEL, Priority::Priority1).unwrap(); - - timer0.listen(); timer0.set_counter_active(true); critical_section::with(|cs| { + timer0.listen(); TIMER0.borrow_ref_mut(cs).replace(timer0); }); @@ -75,8 +79,8 @@ fn main() -> ! { } } -#[interrupt] -fn TG0_T0_LEVEL() { +#[handler] +fn tg0_t0_level() { critical_section::with(|cs| { let mut timer0 = TIMER0.borrow_ref_mut(cs); let timer0 = timer0.as_mut().unwrap(); diff --git a/examples/src/bin/systimer.rs b/examples/src/bin/systimer.rs index 0b3b7c6ed..5d84d6a6b 100644 --- a/examples/src/bin/systimer.rs +++ b/examples/src/bin/systimer.rs @@ -18,13 +18,15 @@ use esp_hal::{ peripherals::{Interrupt, Peripherals}, prelude::*, systimer::{Alarm, Periodic, SystemTimer, Target}, + Blocking, }; use esp_println::println; use fugit::ExtU32; -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 ALARM0: 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() -> ! { @@ -36,19 +38,22 @@ fn main() -> ! { println!("SYSTIMER Current value = {}", SystemTimer::now()); - let alarm0 = systimer.alarm0.into_periodic(); - alarm0.set_period(1u32.secs()); - alarm0.enable_interrupt(true); - - let alarm1 = systimer.alarm1; - alarm1.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 2)); - alarm1.enable_interrupt(true); - - let alarm2 = systimer.alarm2; - alarm2.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 3)); - alarm2.enable_interrupt(true); - critical_section::with(|cs| { + let alarm0 = systimer.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); + ALARM0.borrow_ref_mut(cs).replace(alarm0); ALARM1.borrow_ref_mut(cs).replace(alarm1); ALARM2.borrow_ref_mut(cs).replace(alarm2); @@ -67,8 +72,8 @@ fn main() -> ! { } } -#[interrupt] -fn SYSTIMER_TARGET0() { +#[handler(priority = esp_hal::interrupt::Priority::min())] +fn systimer_target0() { println!("Interrupt lvl1 (alarm0)"); critical_section::with(|cs| { ALARM0 @@ -79,8 +84,8 @@ fn SYSTIMER_TARGET0() { }); } -#[interrupt] -fn SYSTIMER_TARGET1() { +#[handler(priority = esp_hal::interrupt::Priority::Priority1)] +fn systimer_target1() { println!("Interrupt lvl2 (alarm1)"); critical_section::with(|cs| { ALARM1 @@ -91,8 +96,8 @@ fn SYSTIMER_TARGET1() { }); } -#[interrupt] -fn SYSTIMER_TARGET2() { +#[handler(priority = esp_hal::interrupt::Priority::max())] +fn systimer_target2() { println!("Interrupt lvl2 (alarm2)"); critical_section::with(|cs| { ALARM2 diff --git a/examples/src/bin/timer_interrupt.rs b/examples/src/bin/timer_interrupt.rs index 62e4194f9..0696c60e8 100644 --- a/examples/src/bin/timer_interrupt.rs +++ b/examples/src/bin/timer_interrupt.rs @@ -16,10 +16,11 @@ use esp_hal::{ interrupt::{self, Priority}, peripherals::{Interrupt, Peripherals, TIMG0}, prelude::*, - timer::{Timer, Timer0, TimerGroup}, + timer::{Timer, Timer0, TimerGroup, TimerInterrupts}, }; -static TIMER0: Mutex>>>> = Mutex::new(RefCell::new(None)); +static TIMER0: Mutex, esp_hal::Blocking>>>> = + Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { @@ -27,7 +28,14 @@ fn main() -> ! { let system = peripherals.SYSTEM.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new( + peripherals.TIMG0, + &clocks, + Some(TimerInterrupts { + timer0_t0: Some(tg0_t0_level), + ..Default::default() + }), + ); let mut timer0 = timg0.timer0; interrupt::enable(Interrupt::TG0_T0_LEVEL, Priority::Priority1).unwrap(); @@ -41,8 +49,8 @@ fn main() -> ! { loop {} } -#[interrupt] -fn TG0_T0_LEVEL() { +#[handler] +fn tg0_t0_level() { critical_section::with(|cs| { esp_println::println!("Interrupt 1"); diff --git a/examples/src/bin/watchdog.rs b/examples/src/bin/watchdog.rs index 8fe972f69..6595e29cd 100644 --- a/examples/src/bin/watchdog.rs +++ b/examples/src/bin/watchdog.rs @@ -26,7 +26,7 @@ fn main() -> ! { let delay = Delay::new(&clocks); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); let mut wdt0 = timg0.wdt; wdt0.enable(); wdt0.set_timeout(2u64.secs()); diff --git a/hil-test/tests/gpio.rs b/hil-test/tests/gpio.rs index 93defd258..017aab9b1 100644 --- a/hil-test/tests/gpio.rs +++ b/hil-test/tests/gpio.rs @@ -45,7 +45,7 @@ impl Context { let delay = Delay::new(&clocks); - let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); Context {