-
Notifications
You must be signed in to change notification settings - Fork 103
/
delay.rs
151 lines (123 loc) · 3.27 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
//! Delays
use cast::u32;
use cortex_m::asm;
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::Hertz;
/// System timer (SysTick) as a delay provider
pub struct Delay {
clocks: Clocks,
syst: SYST,
}
impl Delay {
/// Configures the system timer (SysTick) as a delay provider
pub fn new(mut syst: SYST, clocks: Clocks) -> Self {
syst.set_clock_source(SystClkSource::Core);
Delay { syst, clocks }
}
/// Releases the system timer (SysTick) resource
pub fn free(self) -> SYST {
self.syst
}
}
/// System timer (SysTick) as a delay provider.
impl DelayMs<u32> for Delay {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
}
impl DelayMs<u16> for Delay {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32(ms));
}
}
impl DelayMs<u8> for Delay {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32(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;
let mut total_rvr = us * (self.clocks.hclk().raw() / 1_000_000);
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(us))
}
}
impl DelayUs<u8> for Delay {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}
/// Cortex-M `asm::delay` as provider
#[derive(Clone, Copy)]
pub struct DelayCM {
sysclk: Hertz,
}
impl DelayCM {
/// Create a new delay
pub fn new(clocks: Clocks) -> Self {
DelayCM {
sysclk: clocks.sysclk(),
}
}
/// Create a new delay that is unchecked. The user needs to know the `sysclk`.
///
/// # Safety
/// Sysclk must be the same as the actual clock frequency of the chip
pub const unsafe fn new_unchecked(sysclk: Hertz) -> Self {
DelayCM { sysclk }
}
}
impl DelayMs<u32> for DelayCM {
fn delay_ms(&mut self, ms: u32) {
self.delay_us(ms * 1_000);
}
}
impl DelayMs<u16> for DelayCM {
fn delay_ms(&mut self, ms: u16) {
self.delay_ms(u32(ms));
}
}
impl DelayMs<u8> for DelayCM {
fn delay_ms(&mut self, ms: u8) {
self.delay_ms(u32(ms));
}
}
impl DelayUs<u32> for DelayCM {
fn delay_us(&mut self, us: u32) {
// Max delay is 53_687_091 us at 80 MHz
let ticks = self.sysclk.raw() / 1_000_000;
asm::delay(ticks * us);
}
}
impl DelayUs<u16> for DelayCM {
fn delay_us(&mut self, us: u16) {
self.delay_us(u32(us))
}
}
impl DelayUs<u8> for DelayCM {
fn delay_us(&mut self, us: u8) {
self.delay_us(u32(us))
}
}