@@ -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