From cb0bc7ef288de9410db4541607235d157bc44b6b Mon Sep 17 00:00:00 2001 From: McBandaska Date: Thu, 8 May 2025 20:08:33 +0200 Subject: [PATCH 1/2] both timers support up to 4 alarms --- rp235x-hal/src/timer.rs | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/rp235x-hal/src/timer.rs b/rp235x-hal/src/timer.rs index 0caf3ef1f..ca2b1ff2d 100644 --- a/rp235x-hal/src/timer.rs +++ b/rp235x-hal/src/timer.rs @@ -22,18 +22,19 @@ use crate::{ /// Instant type used by the Timer & Alarm methods. pub type Instant = TimerInstantU64<1_000_000>; -static ALARMS: AtomicU8 = AtomicU8::new(0x0F); -fn take_alarm(mask: u8) -> bool { +static ALARMS_TIMER0: AtomicU8 = AtomicU8::new(0x0F); +static ALARMS_TIMER1: AtomicU8 = AtomicU8::new(0x0F); +fn take_alarm(mask: u8, alarms: &'static AtomicU8) -> bool { critical_section::with(|_| { - let alarms = ALARMS.load(Ordering::Relaxed); - ALARMS.store(alarms & !mask, Ordering::Relaxed); - (alarms & mask) != 0 + let current_alarms = alarms.load(Ordering::Relaxed); + alarms.store(current_alarms & !mask, Ordering::Relaxed); + (current_alarms & mask) != 0 }) } -fn release_alarm(mask: u8) { +fn release_alarm(mask: u8, alarms: &'static AtomicU8) { critical_section::with(|_| { - let alarms = ALARMS.load(Ordering::Relaxed); - ALARMS.store(alarms | mask, Ordering::Relaxed); + let current_alarms = alarms.load(Ordering::Relaxed); + alarms.store(current_alarms | mask, Ordering::Relaxed); }); } @@ -66,6 +67,15 @@ pub trait TimerDevice: Sealed + Clone + Copy + 'static { unsafe { &*pac::TIMER1::ptr() } } } + + /// Get the static AtomicU8 for managing alarms. + fn get_alarms_tracker() -> &'static AtomicU8 { + if Self::ID == 0 { + &ALARMS_TIMER0 + } else { + &ALARMS_TIMER1 + } + } } impl TimerDevice for CopyableTimer0 { @@ -168,22 +178,22 @@ where } /// Retrieve a reference to alarm 0. Will only return a value the first time this is called pub fn alarm_0(&mut self) -> Option> { - take_alarm(1 << 0).then_some(Alarm0(*self)) + take_alarm(1 << 0, ::get_alarms_tracker()).then_some(Alarm0(*self)) } /// Retrieve a reference to alarm 1. Will only return a value the first time this is called pub fn alarm_1(&mut self) -> Option> { - take_alarm(1 << 1).then_some(Alarm1(*self)) + take_alarm(1 << 1, ::get_alarms_tracker()).then_some(Alarm1(*self)) } /// Retrieve a reference to alarm 2. Will only return a value the first time this is called pub fn alarm_2(&mut self) -> Option> { - take_alarm(1 << 2).then_some(Alarm2(*self)) + take_alarm(1 << 2, ::get_alarms_tracker()).then_some(Alarm2(*self)) } /// Retrieve a reference to alarm 3. Will only return a value the first time this is called pub fn alarm_3(&mut self) -> Option> { - take_alarm(1 << 3).then_some(Alarm3(*self)) + take_alarm(1 << 3, ::get_alarms_tracker()).then_some(Alarm3(*self)) } /// Pauses execution for at minimum `us` microseconds. @@ -549,7 +559,7 @@ macro_rules! impl_alarm { { fn drop(&mut self) { self.disable_interrupt(); - release_alarm($armed_bit_mask) + release_alarm($armed_bit_mask, D::get_alarms_tracker()); } } }; @@ -636,4 +646,4 @@ pub mod monotonic { unsafe fn reset(&mut self) {} } -} +} \ No newline at end of file From 775e95859c58b07152dd2bd50bbae1d5621a1591 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Tue, 12 Aug 2025 19:24:16 +0100 Subject: [PATCH 2/2] Use CAS operations rather than a critical section to flip alarm bits. --- rp235x-hal/src/timer.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/rp235x-hal/src/timer.rs b/rp235x-hal/src/timer.rs index ca2b1ff2d..ea0404820 100644 --- a/rp235x-hal/src/timer.rs +++ b/rp235x-hal/src/timer.rs @@ -22,20 +22,16 @@ use crate::{ /// Instant type used by the Timer & Alarm methods. pub type Instant = TimerInstantU64<1_000_000>; -static ALARMS_TIMER0: AtomicU8 = AtomicU8::new(0x0F); -static ALARMS_TIMER1: AtomicU8 = AtomicU8::new(0x0F); +static ALARMS_TIMER0: AtomicU8 = AtomicU8::new(0x00); +static ALARMS_TIMER1: AtomicU8 = AtomicU8::new(0x00); + fn take_alarm(mask: u8, alarms: &'static AtomicU8) -> bool { - critical_section::with(|_| { - let current_alarms = alarms.load(Ordering::Relaxed); - alarms.store(current_alarms & !mask, Ordering::Relaxed); - (current_alarms & mask) != 0 - }) + let current_alarms = alarms.fetch_or(mask, Ordering::Relaxed); + (current_alarms & mask) == 0 } + fn release_alarm(mask: u8, alarms: &'static AtomicU8) { - critical_section::with(|_| { - let current_alarms = alarms.load(Ordering::Relaxed); - alarms.store(current_alarms | mask, Ordering::Relaxed); - }); + alarms.fetch_and(!mask, Ordering::Relaxed); } /// Represents Timer0 @@ -646,4 +642,4 @@ pub mod monotonic { unsafe fn reset(&mut self) {} } -} \ No newline at end of file +}