|
|
|
@ -33,22 +33,24 @@ use crate::rcc::Clocks;
|
|
|
|
|
use embedded_hal::blocking::delay::{DelayMs, DelayUs}; |
|
|
|
|
|
|
|
|
|
/// System timer (SysTick) as a delay provider
|
|
|
|
|
#[derive(Clone)] |
|
|
|
|
pub struct Delay { |
|
|
|
|
clocks: Clocks, |
|
|
|
|
syst: SYST, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const MAX_SYSTICK: u32 = 0x00FF_FFFF; |
|
|
|
|
|
|
|
|
|
impl Delay { |
|
|
|
|
/// Configures the system timer (SysTick) as a delay provider
|
|
|
|
|
pub fn new(mut syst: SYST, clocks: Clocks) -> Self { |
|
|
|
|
/// As access to the count register is possible without a reference, we can
|
|
|
|
|
/// just drop it
|
|
|
|
|
pub fn new(mut syst: SYST, clocks: Clocks) -> Delay { |
|
|
|
|
syst.set_clock_source(SystClkSource::Core); |
|
|
|
|
|
|
|
|
|
Delay { syst, clocks } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Releases the system timer (SysTick) resource
|
|
|
|
|
pub fn free(self) -> SYST { |
|
|
|
|
self.syst |
|
|
|
|
syst.set_reload(MAX_SYSTICK); |
|
|
|
|
syst.clear_current(); |
|
|
|
|
syst.enable_counter(); |
|
|
|
|
Delay { clocks } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -79,10 +81,11 @@ impl DelayMs<u8> for Delay {
|
|
|
|
|
impl DelayUs<u32> for Delay { |
|
|
|
|
fn delay_us(&mut self, us: u32) { |
|
|
|
|
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
|
|
|
|
|
const MAX_RVR: u32 = 0x00FF_FFFF; |
|
|
|
|
// Here less than maximum is used so we have some play if there's a long running interrupt.
|
|
|
|
|
const MAX_RVR: u32 = 0x007F_FFFF; |
|
|
|
|
|
|
|
|
|
let mut total_rvr = if self.clocks.sysclk().0 < 1_000_000 { |
|
|
|
|
us / (1_000_00 / self.clocks.sysclk().0) |
|
|
|
|
us / (1_000_000 / self.clocks.sysclk().0) |
|
|
|
|
} else { |
|
|
|
|
us * (self.clocks.sysclk().0 / 1_000_000) |
|
|
|
|
}; |
|
|
|
@ -94,16 +97,9 @@ impl DelayUs<u32> for Delay {
|
|
|
|
|
MAX_RVR |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
self.syst.set_reload(current_rvr); |
|
|
|
|
self.syst.clear_current(); |
|
|
|
|
self.syst.enable_counter(); |
|
|
|
|
|
|
|
|
|
// Update the tracking variable while we are waiting...
|
|
|
|
|
let start_count = SYST::get_current(); |
|
|
|
|
total_rvr -= current_rvr; |
|
|
|
|
|
|
|
|
|
while !self.syst.has_wrapped() {} |
|
|
|
|
|
|
|
|
|
self.syst.disable_counter(); |
|
|
|
|
while ((start_count - SYST::get_current()) % MAX_SYSTICK) < current_rvr {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|