Created
November 14, 2021 16:26
-
-
Save VictorKoenders/bcdc0a65ebebb0c396465391decb64ac to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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