Skip to content

Commit dbadc66

Browse files
authored
Merge pull request #208 from Sh3Rm4n/delay
Increase SysTick delay limit
2 parents 9e29ec6 + bc8bab8 commit dbadc66

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Changed
1111

12-
- Added support for more CAN bit rates and modes. ([#186](https://github.com/stm32-rs/stm32f3xx-hal/pull/186)
12+
- Added support for more CAN bit rates and modes. ([#186])
13+
14+
### Fixed
15+
16+
- Delay based on systick no longer panics ([#203]) for to high values
17+
and support longer delays ([#208])
1318

1419
## [v0.6.1] - 2020-12-10
1520

@@ -266,6 +271,9 @@ let clocks = rcc
266271

267272
- Support `stm32f303` device
268273

274+
[#208]: https://github.com/stm32-rs/stm32f3xx-hal/pull/208
275+
[#203]: https://github.com/stm32-rs/stm32f3xx-hal/issues/203
276+
[#186]: https://github.com/stm32-rs/stm32f3xx-hal/pull/186
269277
[#184]: https://github.com/stm32-rs/stm32f3xx-hal/pull/184
270278
[#172]: https://github.com/stm32-rs/stm32f3xx-hal/pull/172
271279
[#170]: https://github.com/stm32-rs/stm32f3xx-hal/pull/170

src/delay.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ pub struct Delay {
1616

1717
impl 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

3140
impl 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

4958
impl 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

Comments
 (0)