rtc: Add alarm callback.
This commit is contained in:
parent
f8d63b1f30
commit
82e5e3c45f
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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!");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user