@@ -16,6 +16,15 @@ pub struct Delay {
16
16
17
17
impl Delay {
18
18
/// Configures the system timer (SysTick) as a delay provider
19
+ ///
20
+ /// # Limitations
21
+ ///
22
+ /// Depending on the core clock, this delay provider
23
+ /// can delay between 1 minute (for 72 Mhz) up to almost 9 minutes (for 8 Mhz).
24
+ /// Higher input values will be capped to these limits.
25
+ ///
26
+ /// For accuracy purposes and because this is a blocking, busy-waiting function,
27
+ /// if delays in the second to minute range are needed, use timers instead.
19
28
pub fn new ( mut syst : SYST , clocks : Clocks ) -> Self {
20
29
syst. set_clock_source ( SystClkSource :: Core ) ;
21
30
@@ -30,7 +39,7 @@ impl Delay {
30
39
31
40
impl DelayMs < u32 > for Delay {
32
41
fn delay_ms ( & mut self , ms : u32 ) {
33
- self . delay_us ( ms * 1_000 ) ;
42
+ self . delay_us ( ms. saturating_mul ( 1_000 ) ) ;
34
43
}
35
44
}
36
45
@@ -48,17 +57,36 @@ impl DelayMs<u8> for Delay {
48
57
49
58
impl DelayUs < u32 > for Delay {
50
59
fn delay_us ( & mut self , us : u32 ) {
51
- let rvr = us * ( self . clocks . sysclk ( ) . 0 / 1_000_000 ) ;
52
-
53
- crate :: assert!( rvr < ( 1 << 24 ) ) ;
54
-
55
- self . syst . set_reload ( rvr) ;
56
- self . syst . clear_current ( ) ;
57
- self . syst . enable_counter ( ) ;
58
-
59
- while !self . syst . has_wrapped ( ) { }
60
-
61
- self . syst . disable_counter ( ) ;
60
+ // The RVR register is 24 bits wide, as SysTick is based on a 24 bit counter
61
+ const MAX_RVR : u32 = 1 << 24 ;
62
+
63
+ // Depending on hclk (core clock), this 32 bit value allows
64
+ // delays between 1 min to 9 min.
65
+ //
66
+ // (((32^2) - 1) / 72) µs ~ 59.6 seconds
67
+ // (((32^2) - 1) / 8) µs ~ 536.8 seconds
68
+ let mut total_rvr = us. saturating_mul ( self . clocks . hclk ( ) . 0 / 1_000_000 ) ;
69
+
70
+ // Use the full 32 bit range to allow longer delays
71
+ //
72
+ // Like dividing total_rvr / MAX_RVR
73
+ // and delaying by MAX_RVR * (fraction).
74
+ while total_rvr != 0 {
75
+ let current_rvr = if total_rvr < MAX_RVR {
76
+ total_rvr
77
+ } else {
78
+ MAX_RVR
79
+ } ;
80
+ total_rvr -= current_rvr;
81
+
82
+ self . syst . set_reload ( current_rvr) ;
83
+ self . syst . clear_current ( ) ;
84
+ self . syst . enable_counter ( ) ;
85
+
86
+ while !self . syst . has_wrapped ( ) { }
87
+
88
+ self . syst . disable_counter ( ) ;
89
+ }
62
90
}
63
91
}
64
92
0 commit comments