-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathdelay.rs
156 lines (132 loc) · 4.17 KB
/
delay.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! # Delays
//!
//! Implementations for the [`DelayMs`] and [`DelayUs`] traits
//!
//! [DelayMs]: embedded_hal::blocking::delay::DelayMs
//! [DelayUs]: embedded_hal::blocking::delay::DelayUs
use core::convert::From;
use core::fmt;
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use crate::hal::blocking::delay::{DelayMs, DelayUs};
use crate::rcc::Clocks;
use crate::time::duration::{Microseconds, Milliseconds};
use crate::time::fixed_point::FixedPoint;
/// System timer (`SysTick`) as a delay provider
pub struct Delay {
clocks: Clocks,
syst: SYST,
}
#[cfg(feature = "defmt")]
impl defmt::Format for Delay {
fn format(&self, f: defmt::Formatter) {
defmt::write!(f, "Delay {{ clocks: {} , syst: SYST }}", self.clocks);
}
}
impl fmt::Debug for Delay {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Delay")
.field("clocks", &self.clocks)
.field("syst", &"SYST")
.finish()
}
}
impl Delay {
/// Configures the system timer (`SysTick`) as a delay provider
///
/// # Limitations
///
/// Depending on the core clock, this delay provider
/// can delay between 1 minute (for 72 Mhz) up to almost 9 minutes (for 8 Mhz).
/// Higher input values will be capped to these limits.
///
/// For accuracy purposes and because this is a blocking, busy-waiting function,
/// if delays in the second to minute range are needed, use timers instead.
#[must_use]
pub fn new(mut syst: SYST, clocks: Clocks) -> Self {
syst.set_clock_source(SystClkSource::Core);
Delay { clocks, syst }
}
/// Get access to the underlying register block.
///
/// # Safety
///
/// This function is not _memory_ unsafe per se, but does not guarantee
/// anything about assumptions of invariants made in this implementation.
///
/// Changing specific options can lead to un-expected behavior and nothing
/// is guaranteed.
pub unsafe fn peripheral(&mut self) -> &mut SYST {
&mut self.syst
}
/// Releases the system timer (`SysTick`) resource
#[must_use]
pub fn free(self) -> SYST {
self.syst
}
}
impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms.saturating_mul(1_000));
}
}
impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32::from(ms));
}
}
impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32::from(ms));
}
}
impl DelayUs<u32> for Delay {
fn delay_us(&mut self, us: u32) {
// The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
const MAX_RVR: u32 = 0x00FF_FFFF;
// Depending on hclk (core clock), this 32 bit value allows
// delays between 1 min to 9 min.
//
// (((32^2) - 1) / 72) µs ~ 59.6 seconds
// (((32^2) - 1) / 8) µs ~ 536.8 seconds
let mut total_rvr = us.saturating_mul(self.clocks.hclk().0 / 1_000_000);
// Use the full 32 bit range to allow longer delays
//
// Like dividing total_rvr / MAX_RVR
// and delaying by MAX_RVR * (fraction).
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();
}
}
}
impl DelayUs<u16> for Delay {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32::from(us));
}
}
impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32::from(us));
}
}
impl DelayUs<Microseconds> for Delay {
fn delay_us(&mut self, us: Microseconds) {
self.delay_us(us.integer());
}
}
impl DelayMs<Milliseconds> for Delay {
fn delay_ms(&mut self, ms: Milliseconds) {
self.delay_ms(ms.integer());
}
}