Skip to content

Commit d9a66bb

Browse files
committed
impl countdown
1 parent f90cf59 commit d9a66bb

File tree

1 file changed

+88
-4
lines changed

1 file changed

+88
-4
lines changed

src/delay.rs

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@
3737
use cast::u32;
3838
use cortex_m::peripheral::syst::SystClkSource;
3939
use cortex_m::peripheral::SYST;
40-
41-
use crate::nb::block;
42-
use crate::rcc::CoreClocks;
43-
use crate::time::{Hertz, U32Ext};
4440
use embedded_hal::{
4541
blocking::delay::{DelayMs, DelayUs},
4642
timer::CountDown,
4743
};
44+
use void::Void;
45+
46+
use crate::nb::block;
47+
use crate::rcc::CoreClocks;
48+
use crate::time::{Hertz, U32Ext};
4849

4950
pub trait DelayExt {
5051
fn delay(self, clocks: CoreClocks) -> Delay;
@@ -62,6 +63,89 @@ pub struct Delay {
6263
syst: SYST,
6364
}
6465

66+
/// Implements [CountDown](embedded_hal::timer::CountDown) for the System timer (SysTick).
67+
/// Time is measured in microseconds
68+
pub struct CountdownUs<'a> {
69+
clocks: CoreClocks,
70+
syst: &'a mut SYST,
71+
total_rvr: u64,
72+
finished: bool,
73+
}
74+
75+
impl<'a> CountdownUs<'a> {
76+
/// Create a new [CountDown] measured in microseconds.
77+
pub fn new(syst: &'a mut SYST, clocks: CoreClocks) -> Self {
78+
Self {
79+
syst,
80+
clocks,
81+
total_rvr: 0,
82+
finished: true,
83+
}
84+
}
85+
86+
/// start a wait cycle and sets finished to true if [CountdownUs] is done waiting.
87+
fn start_wait(&mut self) {
88+
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
89+
const MAX_RVR: u32 = 0x00FF_FFFF;
90+
91+
if self.total_rvr != 0 {
92+
self.finished = false;
93+
let current_rvr = if self.total_rvr <= MAX_RVR.into() {
94+
self.total_rvr as u32
95+
} else {
96+
MAX_RVR
97+
};
98+
99+
self.syst.set_reload(current_rvr);
100+
self.syst.clear_current();
101+
self.syst.enable_counter();
102+
103+
self.total_rvr -= current_rvr as u64;
104+
} else {
105+
self.finished = true;
106+
}
107+
}
108+
}
109+
110+
impl<'a> CountDown for CountdownUs<'a> {
111+
type Time = u32;
112+
113+
fn start<T>(&mut self, count: T)
114+
where
115+
T: Into<Self::Time>,
116+
{
117+
let us = count.into();
118+
119+
// With c_ck up to 480e6, we need u64 for delays > 8.9s
120+
121+
self.total_rvr = if cfg!(not(feature = "revision_v")) {
122+
// See errata ES0392 §2.2.3. Revision Y does not have the /8 divider
123+
u64::from(us) * u64::from(self.clocks.c_ck().0 / 1_000_000)
124+
} else if cfg!(feature = "cm4") {
125+
// CM4 dervived from HCLK
126+
u64::from(us) * u64::from(self.clocks.hclk().0 / 8_000_000)
127+
} else {
128+
// Normally divide by 8
129+
u64::from(us) * u64::from(self.clocks.c_ck().0 / 8_000_000)
130+
};
131+
132+
self.start_wait();
133+
}
134+
135+
fn wait(&mut self) -> nb::Result<(), Void> {
136+
if self.finished {
137+
return Ok(());
138+
}
139+
140+
if self.syst.has_wrapped() {
141+
self.syst.disable_counter();
142+
self.start_wait();
143+
}
144+
145+
Err(nb::Error::WouldBlock)
146+
}
147+
}
148+
65149
impl Delay {
66150
/// Configures the system timer (SysTick) as a delay provider
67151
pub fn new(mut syst: SYST, clocks: CoreClocks) -> Self {

0 commit comments

Comments
 (0)