Skip to content

Commit 24f8d16

Browse files
committed
both embedded-hals for Delay
1 parent d9e135f commit 24f8d16

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

src/delay/hal_1.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//! Delay implementation based on general-purpose 32 bit timers and System timer (SysTick).
2+
//!
3+
//! TIM2 and TIM5 are a general purpose 32-bit auto-reload up/downcounter with
4+
//! a 16-bit prescaler.
5+
6+
use cast::u16;
7+
use core::convert::Infallible;
8+
use cortex_m::peripheral::SYST;
9+
use embedded_hal_one::delay::blocking::DelayUs;
10+
11+
use super::{Delay, Wait};
12+
13+
impl DelayUs for Delay<SYST> {
14+
type Error = Infallible;
15+
16+
fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
17+
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
18+
const MAX_RVR: u32 = 0x00FF_FFFF;
19+
20+
let mut total_rvr = us * (self.clk.0 / 8_000_000);
21+
22+
while total_rvr != 0 {
23+
let current_rvr = if total_rvr <= MAX_RVR {
24+
total_rvr
25+
} else {
26+
MAX_RVR
27+
};
28+
29+
self.tim.set_reload(current_rvr);
30+
self.tim.clear_current();
31+
self.tim.enable_counter();
32+
33+
// Update the tracking variable while we are waiting...
34+
total_rvr -= current_rvr;
35+
36+
while !self.tim.has_wrapped() {}
37+
38+
self.tim.disable_counter();
39+
}
40+
41+
Ok(())
42+
}
43+
44+
fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
45+
self.delay_us(ms * 1_000)
46+
}
47+
}
48+
49+
impl<TIM> DelayUs for Delay<TIM>
50+
where
51+
Self: Wait,
52+
{
53+
type Error = Infallible;
54+
55+
/// Sleep for up to 2^32-1 microseconds (~71 minutes).
56+
fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
57+
// Set up prescaler so that a tick takes exactly 1 µs.
58+
//
59+
// For example, if the clock is set to 48 MHz, with a prescaler of 48
60+
// we'll get ticks that are 1 µs long. This means that we can write the
61+
// delay value directly to the auto-reload register (ARR).
62+
let psc = u16(self.clk.0 / 1_000_000).expect("Prescaler does not fit in u16");
63+
let arr = us;
64+
self.wait(psc, arr);
65+
66+
Ok(())
67+
}
68+
69+
/// Sleep for up to (2^32)/2-1 milliseconds (~24 days).
70+
/// If the `ms` value is larger than 2147483647, the code will panic.
71+
fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
72+
// See next section for explanation why the usable range is reduced.
73+
assert!(ms <= 2_147_483_647); // (2^32)/2-1
74+
75+
// Set up prescaler so that a tick takes exactly 0.5 ms.
76+
//
77+
// For example, if the clock is set to 48 MHz, with a prescaler of 24'000
78+
// we'll get ticks that are 0.5 ms long. This means that we can write the
79+
// delay value multipled by two to the auto-reload register (ARR).
80+
//
81+
// Note that we cannot simply use a prescaler value where the tick corresponds
82+
// to 1 ms, because then a clock of 100 MHz would correspond to a prescaler
83+
// value of 100'000, which doesn't fit in the 16-bit PSC register.
84+
//
85+
// Unfortunately this means that only one half of the full 32-bit range
86+
// can be used, but 24 days should be plenty of usable delay time.
87+
let psc = u16(self.clk.0 / 1000 / 2).expect("Prescaler does not fit in u16");
88+
89+
// Since PSC = 0.5 ms, double the value for the ARR
90+
let arr = ms << 1;
91+
92+
self.wait(psc, arr);
93+
94+
Ok(())
95+
}
96+
}

src/delay/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Delays
22
33
mod hal_02;
4+
mod hal_1;
45

56
use crate::{
67
pac,

src/dwt.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,26 @@ impl<T: Into<u64>> embedded_hal::blocking::delay::DelayMs<T> for Delay {
114114
}
115115
}
116116

117+
impl embedded_hal_one::delay::blocking::DelayUs for Delay {
118+
type Error = core::convert::Infallible;
119+
120+
fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
121+
// Convert us to ticks
122+
let start = DWT::get_cycle_count();
123+
let ticks = (us as u64 * self.clock.0 as u64) / 1_000_000;
124+
Delay::delay_ticks(start, ticks);
125+
Ok(())
126+
}
127+
128+
fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
129+
// Convert ms to ticks
130+
let start = DWT::get_cycle_count();
131+
let ticks = (ms as u64 * self.clock.0 as u64) / 1_000;
132+
Delay::delay_ticks(start, ticks);
133+
Ok(())
134+
}
135+
}
136+
117137
/// Very simple stopwatch which reads from DWT Cycle Counter to record timing.
118138
///
119139
/// Since DWT Cycle Counter is a 32-bit counter that wraps around to 0 on overflow,

0 commit comments

Comments
 (0)