Skip to content

Instantly share code, notes, and snippets.

@VictorKoenders
Created November 14, 2021 16:26
Show Gist options
  • Save VictorKoenders/bcdc0a65ebebb0c396465391decb64ac to your computer and use it in GitHub Desktop.
Save VictorKoenders/bcdc0a65ebebb0c396465391decb64ac to your computer and use it in GitHub Desktop.
use embedded_time::duration::Microseconds;
use rp2040_hal::pac::timer::RegisterBlock;
use rp2040_hal::pac::TIMER;
pub struct Timer {
_timer: TIMER,
}
impl Timer {
pub fn new(timer: TIMER) -> Self {
Self { _timer: timer }
}
pub fn split(self) -> (Timer0, Timer1, Timer2, Timer3) {
// HERE BE DRAGONS
// # Safety
//
// We know that we are the sole owner of TIMER, and that TIMER is a
// simple wrapper around a pointer to its RegisterBlock.
// We know that each TimerX implementation only touches its own
// addresses, so having multiple references to this RegisterBlock
// is fine.
(
Timer0(unsafe { &*TIMER::ptr() }),
Timer1(unsafe { &*TIMER::ptr() }),
Timer2(unsafe { &*TIMER::ptr() }),
Timer3(unsafe { &*TIMER::ptr() }),
)
}
}
macro_rules! impl_timer {
($n: tt: $name: ident ($timer_alarm:ident, $int_alarm: ident)) => {
pub struct $name(&'static RegisterBlock);
impl $name {
pub fn on_interrupt(&self) {
self.0.intr.modify(|_, w| w.$int_alarm().set_bit());
}
pub fn trigger_now(&self) {
self.start_countdown(Microseconds(0u32));
}
pub fn start_countdown<TIME: core::convert::TryInto<Microseconds>>(
&self,
countdown: TIME,
) {
let time = match countdown.try_into() {
Ok(time) => time,
Err(_) => panic!("Invalid time"),
};
cortex_m::interrupt::free(|_| {
self.0.$timer_alarm.write(|w| unsafe {
w.bits(self.0.timelr.read().bits().wrapping_add(time.0))
});
self.0.inte.modify(|_, w| w.$int_alarm().set_bit());
});
}
}
// we have a static reference to a RegisterBlock, but we know all instance have unique access
// see Timer::split() for more information
unsafe impl Send for $name {}
};
}
impl_timer!(0: Timer0(alarm0, alarm_0));
impl_timer!(1: Timer1(alarm1, alarm_1));
impl_timer!(2: Timer2(alarm2, alarm_2));
impl_timer!(3: Timer3(alarm3, alarm_3));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment