From e1b20c966e7d4726895539d0e733f487e58bf3b4 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 18 Apr 2022 20:14:03 +0200 Subject: [PATCH] Allow cancelling timers. --- src/timer.rs | 61 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/timer.rs b/src/timer.rs index 78ebff70..10ebc0cb 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,6 +1,8 @@ //! Timers -use crate::hal::timer::{CountDown, Periodic}; +use core::convert::Infallible; + +use crate::hal::timer::{Cancel, CountDown, Periodic}; #[cfg(any( // feature = "stm32l451", @@ -87,17 +89,16 @@ macro_rules! hal { type Time = Hertz; // NOTE(allow) `w.psc().bits()` is safe for TIM{6,7} but not for TIM{2,3,4} due to - // some SVD omission + // some SVD omission. #[allow(unused_unsafe)] fn start(&mut self, timeout: T) where T: Into, { - // pause - self.tim.cr1.modify(|_, w| w.cen().clear_bit()); + self.pause(); self.timeout = timeout.into(); - let ticks = self.clocks.pclk1() / self.timeout; // TODO check pclk that timer is on + let ticks = self.clocks.pclk1() / self.timeout; // TODO: Check pclk that timer is on. let psc = u16((ticks - 1) / (1 << 16)).unwrap(); self.tim.psc.write(|w| unsafe { w.psc().bits(psc) }); @@ -106,14 +107,15 @@ macro_rules! hal { self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) }); - // Trigger an update event to load the prescaler value to the clock + // Trigger an update event to load the prescaler value to the clock. self.tim.egr.write(|w| w.ug().set_bit()); + // The above line raises an update event which will indicate // that the timer is already finished. Since this is not the case, - // it should be cleared + // it should be cleared. self.clear_update_interrupt_flag(); - // start counter + // Start counter. self.tim.cr1.modify(|_, w| w.cen().set_bit()); } @@ -127,6 +129,17 @@ macro_rules! hal { } } + impl Cancel for Timer<$TIM> { + type Error = Infallible; + + fn cancel(&mut self) -> Result<(), Self::Error> { + self.pause(); + self.reset(); + + Ok(()) + } + } + impl Timer<$TIM> { // XXX(why not name this `new`?) bummer: constructors need to have different names // even if the `$TIM` are non overlapping (compare to the `free` function below @@ -170,15 +183,16 @@ macro_rules! hal { let max = core::$width::MAX; tim.arr.write(|w| unsafe { w.bits(max.into()) }); - // Trigger an update event to load the prescaler value to the clock + // Trigger an update event to load the prescaler value to the clock. tim.egr.write(|w| w.ug().set_bit()); + // The above line raises an update event which will indicate // that the timer is already finished. Since this is not the case, // it should be cleared tim.sr.modify(|_, w| w.uif().clear_bit()); - // start counter + // Start counter. tim.cr1.modify(|_, w| { w.cen().set_bit(); @@ -202,17 +216,16 @@ macro_rules! hal { pub fn listen(&mut self, event: Event) { match event { Event::TimeOut => { - // Enable update event interrupt + // Enable update event interrupt. self.tim.dier.write(|w| w.uie().set_bit()); } } } - /// Clears interrupt associated with `event`. /// - /// If the interrupt is not cleared, it will immediately retrigger after - /// the ISR has finished. + /// If the interrupt is not cleared, it will immediately + /// retrigger after the ISR has finished. pub fn clear_interrupt(&mut self, event: Event) { match event { Event::TimeOut => { @@ -222,8 +235,7 @@ macro_rules! hal { } } - - /// Stops listening for an `event` + /// Stops listening for an `event`. pub fn unlisten(&mut self, event: Event) { match event { Event::TimeOut => { @@ -233,7 +245,7 @@ macro_rules! hal { } } - /// Clears Update Interrupt Flag + /// Clear the update interrupt flag. pub fn clear_update_interrupt_flag(&mut self) { self.tim.sr.modify(|_, w| w.uif().clear_bit()); } @@ -244,10 +256,19 @@ macro_rules! hal { cnt.cnt().bits() } - /// Releases the TIM peripheral - pub fn free(self) -> $TIM { - // pause counter + /// Pause the counter. + pub fn pause(&mut self) { self.tim.cr1.modify(|_, w| w.cen().clear_bit()); + } + + /// Reset the counter. + pub fn reset(&mut self) { + self.tim.cnt.modify(|_, w| unsafe { w.bits(0) }); + } + + /// Releases the TIM peripheral. + pub fn free(mut self) -> $TIM { + self.pause(); self.tim } }