9
9
use core:: convert:: { From , TryFrom } ;
10
10
11
11
use cortex_m:: peripheral:: DWT ;
12
+ #[ cfg( feature = "enumset" ) ]
13
+ use enumset:: { EnumSet , EnumSetType } ;
12
14
use void:: Void ;
13
15
14
16
use crate :: hal:: timer:: { CountDown , Periodic } ;
@@ -120,6 +122,11 @@ pub struct Timer<TIM> {
120
122
}
121
123
122
124
/// Interrupt events
125
+ #[ derive( Debug ) ]
126
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
127
+ #[ cfg_attr( feature = "enumset" , derive( EnumSetType ) ) ]
128
+ #[ cfg_attr( not( feature = "enumset" ) , derive( Copy , Clone , PartialEq , Eq ) ) ]
129
+ #[ non_exhaustive]
123
130
pub enum Event {
124
131
/// Timer timed out / count down ended
125
132
Update ,
@@ -169,7 +176,7 @@ macro_rules! hal {
169
176
// The above line raises an update event which will indicate
170
177
// that the timer is already finished. Since this is not the case,
171
178
// it should be cleared
172
- self . clear_update_interrupt_flag ( ) ;
179
+ self . clear_event ( Event :: Update ) ;
173
180
174
181
// start counter
175
182
self . tim. cr1. modify( |_, w| w. cen( ) . enabled( ) ) ;
@@ -179,7 +186,7 @@ macro_rules! hal {
179
186
if self . tim. sr. read( ) . uif( ) . is_clear( ) {
180
187
Err ( nb:: Error :: WouldBlock )
181
188
} else {
182
- self . clear_update_interrupt_flag ( ) ;
189
+ self . clear_event ( Event :: Update ) ;
183
190
Ok ( ( ) )
184
191
}
185
192
}
@@ -202,32 +209,95 @@ macro_rules! hal {
202
209
timer
203
210
}
204
211
205
- /// Starts listening for an `event`
206
- pub fn listen( & mut self , event: Event ) {
212
+ /// Stops the timer
213
+ #[ inline]
214
+ pub fn stop( & mut self ) {
215
+ self . tim. cr1. modify( |_, w| w. cen( ) . disabled( ) ) ;
216
+ }
217
+
218
+ /// Enable or disable the interrupt for the specified [`Event`].
219
+ #[ inline]
220
+ pub fn enable_interrupt( & mut self , event: Event ) {
221
+ self . configure_interrupt( event, true ) ;
222
+ }
223
+
224
+ /// Enable or disable the interrupt for the specified [`Event`].
225
+ #[ inline]
226
+ pub fn disable_interrupt( & mut self , event: Event ) {
227
+ self . configure_interrupt( event, false ) ;
228
+ }
229
+
230
+
231
+ // TODO(Sh3Rm4n): After macro -> Instance refactor introduce associated const INTERRUPT.
232
+ // /// Get the correspoing Interrupt number
233
+ // // pub fn nvic() -> Interrupt { }
234
+
235
+ /// Enable or disable the interrupt for the specified [`Event`].
236
+ #[ inline]
237
+ pub fn configure_interrupt( & mut self , event: Event , enable: bool ) {
207
238
match event {
208
- Event :: Update => self . tim. dier. write( |w| w. uie( ) . enabled( ) ) ,
239
+ Event :: Update => self . tim. dier. write( |w| w. uie( ) . bit( enable) ) ,
240
+ }
241
+ }
242
+
243
+ /// Enable or disable interrupt for the specified [`Event`]s.
244
+ ///
245
+ /// Like [`Timer::configure_interrupt`], but instead using an enumset. The corresponding
246
+ /// interrupt for every [`Event`] in the set will be enabled, every other interrupt will be
247
+ /// **disabled**.
248
+ #[ cfg( feature = "enumset" ) ]
249
+ #[ cfg_attr( docsrs, doc( cfg( feature = "enumset" ) ) ) ]
250
+ pub fn configure_interrupts( & mut self , events: EnumSet <Event >) -> & mut Self {
251
+ for event in events. complement( ) . iter( ) {
252
+ self . configure_interrupt( event, false ) ;
253
+ }
254
+ for event in events. iter( ) {
255
+ self . configure_interrupt( event, true ) ;
209
256
}
257
+
258
+ self
210
259
}
211
260
212
- /// Stops listening for an ` event`
213
- pub fn unlisten ( & mut self , event: Event ) {
261
+ /// Check if an interrupt event happend.
262
+ pub fn is_event_triggered ( & self , event: Event ) -> bool {
214
263
match event {
215
- Event :: Update => self . tim. dier . write ( |w| w . uie ( ) . disabled ( ) ) ,
264
+ Event :: Update => self . tim. sr . read ( ) . uif ( ) . bit ( ) ,
216
265
}
217
266
}
218
267
219
- /// Stops the timer
220
- pub fn stop( & mut self ) {
221
- self . tim. cr1. modify( |_, w| w. cen( ) . disabled( ) ) ;
268
+ /// Get an [`EnumSet`] of all fired interrupt events.
269
+ #[ cfg( feature = "enumset" ) ]
270
+ #[ cfg_attr( docsrs, doc( cfg( feature = "enumset" ) ) ) ]
271
+ pub fn triggered_events( & self ) -> EnumSet <Event > {
272
+ let mut events = EnumSet :: new( ) ;
273
+
274
+ for event in EnumSet :: <Event >:: all( ) . iter( ) {
275
+ if self . is_event_triggered( event) {
276
+ events |= event;
277
+ }
278
+ }
279
+
280
+ events
281
+ }
282
+
283
+ /// Clear the given interrupt event flag.
284
+ #[ inline]
285
+ pub fn clear_event( & mut self , event: Event ) {
286
+ match event {
287
+ Event :: Update => self . tim. sr. modify( |_, w| w. uif( ) . clear( ) ) ,
288
+ }
222
289
}
223
290
224
- /// Clears Update Interrupt Flag
225
- pub fn clear_update_interrupt_flag( & mut self ) {
226
- self . tim. sr. modify( |_, w| w. uif( ) . clear( ) ) ;
291
+ /// Clear **all** interrupt events.
292
+ #[ inline]
293
+ pub fn clear_events( & mut self ) {
294
+ // SAFETY: This atomic write clears all flags and ignores the reserverd bit fields.
295
+ self . tim. sr. write( |w| unsafe { w. bits( 0 ) } ) ;
227
296
}
228
297
229
298
/// Releases the TIM peripheral
230
- pub fn release( mut self ) -> $TIMX {
299
+ #[ inline]
300
+ pub fn free( mut self ) -> $TIMX {
231
301
self . stop( ) ;
232
302
self . tim
233
303
}
0 commit comments