Skip to content

Commit ad072b0

Browse files
committed
Adds micros_since method to timers
1 parent 79e68ac commit ad072b0

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1515
- Update existing ADC example according to ADC API changes
1616
- Add new ADC example to read ambient temperature using ADC1 CH16
1717
- Add `listen` and `unlisten` to `serial::Tx` and `serial::Rx`.
18-
- Add `count` and `reset` methods to timer
18+
- Add `micros_since` and `reset` methods to timer
1919

2020

2121
### Breaking changes

src/timer.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::hal::timer::{CountDown, Periodic};
44
use crate::pac::{TIM1, TIM2, TIM3, TIM4};
5-
use cast::{u16, u32};
5+
use cast::{u16, u32, u64};
66
use cortex_m::peripheral::syst::SystClkSource;
77
use cortex_m::peripheral::SYST;
88
use nb;
@@ -73,6 +73,26 @@ impl Timer<SYST> {
7373
}
7474
}
7575

76+
/// Resets the timer
77+
pub fn reset(&mut self) {
78+
// According to the Cortex-M3 Generic User Guide, the interrupt request is only generated
79+
// when the counter goes from 1 to 0, so writing zero should not trigger an interrupt
80+
self.tim.clear_current();
81+
}
82+
83+
/// Returns the number of microseconds since the last update event.
84+
/// *NOTE:* This method is not a very good candidate to keep track of time, because
85+
/// it is very easy to lose an update event.
86+
pub fn micros_since(&self) -> u32 {
87+
let reload_value = SYST::get_reload();
88+
let timer_clock = u64(self.clocks.sysclk().0);
89+
let ticks = u64(reload_value - SYST::get_current());
90+
91+
// It is safe to make this cast since the maximum ticks is (2^24 - 1) and the minimum sysclk
92+
// is 4Mhz, which gives a maximum period of ~4.2 seconds which is < (2^32 - 1) microsenconds
93+
u32(1_000_000 * ticks / timer_clock).unwrap()
94+
}
95+
7696
/// Stops the timer
7797
pub fn stop(&mut self) {
7898
self.tim.disable_counter();
@@ -161,15 +181,27 @@ macro_rules! hal {
161181
self.tim
162182
}
163183

164-
/// Returns the current counter value
165-
pub fn count(&self) -> u16 {
166-
self.tim.cnt.read().cnt().bits()
184+
/// Returns the number of microseconds since the last update event.
185+
/// *NOTE:* This method is not a very good candidate to keep track of time, because
186+
/// it is very easy to lose an update event.
187+
pub fn micros_since(&self) -> u32 {
188+
let timer_clock = $TIMX::get_clk(&self.clocks).0;
189+
let psc = u32(self.tim.psc.read().psc().bits());
190+
191+
// freq_divider is always bigger than 0, since (psc + 1) is always less than
192+
// timer_clock
193+
let freq_divider = u64(timer_clock / (psc + 1));
194+
let cnt = u64(self.tim.cnt.read().cnt().bits());
195+
196+
// It is safe to make this cast, because the maximum timer period in this HAL is
197+
// 1s (1Hz), then 1 second < (2^32 - 1) microseconds
198+
u32(1_000_000 * cnt / freq_divider).unwrap()
167199
}
168200

169201
/// Resets the counter and generates an update event
170202
pub fn reset(&mut self) {
171203
// Sets the URS bit to prevent an interrupt from being triggered by
172-
// the UG bit.
204+
// the UG bit
173205
self.tim.cr1.modify(|_, w| w.urs().set_bit());
174206

175207
self.tim.egr.write(|w| w.ug().set_bit());

0 commit comments

Comments
 (0)