summaryrefslogtreecommitdiff
path: root/embassy-rp
diff options
context:
space:
mode:
authorDario Nieuwenhuis <dirbaio@dirbaio.net>2021-08-25 18:50:05 +0200
committerDario Nieuwenhuis <dirbaio@dirbaio.net>2021-08-25 21:06:27 +0200
commit7c0990ad1e8d1a455818740973ca0267bb3f5854 (patch)
treea7acf5be11f48adb18c10369477cd1cbc80798d3 /embassy-rp
parent55b2d7b5248cb81e80e8c207ab03e6b4b52ce2f9 (diff)
downloadembassy-7c0990ad1e8d1a455818740973ca0267bb3f5854.zip
time: allow storing state inside the driver struct.
Diffstat (limited to 'embassy-rp')
-rw-r--r--embassy-rp/src/timer.rs124
1 files changed, 64 insertions, 60 deletions
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<AlarmHandle> {
- 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<AlarmHandle> {
+ 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)
}