Skip to content

Commit

Permalink
Increase SysTick delay limit
Browse files Browse the repository at this point in the history
Leverage a full 32 bit range instead of only 24 bit range.
This will increase the maximum possible delay from ~2 seconds
up to 9 minutes.

Also cap the value, instead of panicking, if the value is to high.

Fixes stm32-rs#203
  • Loading branch information
Sh3Rm4n committed Mar 9, 2021
1 parent 9e29ec6 commit 1610232
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- Added support for more CAN bit rates and modes. ([#186](https://github.com/stm32-rs/stm32f3xx-hal/pull/186)
- Added support for more CAN bit rates and modes. ([#186])

### Fixed

- Delay based on systick no longer panics ([#203]) for to high values
and support longer delays ([#208])

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

Expand Down Expand Up @@ -266,6 +271,9 @@ let clocks = rcc

- Support `stm32f303` device

[#184]: https://github.com/stm32-rs/stm32f3xx-hal/pull/208
[#184]: https://github.com/stm32-rs/stm32f3xx-hal/issues/203
[#184]: https://github.com/stm32-rs/stm32f3xx-hal/pull/186
[#184]: https://github.com/stm32-rs/stm32f3xx-hal/pull/184
[#172]: https://github.com/stm32-rs/stm32f3xx-hal/pull/172
[#170]: https://github.com/stm32-rs/stm32f3xx-hal/pull/170
Expand Down
52 changes: 40 additions & 12 deletions src/delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ pub struct Delay {

impl Delay {
/// Configures the system timer (SysTick) as a delay provider
///
/// # Limitations
///
/// Depending on the core clock, this delay provider
/// can delay between 1 minute (for 72 Mhz) up to almost 9 minutes (for 8 Mhz).
/// Higher input values will be capped to these limits.
///
/// For accuracy purposes and because this is a blocking, busy-waiting function,
/// if delays in the second to minute range are needed, use timers instead.
pub fn new(mut syst: SYST, clocks: Clocks) -> Self {
syst.set_clock_source(SystClkSource::Core);

Expand All @@ -30,7 +39,7 @@ impl Delay {

impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
self.delay_us(ms.saturating_mul(1_000));
}
}

Expand All @@ -48,17 +57,36 @@ impl DelayMs<u8> for Delay {

impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
let rvr = us * (self.clocks.sysclk().0 / 1_000_000);

crate::assert!(rvr < (1 << 24));

self.syst.set_reload(rvr);
self.syst.clear_current();
self.syst.enable_counter();

while !self.syst.has_wrapped() {}

self.syst.disable_counter();
// The RVR register is 24 bits wide, as SysTick is based on a 24 bit counter
const MAX_RVR: u32 = 1 << 24;

// Depending on hclk (core clock), this 32 bit value allows
// delays between 1 min to 9 min.
//
// (((32^2) - 1) / 72) µs ~ 59.6 seconds
// (((32^2) - 1) / 8) µs ~ 536.8 seconds
let mut total_rvr = us.saturating_mul(self.clocks.hclk().0 / 1_000_000);

// Use the full 32 bit range to allow longer delays
//
// Like dividing total_rvr / MAX_RVR
// and delaying by MAX_RVR * (fraction).
while total_rvr != 0 {
let current_rvr = if total_rvr < MAX_RVR {
total_rvr
} else {
MAX_RVR
};
total_rvr -= current_rvr;

self.syst.set_reload(current_rvr);
self.syst.clear_current();
self.syst.enable_counter();

while !self.syst.has_wrapped() {}

self.syst.disable_counter();
}
}
}

Expand Down

0 comments on commit 1610232

Please sign in to comment.