From 7c0990ad1e8d1a455818740973ca0267bb3f5854 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 25 Aug 2021 18:50:05 +0200 Subject: time: allow storing state inside the driver struct. --- embassy-rp/src/timer.rs | 124 +++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 60 deletions(-) (limited to 'embassy-rp') diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs index 71c59ec8..ed265c47 100644 --- a/embassy-rp/src/timer.rs +++ b/embassy-rp/src/timer.rs @@ -19,38 +19,40 @@ const DUMMY_ALARM: AlarmState = AlarmState { callback: Cell::new(None), }; -static ALARMS: Mutex<[AlarmState; ALARM_COUNT]> = Mutex::new([DUMMY_ALARM; ALARM_COUNT]); -static NEXT_ALARM: AtomicU8 = AtomicU8::new(0); - -fn now() -> u64 { - loop { - unsafe { - let hi = pac::TIMER.timerawh().read(); - let lo = pac::TIMER.timerawl().read(); - let hi2 = pac::TIMER.timerawh().read(); - if hi == hi2 { - return (hi as u64) << 32 | (lo as u64); - } - } - } +struct TimerDriver { + alarms: Mutex<[AlarmState; ALARM_COUNT]>, + next_alarm: AtomicU8, } -struct TimerDriver; -embassy::time_driver_impl!(TimerDriver); +embassy::time_driver_impl!(static DRIVER: TimerDriver = TimerDriver{ + alarms: Mutex::new([DUMMY_ALARM; ALARM_COUNT]), + next_alarm: AtomicU8::new(0), +}); impl Driver for TimerDriver { - fn now() -> u64 { - now() + fn now(&self) -> u64 { + loop { + unsafe { + let hi = pac::TIMER.timerawh().read(); + let lo = pac::TIMER.timerawl().read(); + let hi2 = pac::TIMER.timerawh().read(); + if hi == hi2 { + return (hi as u64) << 32 | (lo as u64); + } + } + } } - unsafe fn allocate_alarm() -> Option { - let id = NEXT_ALARM.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { - if x < ALARM_COUNT as u8 { - Some(x + 1) - } else { - None - } - }); + unsafe fn allocate_alarm(&self) -> Option { + let id = self + .next_alarm + .fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { + if x < ALARM_COUNT as u8 { + Some(x + 1) + } else { + None + } + }); match id { Ok(id) => Some(AlarmHandle::new(id)), @@ -58,18 +60,18 @@ impl Driver for TimerDriver { } } - fn set_alarm_callback(alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { + fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { let n = alarm.id() as usize; critical_section::with(|cs| { - let alarm = &ALARMS.borrow(cs)[n]; + let alarm = &self.alarms.borrow(cs)[n]; alarm.callback.set(Some((callback, ctx))); }) } - fn set_alarm(alarm: AlarmHandle, timestamp: u64) { + fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { let n = alarm.id() as usize; critical_section::with(|cs| { - let alarm = &ALARMS.borrow(cs)[n]; + let alarm = &self.alarms.borrow(cs)[n]; alarm.timestamp.set(timestamp); // Arm it. @@ -78,44 +80,46 @@ impl Driver for TimerDriver { // it is checked if the alarm time has passed. unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; - let now = now(); + let now = self.now(); // If alarm timestamp has passed, trigger it instantly. // This disarms it. if timestamp <= now { - trigger_alarm(n, cs); + self.trigger_alarm(n, cs); } }) } } -fn check_alarm(n: usize) { - critical_section::with(|cs| { - let alarm = &ALARMS.borrow(cs)[n]; - let timestamp = alarm.timestamp.get(); - if timestamp <= now() { - trigger_alarm(n, cs) - } else { - // Not elapsed, arm it again. - // This can happen if it was set more than 2^32 us in the future. - unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; - } - }); +impl TimerDriver { + fn check_alarm(&self, n: usize) { + critical_section::with(|cs| { + let alarm = &self.alarms.borrow(cs)[n]; + let timestamp = alarm.timestamp.get(); + if timestamp <= self.now() { + self.trigger_alarm(n, cs) + } else { + // Not elapsed, arm it again. + // This can happen if it was set more than 2^32 us in the future. + unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; + } + }); - // clear the irq - unsafe { pac::TIMER.intr().write(|w| w.set_alarm(n, true)) } -} + // clear the irq + unsafe { pac::TIMER.intr().write(|w| w.set_alarm(n, true)) } + } -fn trigger_alarm(n: usize, cs: CriticalSection) { - // disarm - unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } + fn trigger_alarm(&self, n: usize, cs: CriticalSection) { + // disarm + unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } - let alarm = &ALARMS.borrow(cs)[n]; - alarm.timestamp.set(u64::MAX); + let alarm = &self.alarms.borrow(cs)[n]; + alarm.timestamp.set(u64::MAX); - // Call after clearing alarm, so the callback can set another alarm. - if let Some((f, ctx)) = alarm.callback.get() { - f(ctx); + // Call after clearing alarm, so the callback can set another alarm. + if let Some((f, ctx)) = alarm.callback.get() { + f(ctx); + } } } @@ -123,7 +127,7 @@ fn trigger_alarm(n: usize, cs: CriticalSection) { pub unsafe fn init() { // init alarms critical_section::with(|cs| { - let alarms = ALARMS.borrow(cs); + let alarms = DRIVER.alarms.borrow(cs); for a in alarms { a.timestamp.set(u64::MAX); } @@ -144,20 +148,20 @@ pub unsafe fn init() { #[interrupt] unsafe fn TIMER_IRQ_0() { - check_alarm(0) + DRIVER.check_alarm(0) } #[interrupt] unsafe fn TIMER_IRQ_1() { - check_alarm(1) + DRIVER.check_alarm(1) } #[interrupt] unsafe fn TIMER_IRQ_2() { - check_alarm(2) + DRIVER.check_alarm(2) } #[interrupt] unsafe fn TIMER_IRQ_3() { - check_alarm(3) + DRIVER.check_alarm(3) } -- cgit v1.2.3