You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I wrote some code to link two 16 bit timers on an STM32L0 in order to form a 32 bit upcounting timer that can be used to measure relative time. The goal is to use this abstraction in order to implement the Monotonic trait for the RTIC scheduler.
Here's the current code, needs more testing & should be made more general (there are other timer pairs that allow linking), but seems to work already:
/// Two linked 16 bit timers that form a 32 bit upcounter.pubstructLinkedTimer{/// Timer in master modetim2:TIM2,/// Timer in slave modetim3:TIM3,}implLinkedTimer{/// Create a new `LinkedTimer` with TIM2 as master and TIM3 as slave.pubfnnew(tim2:TIM2,tim3:TIM3,rcc:&mutRcc) -> Self{// Enable timers
rcc.rb.apb1enr.modify(|_, w| w.tim2en().set_bit());
rcc.rb.apb1enr.modify(|_, w| w.tim3en().set_bit());// Reset timers
rcc.rb.apb1rstr.modify(|_, w| w.tim2rst().set_bit());
rcc.rb.apb1rstr.modify(|_, w| w.tim2rst().clear_bit());
rcc.rb.apb1rstr.modify(|_, w| w.tim3rst().set_bit());
rcc.rb.apb1rstr.modify(|_, w| w.tim3rst().clear_bit());// Enable counter
tim2.cr1.modify(|_, w| w.cen().set_bit());
tim3.cr1.modify(|_, w| w.cen().set_bit());// In the MMS (Master Mode Selection) register, set the master mode so// that a rising edge is output on the trigger output TRGO every time// an update event is generated.
tim2.cr2.modify(|_, w| w.mms().variant(tim2::cr2::MMS_A::UPDATE));// In the SMCR (Slave Mode Control Register), select the internal// trigger 0 (ITR0) as trigger source (TS).//// See table 76 ("TIM2/TIM3 internal trigger connection") in the// reference manual RM0377.
tim3.smcr.modify(|_, w| w.ts().variant(tim2::smcr::TS_A::ITR0));// Set the SMS (Slave Mode Selection) register to "external clock mode 1",// where the rising edges of the selected trigger (TRGI) clock the counter.
tim3.smcr.modify(|_, w| w.sms().variant(tim2::smcr::SMS_A::EXT_CLOCK_MODE));Self{ tim2, tim3 }}fnmaster(&self) -> &TIM2{&self.tim2}fnslave(&self) -> &TIM3{&self.tim3}/// Return the current 32 bit counter value.pubfnget_counter(&self) -> u32{let lsb = self.master().cnt.read().cnt().bits()asu32;let msb = self.slave().cnt.read().cnt().bits()asu32;(msb << 16) | lsb
}}
Should this go into the stm32l0-hal? If yes, how should it be called? Should there be a trait involved that's implemented for all timers that allow linking? Or a trait for upcounting timers that cannot be reset?
If yes, should there also be logic for detecting overflows in the HAL, or should that be part of user code?
Right now there's no API in embedded-hal that matches this pattern (see also this discussion). It also cannot be combined with CountDown because resetting the timer (on start) also resets the counter.
I wrote some code to link two 16 bit timers on an STM32L0 in order to form a 32 bit upcounting timer that can be used to measure relative time. The goal is to use this abstraction in order to implement the
Monotonic
trait for the RTIC scheduler.Here's the current code, needs more testing & should be made more general (there are other timer pairs that allow linking), but seems to work already:
When polling the value with 10 Hz:
Should this go into the stm32l0-hal? If yes, how should it be called? Should there be a trait involved that's implemented for all timers that allow linking? Or a trait for upcounting timers that cannot be reset?
If yes, should there also be logic for detecting overflows in the HAL, or should that be part of user code?
Right now there's no API in embedded-hal that matches this pattern (see also this discussion). It also cannot be combined with
CountDown
because resetting the timer (on start) also resets the counter.CC @astro @hannobraun @rnestler
The text was updated successfully, but these errors were encountered: