Skip to content

Commit

Permalink
delay: Add delay module
Browse files Browse the repository at this point in the history
  • Loading branch information
astapleton committed Oct 4, 2024
1 parent 7a77a37 commit d894ad9
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 9 deletions.
20 changes: 11 additions & 9 deletions examples/blinky.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,36 @@
mod utilities;

use cortex_m_rt::entry;
use stm32h5xx_hal::{pac, prelude::*};
use embedded_hal::delay::DelayNs;
use fugit::SecsDurationU32;
use stm32h5xx_hal::{delay::Delay, pac, prelude::*, rcc::ResetEnable};

#[entry]
fn main() -> ! {
utilities::logger::init();

let cp = cortex_m::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();

let pwr = dp.PWR.constrain();
let pwrcfg = pwr.vos0().freeze();

// Constrain and Freeze clock
let rcc = dp.RCC.constrain();
let _ccdr = rcc.sys_ck(250.MHz()).freeze(pwrcfg, &dp.SBS);
let ccdr = rcc.sys_ck(250.MHz()).freeze(pwrcfg, &dp.SBS);

ccdr.peripheral.GPIOA.enable();

dp.GPIOA.moder().write(|w| w.mode5().output()); // output
dp.GPIOA.pupdr().write(|w| w.pupd5().pull_up()); // pull-up

// dp.GPIOA.odr.write(|w| w.od5().set_bit());
let mut delay = Delay::new(cp.SYST, &ccdr.clocks);
let duration = SecsDurationU32::secs(1).to_millis();

loop {
dp.GPIOA.odr().write(|w| w.od5().low());
for _ in 0..10_000 {
cortex_m::asm::nop();
}
delay.delay_ns(duration);
dp.GPIOA.odr().write(|w| w.od5().high());
for _ in 0..10_000 {
cortex_m::asm::nop();
}
delay.delay_ns(duration);
}
}
112 changes: 112 additions & 0 deletions src/delay.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//! Delay providers
//!
//! # Examples
//!
//! ## Delay
//!
//! ```no_run
//! let mut delay = Delay::new(core.SYST, device.clocks);
//!
//! delay.delay_ms(500);
//!
//! // Release SYST from the delay
//! let syst = delay.free();
//! ```
//!
//! # Examples
//!
//! - [Blinky](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/blinky.rs)

use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use embedded_hal::delay::DelayNs;
use fugit::SecsDurationU64;

use crate::rcc::CoreClocks;

const SYSTICK_HCLK_DIV: u32 = 8;

pub trait DelayExt {
fn delay(self, clocks: &CoreClocks) -> Delay;
}

impl DelayExt for SYST {
fn delay(self, clocks: &CoreClocks) -> Delay {
Delay::new(self, clocks)
}
}

/// System timer (SysTick) as a delay provider
pub struct Delay {
hclk_hz: u32,
syst: SYST,
}
fn calc_rvr(ns: u32, hclk: u32) -> u32 {
// Default is for SYSTICK to be fed by HCLK/8
let ticks: u64 = (SecsDurationU64::secs(1) * SYSTICK_HCLK_DIV).to_nanos();
((ns as u64 * hclk as u64) / ticks) as u32
}

impl Delay {
/// Configures the system timer (SysTick) as a delay provider
pub fn new(mut syst: SYST, clocks: &CoreClocks) -> Self {
syst.set_clock_source(SystClkSource::External);

Delay {
hclk_hz: clocks.hclk().raw(),
syst,
}
}

/// Releases the system timer (SysTick) resource
pub fn free(self) -> SYST {
self.syst
}
}

impl DelayNs for Delay {
fn delay_ns(&mut self, ns: u32) {
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
const MAX_RVR: u32 = 0x00FF_FFFF;

let mut total_rvr = calc_rvr(ns, self.hclk_hz);

while total_rvr != 0 {
let current_rvr = if total_rvr <= MAX_RVR {
total_rvr
} else {
MAX_RVR
};

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

// Update the tracking variable while we are waiting...
total_rvr -= current_rvr;

while !self.syst.has_wrapped() {}

self.syst.disable_counter();
}
}
}

#[cfg(test)]
mod tests {
use super::calc_rvr;
#[test]
fn test_calc_rvr() {
let rvr = calc_rvr(1000, 8_000_000);
assert_eq!(rvr, 1);

let rvr = calc_rvr(1000_000, 8_000_000);
assert_eq!(rvr, 1000);

let rvr = calc_rvr(1000_000, 10_000_000);
assert_eq!(rvr, 1250);

let rvr = calc_rvr(1000_000, 250_000_000);
assert_eq!(rvr, 31250);
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ pub mod time;

#[cfg(feature = "device-selected")]
pub mod rcc;

#[cfg(feature = "device-selected")]
pub mod delay;
2 changes: 2 additions & 0 deletions src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Prelude

pub use crate::delay::DelayExt as _stm32h5xx_hal_delay_DelayExt;
pub use crate::pwr::PwrExt as _stm32h5xx_hal_pwr_PwrExt;
pub use crate::rcc::RccExt as _stm32h5xx_hal_rcc_RccExt;

pub use crate::time::U32Ext as _;
pub use fugit::{ExtU32 as _, RateExtU32 as _};

0 comments on commit d894ad9

Please sign in to comment.