rtc: Add alarm callback.

This commit is contained in:
Dario Nieuwenhuis 2020-09-24 22:41:52 +02:00
parent f8d63b1f30
commit 82e5e3c45f
2 changed files with 22 additions and 11 deletions

View File

@ -52,15 +52,18 @@ pub struct RTC<T> {
period: AtomicU32, period: AtomicU32,
/// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
alarm: Mutex<Cell<u64>>, alarm: Mutex<Cell<(u64, Option<fn()>)>>,
} }
unsafe impl<T> Send for RTC<T> {}
unsafe impl<T> Sync for RTC<T> {}
impl<T: Instance> RTC<T> { impl<T: Instance> RTC<T> {
pub fn new(rtc: T) -> Self { pub fn new(rtc: T) -> Self {
Self { Self {
rtc, rtc,
period: AtomicU32::new(0), period: AtomicU32::new(0),
alarm: Mutex::new(Cell::new(u64::MAX)), alarm: Mutex::new(Cell::new((u64::MAX, None))),
} }
} }
@ -108,7 +111,7 @@ impl<T: Instance> RTC<T> {
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
let t = (period as u64) << 23; let t = (period as u64) << 23;
let at = self.alarm.borrow(cs).get(); let (at, _) = self.alarm.borrow(cs).get();
let diff = at - t; let diff = at - t;
if diff < 0xc00000 { if diff < 0xc00000 {
@ -126,22 +129,26 @@ impl<T: Instance> RTC<T> {
fn trigger_alarm(&self) { fn trigger_alarm(&self) {
self.rtc.intenclr.write(|w| w.compare1().clear()); self.rtc.intenclr.write(|w| w.compare1().clear());
interrupt::free(|cs| self.alarm.borrow(cs).set(u64::MAX)); interrupt::free(|cs| {
let alarm = self.alarm.borrow(cs);
let (_, f) = alarm.get();
alarm.set((u64::MAX, None));
// TODO // Call after clearing alarm, so the callback can set another alarm.
trace!("ALARM! {:u32}", self.now() as u32); f.map(|f| f())
});
} }
pub fn set_alarm(&self, at: u64) { fn do_set_alarm(&self, at: u64, f: Option<fn()>) {
interrupt::free(|cs| { interrupt::free(|cs| {
self.alarm.borrow(cs).set((at, f));
let t = self.now(); let t = self.now();
if at <= t { if at <= t {
self.trigger_alarm(); self.trigger_alarm();
return; return;
} }
self.alarm.borrow(cs).set(at);
let diff = at - t; let diff = at - t;
if diff < 0xc00000 { if diff < 0xc00000 {
self.rtc.cc[1].write(|w| unsafe { w.bits(at as u32 & 0xFFFFFF) }); self.rtc.cc[1].write(|w| unsafe { w.bits(at as u32 & 0xFFFFFF) });
@ -162,8 +169,12 @@ impl<T: Instance> RTC<T> {
}) })
} }
pub fn set_alarm(&self, at: u64, f: fn()) {
self.do_set_alarm(at, Some(f));
}
pub fn clear_alarm(&self) { pub fn clear_alarm(&self) {
self.set_alarm(u64::MAX); self.do_set_alarm(u64::MAX, None);
} }
} }

View File

@ -31,7 +31,7 @@ fn main() -> ! {
}; };
rtc.start(); rtc.start();
rtc.set_alarm(53719); rtc.set_alarm(53719, || info!("ALARM TRIGGERED"));
info!("initialized!"); info!("initialized!");