Skip to content

Commit 2303279

Browse files
committed
fix clear_compare_flag, add more comments
1 parent 169db54 commit 2303279

File tree

1 file changed

+24
-17
lines changed

1 file changed

+24
-17
lines changed

src/lib.rs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,15 @@ impl<const TIMER_HZ: u32> Monotonic for DwtSystick<TIMER_HZ> {
9999
}
100100

101101
fn set_compare(&mut self, val: Self::Instant) {
102-
// The input `val` is in the timer, but the SysTick is a down-counter.
103-
// We need to convert into its domain.
104-
let now = self.now();
105-
102+
// The input `val` refers to the cycle counter value (up-counter)
103+
// but the SysTick is a down-counter with interrupt on zero.
106104
let reload = val
107-
.checked_duration_since(now)
105+
.checked_duration_since(self.now())
108106
// Minimum reload value if `val` is in the past
109-
.map_or(0, |t| t.ticks())
107+
.map_or(0, |duration| duration.ticks())
108+
// CYCCNT and SysTick have the same clock, no
109+
// ticks conversion necessary, only clamping:
110+
//
110111
// ARM Architecture Reference Manual says:
111112
// "Setting SYST_RVR to zero has the effect of
112113
// disabling the SysTick counter independently
@@ -116,6 +117,8 @@ impl<const TIMER_HZ: u32> Monotonic for DwtSystick<TIMER_HZ> {
116117
.min(0xff_ffff) as u32;
117118

118119
self.systick.set_reload(reload);
120+
// Also clear the current counter. That doesn't cause a SysTick
121+
// interrupt and loads the reload value on the next cycle.
119122
self.systick.clear_current();
120123
}
121124

@@ -124,23 +127,27 @@ impl<const TIMER_HZ: u32> Monotonic for DwtSystick<TIMER_HZ> {
124127
Self::Instant::from_ticks(0)
125128
}
126129

127-
#[cfg(feature = "extend")]
128-
fn disable_timer(&mut self) {
129-
// Do not disable but set a maximum reload value.
130-
self.systick.set_reload(0xff_ffff);
131-
// Also clear the current counter since.
132-
// That doesn't cause a SysTick interrupt and loads the reload
133-
// value on the next cycle.
134-
self.systick.clear_current();
130+
#[inline(always)]
131+
fn clear_compare_flag(&mut self) {
132+
// SysTick exceptions don't need flag clearing.
133+
//
134+
// But when extending the cycle counter range, we need to keep
135+
// the interrupts enabled to detect overflow.
136+
// This function is always called in the interrupt handler early.
137+
// Reset a maximum reload value in case `set_compare()` is not called.
138+
// Otherwise the interrupt would keep firing at the previous set
139+
// interval.
140+
#[cfg(feature = "extend")]
141+
{
142+
self.systick.set_reload(0xff_ffff);
143+
self.systick.clear_current();
144+
}
135145
}
136146

137147
#[cfg(feature = "extend")]
138148
fn on_interrupt(&mut self) {
139149
// Ensure `now()` is called regularly to track overflows.
140150
// Since SysTick is narrower than CYCCNT, this is sufficient.
141-
// TODO: check whether this could be moved to `disable_timer()`
142-
// as that's the complementary code branch to `set_compare()`
143-
// (which already calls `now()`).
144151
self.now();
145152
}
146153
}

0 commit comments

Comments
 (0)