mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-23 20:51:31 +11:00
Merge pull request #280 from 9names/alarm-ergonomics
Use atomic operations for altering Timer alarm interrupts
This commit is contained in:
commit
16c9064c52
|
@ -54,7 +54,7 @@ mod app {
|
||||||
let mut timer = hal::Timer::new(c.device.TIMER, &mut resets);
|
let mut timer = hal::Timer::new(c.device.TIMER, &mut resets);
|
||||||
let mut alarm = timer.alarm_0().unwrap();
|
let mut alarm = timer.alarm_0().unwrap();
|
||||||
let _ = alarm.schedule(SCAN_TIME_US.microseconds());
|
let _ = alarm.schedule(SCAN_TIME_US.microseconds());
|
||||||
alarm.enable_interrupt(&mut timer);
|
alarm.enable_interrupt();
|
||||||
|
|
||||||
(Shared { timer, alarm, led }, Local {}, init::Monotonics())
|
(Shared { timer, alarm, led }, Local {}, init::Monotonics())
|
||||||
}
|
}
|
||||||
|
@ -73,10 +73,9 @@ mod app {
|
||||||
}
|
}
|
||||||
*c.local.tog = !*c.local.tog;
|
*c.local.tog = !*c.local.tog;
|
||||||
|
|
||||||
let timer = c.shared.timer;
|
let mut alarm = c.shared.alarm;
|
||||||
let alarm = c.shared.alarm;
|
(alarm).lock(|a| {
|
||||||
(timer, alarm).lock(|t, a| {
|
a.clear_interrupt();
|
||||||
a.clear_interrupt(t);
|
|
||||||
let _ = a.schedule(SCAN_TIME_US.microseconds());
|
let _ = a.schedule(SCAN_TIME_US.microseconds());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
use embedded_time::duration::Microseconds;
|
use embedded_time::duration::Microseconds;
|
||||||
|
|
||||||
|
use crate::atomic_register_access::{write_bitmask_clear, write_bitmask_set};
|
||||||
use crate::pac::{RESETS, TIMER};
|
use crate::pac::{RESETS, TIMER};
|
||||||
use crate::resets::SubsystemReset;
|
use crate::resets::SubsystemReset;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
@ -200,12 +201,15 @@ macro_rules! impl_alarm {
|
||||||
/// ` is called.
|
/// ` is called.
|
||||||
///
|
///
|
||||||
/// The interrupt is unable to trigger a 2nd time until this interrupt is cleared.
|
/// The interrupt is unable to trigger a 2nd time until this interrupt is cleared.
|
||||||
pub fn clear_interrupt(&mut self, timer: &mut Timer) {
|
pub fn clear_interrupt(&mut self) {
|
||||||
// safety: Because we have a mutable reference on `timer`, we have exclusive access to `TIMER::ptr()`
|
// safety: TIMER.intr is a write-clear register, so we can atomically clear our interrupt
|
||||||
let _ = timer;
|
// by writing its value to this field
|
||||||
let timer = unsafe { &*TIMER::ptr() };
|
// Only one instance of this alarm index can exist, and only this alarm interacts with this bit
|
||||||
|
// of the TIMER.inte register
|
||||||
timer.intr.modify(|_, w| w.$int_alarm().set_bit());
|
unsafe {
|
||||||
|
let timer = &(*pac::TIMER::ptr());
|
||||||
|
timer.intr.write_with_zero(|w| w.$int_alarm().set_bit());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable this alarm to trigger an interrupt. This alarm will trigger `
|
/// Enable this alarm to trigger an interrupt. This alarm will trigger `
|
||||||
|
@ -215,21 +219,27 @@ macro_rules! impl_alarm {
|
||||||
/// After this interrupt is triggered, make sure to clear the interrupt with [clear_interrupt].
|
/// After this interrupt is triggered, make sure to clear the interrupt with [clear_interrupt].
|
||||||
///
|
///
|
||||||
/// [clear_interrupt]: #method.clear_interrupt
|
/// [clear_interrupt]: #method.clear_interrupt
|
||||||
pub fn enable_interrupt(&mut self, timer: &mut Timer) {
|
pub fn enable_interrupt(&mut self) {
|
||||||
// safety: Because we have a mutable reference on `timer`, we have exclusive access to `TIMER::ptr()`
|
// safety: using the atomic set alias means we can atomically set our interrupt enable bit.
|
||||||
let _ = timer;
|
// Only one instance of this alarm can exist, and only this alarm interacts with this bit
|
||||||
let timer = unsafe { &*TIMER::ptr() };
|
// of the TIMER.inte register
|
||||||
|
unsafe {
|
||||||
timer.inte.modify(|_, w| w.$int_alarm().set_bit());
|
let timer = &(*pac::TIMER::ptr());
|
||||||
|
let reg = (&timer.inte).as_ptr();
|
||||||
|
write_bitmask_set(reg, $armed_bit_mask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable this alarm, preventing it from triggering an interrupt.
|
/// Disable this alarm, preventing it from triggering an interrupt.
|
||||||
pub fn disable_interrupt(&mut self, timer: &mut Timer) {
|
pub fn disable_interrupt(&mut self) {
|
||||||
// safety: Because we have a mutable reference on `timer`, we have exclusive access to `TIMER::ptr()`
|
// safety: using the atomic set alias means we can atomically clear our interrupt enable bit.
|
||||||
let _ = timer;
|
// Only one instance of this alarm can exist, and only this alarm interacts with this bit
|
||||||
let timer = unsafe { &*TIMER::ptr() };
|
// of the TIMER.inte register
|
||||||
|
unsafe {
|
||||||
timer.inte.modify(|_, w| w.$int_alarm().clear_bit());
|
let timer = &(*pac::TIMER::ptr());
|
||||||
|
let reg = (&timer.inte).as_ptr();
|
||||||
|
write_bitmask_clear(reg, $armed_bit_mask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedule the alarm to be finished after `countdown`. If [enable_interrupt] is called, this will trigger interrupt `
|
/// Schedule the alarm to be finished after `countdown`. If [enable_interrupt] is called, this will trigger interrupt `
|
||||||
|
|
Loading…
Reference in a new issue