Skip to content

Commit 53fdb82

Browse files
committed
both embedded-hals for Delay
1 parent d568009 commit 53fdb82

File tree

6 files changed

+344
-240
lines changed

6 files changed

+344
-240
lines changed

src/delay/hal_02.rs

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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, u32};
7+
use cortex_m::peripheral::SYST;
8+
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
9+
10+
use super::{Delay, Wait};
11+
12+
impl DelayUs<u32> for Delay<SYST> {
13+
fn delay_us(&mut self, us: u32) {
14+
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
15+
const MAX_RVR: u32 = 0x00FF_FFFF;
16+
17+
let mut total_rvr = us * (self.clk.0 / 8_000_000);
18+
19+
while total_rvr != 0 {
20+
let current_rvr = if total_rvr <= MAX_RVR {
21+
total_rvr
22+
} else {
23+
MAX_RVR
24+
};
25+
26+
self.tim.set_reload(current_rvr);
27+
self.tim.clear_current();
28+
self.tim.enable_counter();
29+
30+
// Update the tracking variable while we are waiting...
31+
total_rvr -= current_rvr;
32+
33+
while !self.tim.has_wrapped() {}
34+
35+
self.tim.disable_counter();
36+
}
37+
}
38+
}
39+
40+
impl DelayMs<u32> for Delay<SYST> {
41+
fn delay_ms(&mut self, ms: u32) {
42+
self.delay_us(ms * 1_000);
43+
}
44+
}
45+
46+
impl DelayUs<u16> for Delay<SYST> {
47+
fn delay_us(&mut self, us: u16) {
48+
self.delay_us(u32(us))
49+
}
50+
}
51+
52+
impl DelayMs<u16> for Delay<SYST> {
53+
fn delay_ms(&mut self, ms: u16) {
54+
self.delay_ms(u32(ms));
55+
}
56+
}
57+
58+
impl DelayUs<u8> for Delay<SYST> {
59+
fn delay_us(&mut self, us: u8) {
60+
self.delay_us(u32(us))
61+
}
62+
}
63+
64+
impl DelayMs<u8> for Delay<SYST> {
65+
fn delay_ms(&mut self, ms: u8) {
66+
self.delay_ms(u32(ms));
67+
}
68+
}
69+
70+
impl<TIM> DelayUs<u32> for Delay<TIM>
71+
where
72+
Self: Wait,
73+
{
74+
/// Sleep for up to 2^32-1 microseconds (~71 minutes).
75+
fn delay_us(&mut self, us: u32) {
76+
// Set up prescaler so that a tick takes exactly 1 µs.
77+
//
78+
// For example, if the clock is set to 48 MHz, with a prescaler of 48
79+
// we'll get ticks that are 1 µs long. This means that we can write the
80+
// delay value directly to the auto-reload register (ARR).
81+
let psc = u16(self.clk.0 / 1_000_000).expect("Prescaler does not fit in u16");
82+
let arr = us;
83+
self.wait(psc, arr);
84+
}
85+
}
86+
87+
impl<TIM> DelayMs<u32> for Delay<TIM>
88+
where
89+
Self: Wait,
90+
{
91+
/// Sleep for up to (2^32)/2-1 milliseconds (~24 days).
92+
/// If the `ms` value is larger than 2147483647, the code will panic.
93+
fn delay_ms(&mut self, ms: u32) {
94+
// See next section for explanation why the usable range is reduced.
95+
assert!(ms <= 2_147_483_647); // (2^32)/2-1
96+
97+
// Set up prescaler so that a tick takes exactly 0.5 ms.
98+
//
99+
// For example, if the clock is set to 48 MHz, with a prescaler of 24'000
100+
// we'll get ticks that are 0.5 ms long. This means that we can write the
101+
// delay value multipled by two to the auto-reload register (ARR).
102+
//
103+
// Note that we cannot simply use a prescaler value where the tick corresponds
104+
// to 1 ms, because then a clock of 100 MHz would correspond to a prescaler
105+
// value of 100'000, which doesn't fit in the 16-bit PSC register.
106+
//
107+
// Unfortunately this means that only one half of the full 32-bit range
108+
// can be used, but 24 days should be plenty of usable delay time.
109+
let psc = u16(self.clk.0 / 1000 / 2).expect("Prescaler does not fit in u16");
110+
111+
// Since PSC = 0.5 ms, double the value for the ARR
112+
let arr = ms << 1;
113+
114+
self.wait(psc, arr);
115+
}
116+
}
117+
118+
impl<TIM> DelayUs<u16> for Delay<TIM>
119+
where
120+
Self: Wait,
121+
{
122+
/// Sleep for up to 2^16-1 microseconds (~65 milliseconds).
123+
fn delay_us(&mut self, us: u16) {
124+
// See DelayUs<u32> for explanations.
125+
let psc = u16(self.clk.0 / 1_000_000).expect("Prescaler does not fit in u16");
126+
let arr = u32(us);
127+
self.wait(psc, arr);
128+
}
129+
}
130+
131+
impl<TIM> DelayMs<u16> for Delay<TIM>
132+
where
133+
Self: Wait,
134+
{
135+
/// Sleep for up to (2^16)-1 milliseconds (~65 seconds).
136+
fn delay_ms(&mut self, ms: u16) {
137+
// See DelayMs<u32> for explanations. Since the value range is only 16 bit,
138+
// we don't need an assert here.
139+
let psc = u16(self.clk.0 / 1000 / 2).expect("Prescaler does not fit in u16");
140+
let arr = u32(ms) << 1;
141+
self.wait(psc, arr);
142+
}
143+
}

src/delay/hal_1.rs

+96
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

+83-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
//! Delays
22
3-
mod syst;
3+
mod hal_02;
4+
mod hal_1;
45

6+
use crate::{
7+
pac,
8+
rcc::Clocks,
9+
timer::{General, Timer},
10+
};
11+
use core::cmp::max;
12+
use cortex_m::peripheral::syst::SystClkSource;
513
use cortex_m::peripheral::SYST;
614

715
use crate::time::Hertz;
@@ -19,4 +27,77 @@ impl<T> Delay<T> {
1927
}
2028
}
2129

22-
mod timer;
30+
impl Delay<SYST> {
31+
/// Configures the system timer (SysTick) as a delay provider
32+
pub fn new(mut tim: SYST, clocks: &Clocks) -> Self {
33+
tim.set_clock_source(SystClkSource::External);
34+
Self {
35+
tim,
36+
clk: clocks.hclk(),
37+
}
38+
}
39+
}
40+
41+
mod sealed {
42+
pub trait Wait {
43+
fn wait(&mut self, prescaler: u16, auto_reload_register: u32);
44+
}
45+
}
46+
use sealed::Wait;
47+
48+
macro_rules! hal {
49+
($($TIM:ty: ($tim:ident),)+) => {
50+
$(
51+
impl Timer<$TIM> {
52+
pub fn delay(self) -> Delay<$TIM> {
53+
let Self { tim, clk } = self;
54+
55+
// Enable one-pulse mode (counter stops counting at the next update
56+
// event, clearing the CEN bit)
57+
tim.cr1.modify(|_, w| w.opm().enabled());
58+
59+
Delay { tim, clk }
60+
}
61+
}
62+
63+
impl Delay<$TIM> {
64+
/// Configures the timer as a delay provider
65+
pub fn $tim(tim: $TIM, clocks: &Clocks) -> Self {
66+
Timer::new(tim, clocks).delay()
67+
}
68+
}
69+
70+
impl Wait for Delay<$TIM> {
71+
fn wait(&mut self, prescaler: u16, auto_reload_register: u32) {
72+
// Write Prescaler (PSC)
73+
self.tim.set_prescaler(prescaler);
74+
75+
// Write Auto-Reload Register (ARR)
76+
// Note: Make it impossible to set the ARR value to 0, since this
77+
// would cause an infinite loop.
78+
self.tim.set_auto_reload(max(1, auto_reload_register)).unwrap();
79+
80+
// Trigger update event (UEV) in the event generation register (EGR)
81+
// in order to immediately apply the config
82+
self.tim.trigger_update();
83+
84+
// Configure the counter in one-pulse mode (counter stops counting at
85+
// the next updateevent, clearing the CEN bit) and enable the counter.
86+
self.tim.cr1.write(|w| w.opm().set_bit().cen().set_bit());
87+
88+
// Wait for CEN bit to clear
89+
while self.tim.is_counter_enabled() { /* wait */ }
90+
}
91+
}
92+
)+
93+
}
94+
}
95+
96+
hal! {
97+
pac::TIM5: (tim5),
98+
}
99+
100+
#[cfg(feature = "tim2")]
101+
hal! {
102+
pac::TIM2: (tim2),
103+
}

0 commit comments

Comments
 (0)