Skip to content

Commit 0b7252e

Browse files
committed
delay: temporary DelayNs impl (μs-resolution)
1 parent 5c738d1 commit 0b7252e

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

examples/blinky_delay.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use hal::stm32;
1111
use hal::time::ExtU32;
1212
use hal::timer::Timer;
1313
use stm32g4xx_hal as hal;
14+
use embedded_hal_one::delay::DelayNs;
1415

1516
use cortex_m_rt::entry;
1617
use utils::logger::info;
@@ -47,6 +48,6 @@ fn main() -> ! {
4748
info!("Toggle");
4849
led.toggle().unwrap();
4950
info!("TIM2 delay");
50-
delay_tim2.delay_ms(1000_u16);
51+
DelayNs::delay_ms(&mut delay_tim2, 1000);
5152
}
5253
}

src/delay.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ use crate::rcc::Clocks;
4040
use crate::time::MicroSecond;
4141
pub use cortex_m::delay::*;
4242
use cortex_m::peripheral::SYST;
43+
use fugit::ExtU32Ceil;
4344

4445
use crate::nb::block;
4546
use crate::time::ExtU32;
4647
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
48+
use embedded_hal_one::delay::DelayNs;
4749

4850
pub trait CountDown: embedded_hal::timer::CountDown {
4951
fn max_period(&self) -> MicroSecond;
@@ -132,7 +134,7 @@ macro_rules! impl_delay_from_count_down_timer {
132134
T: CountDown<Time = MicroSecond>,
133135
{
134136
fn $delay(&mut self, t: u16) {
135-
self.$delay(t as u32);
137+
$Delay::$delay(self, t as u32);
136138
}
137139
}
138140

@@ -141,7 +143,7 @@ macro_rules! impl_delay_from_count_down_timer {
141143
T: CountDown<Time = MicroSecond>,
142144
{
143145
fn $delay(&mut self, t: u8) {
144-
self.$delay(t as u32);
146+
$Delay::$delay(self, t as u32);
145147
}
146148
}
147149
)+
@@ -152,3 +154,34 @@ impl_delay_from_count_down_timer! {
152154
(DelayMs, delay_ms, 1_000),
153155
(DelayUs, delay_us, 1)
154156
}
157+
158+
// TODO: decouple the timer API from embedded-hal 0.2, stm32f4xx-hal with constant timer
159+
// frequencies looks like a good example
160+
impl<T: CountDown<Time = MicroSecond>> DelayNs for DelayFromCountDownTimer<T> {
161+
// From a quick look at the clock diagram timer resolution can go down to ~3ns on most timers
162+
// 170MHz (PLL-R as SysClk) / 1 (AHB Prescaler) / 1 (APBx prescaler) * 2 = 340MHz timer clock
163+
// TODO: the current fallback to 1us resolution is a stopgap until the module is reworked
164+
fn delay_ns(&mut self, ns: u32) {
165+
DelayNs::delay_us(self, ns.div_ceil(1000))
166+
}
167+
fn delay_us(&mut self, mut us: u32) {
168+
let max_sleep = self.0.max_period();
169+
let max_us = max_sleep.to_micros();
170+
171+
while us > max_us {
172+
self.0.start(max_us.micros_at_least());
173+
let _ = nb::block!(self.0.wait());
174+
us -= max_us;
175+
}
176+
self.0.start(us.micros_at_least());
177+
let _ = nb::block!(self.0.wait());
178+
}
179+
fn delay_ms(&mut self, mut ms: u32) {
180+
const MAX_MILLIS: u32 = u32::MAX / 1000;
181+
while ms > MAX_MILLIS {
182+
ms -= MAX_MILLIS;
183+
DelayNs::delay_us(self, MAX_MILLIS * 1000);
184+
}
185+
DelayNs::delay_us(self, ms * 1000);
186+
}
187+
}

src/time.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,17 @@ impl U32Ext for u32 {
101101
}
102102
}
103103

104-
pub fn duration(hz: Hertz, cycles: u32) -> MicroSecond {
104+
pub fn duration<const NOM: u32, const DENOM: u32>(hz: Hertz, cycles: u32) -> Duration<u32, NOM, DENOM> {
105105
let cycles = cycles as u64;
106106
let clk = hz.raw() as u64;
107-
let us = cycles.saturating_mul(1_000_000_u64) / clk;
108-
MicroSecond::from_ticks(us as u32)
107+
let us = cycles.saturating_mul(DENOM as u64) / clk / NOM as u64;
108+
Duration::<u32, NOM, DENOM>::from_ticks(us as u32)
109109
}
110110

111-
pub fn cycles(ms: MicroSecond, clk: Hertz) -> u32 {
111+
pub fn cycles<const NOM: u32, const DENOM: u32>(ms: Duration<u32, NOM, DENOM>, clk: Hertz) -> u32 {
112112
assert!(ms.ticks() > 0);
113113
let clk = clk.raw() as u64;
114114
let period = ms.ticks() as u64;
115-
let cycles = clk.saturating_mul(period) / 1_000_000_u64;
115+
let cycles = clk.saturating_mul(period).saturating_mul(NOM as u64) / DENOM as u64;
116116
cycles as u32
117117
}

0 commit comments

Comments
 (0)