@@ -43,7 +43,17 @@ use cortex_m::peripheral::SYST;
43
43
use embedded_hal:: delay:: DelayNs ;
44
44
use void:: Void ;
45
45
46
+ use crate :: block;
46
47
use crate :: rcc:: CoreClocks ;
48
+ use crate :: stm32:: { LPTIM1 , LPTIM2 , LPTIM3 } ;
49
+ #[ cfg( not( feature = "rm0455" ) ) ]
50
+ use crate :: stm32:: { LPTIM4 , LPTIM5 } ;
51
+ use crate :: stm32:: {
52
+ TIM1 , TIM12 , TIM13 , TIM14 , TIM15 , TIM16 , TIM17 , TIM2 , TIM3 , TIM4 , TIM5 ,
53
+ TIM6 , TIM7 , TIM8 ,
54
+ } ;
55
+ use crate :: time:: Hertz ;
56
+ use crate :: timer:: { Enabled , LpTimer , Timer } ;
47
57
48
58
pub trait DelayExt {
49
59
fn delay ( self , clocks : CoreClocks ) -> Delay ;
@@ -211,3 +221,75 @@ impl DelayNs for Delay {
211
221
self . systick_delay_cycles ( total_rvr) ;
212
222
}
213
223
}
224
+
225
+ /// Delay that implements [embedded_hal::blocking::delay] traits
226
+ pub struct DelayFromCountDownTimer < TIM > ( TIM ) ;
227
+
228
+ impl < TIM > DelayFromCountDownTimer < TIM > {
229
+ /// Creates a delay from a timer resource
230
+ pub fn new ( timer : TIM ) -> Self {
231
+ Self ( timer)
232
+ }
233
+ /// Free the timer resource for other uses
234
+ pub fn free ( self ) -> TIM {
235
+ self . 0
236
+ }
237
+ }
238
+
239
+ macro_rules! impl_delay_from_count_down_timer {
240
+ ( $( $TIMX: ty) ,+) => {
241
+ $(
242
+ impl DelayFromCountDownTimer <$TIMX>
243
+ {
244
+ fn delay_us_internal( & mut self , t: u32 ) {
245
+ let mut time_left = t;
246
+
247
+ // Due to the LpTimer having only a 3 bit scaler, it is
248
+ // possible that the max timeout we can set is
249
+ // (128 * 65536) / clk_hz milliseconds.
250
+ // Assuming the fastest clk_hz = 480Mhz this is roughly ~17ms,
251
+ // or a frequency of ~57.2Hz. We use a 60Hz frequency for each
252
+ // loop step here to ensure that we stay within these bounds.
253
+ let looping_delay = 1_000_000 / 60 ;
254
+ let looping_delay_hz = Hertz :: from_raw( 1_000_000 / looping_delay) ;
255
+
256
+ let _ = self . 0 . start( looping_delay_hz) ; // This method is infallible
257
+ while time_left > looping_delay {
258
+ block!( self . 0 . wait( ) ) . ok( ) ;
259
+ time_left -= looping_delay;
260
+ }
261
+
262
+ if time_left > 0 {
263
+ // This method is infallible
264
+ let _ = self . 0 . start( Hertz :: from_raw( 1_000_000 / time_left) ) ;
265
+ block!( self . 0 . wait( ) ) . ok( ) ;
266
+ }
267
+ }
268
+ }
269
+
270
+ impl DelayNs for DelayFromCountDownTimer <$TIMX> {
271
+ fn delay_ns( & mut self , ns: u32 ) {
272
+ // TODO(): This delay is 1000x longer than the intended duration!
273
+ self . delay_us_internal( ns) ;
274
+ }
275
+ fn delay_us( & mut self , us: u32 ) {
276
+ self . delay_us_internal( us) ;
277
+ }
278
+ }
279
+ ) +
280
+ }
281
+ }
282
+
283
+ impl_delay_from_count_down_timer ! {
284
+ Timer <TIM1 >, Timer <TIM8 >,
285
+ Timer <TIM2 >, Timer <TIM3 >, Timer <TIM4 >,
286
+ Timer <TIM5 >, Timer <TIM6 >, Timer <TIM7 >,
287
+ Timer <TIM12 >, Timer <TIM13 >, Timer <TIM14 >, Timer <TIM15 >, Timer <TIM16 >, Timer <TIM17 >
288
+ }
289
+ impl_delay_from_count_down_timer ! {
290
+ LpTimer <LPTIM1 , Enabled >, LpTimer <LPTIM2 , Enabled >, LpTimer <LPTIM3 , Enabled >
291
+ }
292
+ #[ cfg( not( feature = "rm0455" ) ) ]
293
+ impl_delay_from_count_down_timer ! {
294
+ LpTimer <LPTIM4 , Enabled >, LpTimer <LPTIM5 , Enabled >
295
+ }
0 commit comments