@@ -16,6 +16,15 @@ pub struct Delay {
1616
1717impl Delay {
1818 /// 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.
1928 pub fn new ( mut syst : SYST , clocks : Clocks ) -> Self {
2029 syst. set_clock_source ( SystClkSource :: Core ) ;
2130
@@ -30,7 +39,7 @@ impl Delay {
3039
3140impl DelayMs < u32 > for Delay {
3241 fn delay_ms ( & mut self , ms : u32 ) {
33- self . delay_us ( ms * 1_000 ) ;
42+ self . delay_us ( ms. saturating_mul ( 1_000 ) ) ;
3443 }
3544}
3645
@@ -48,17 +57,36 @@ impl DelayMs<u8> for Delay {
4857
4958impl DelayUs < u32 > for Delay {
5059 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+ }
6290 }
6391}
6492
0 commit comments