1use crate::rcc::Clocks;
4use cortex_m::peripheral::{DCB, DWT};
5use fugit::HertzU32 as Hertz;
6
7pub trait DwtExt {
8 fn constrain(self, dcb: DCB, clocks: &Clocks) -> Dwt;
9}
10impl DwtExt for DWT {
11 fn constrain(mut self, mut dcb: DCB, clocks: &Clocks) -> Dwt {
13 dcb.enable_trace();
14 self.enable_cycle_counter();
15 Dwt {
16 dwt: self,
17 dcb,
18 clock: clocks.hclk(),
19 }
20 }
21}
22
23pub struct Dwt {
25 dwt: DWT,
26 dcb: DCB,
27 clock: Hertz,
28}
29impl Dwt {
30 pub unsafe fn release(self) -> (DWT, DCB) {
34 (self.dwt, self.dcb)
35 }
36 pub fn delay(&self) -> Delay {
38 Delay { clock: self.clock }
39 }
40 pub fn stopwatch<'i>(&self, times: &'i mut [u32]) -> StopWatch<'i> {
44 StopWatch::new(times, self.clock)
45 }
46 pub fn measure<F: FnOnce()>(&self, f: F) -> ClockDuration {
52 let mut times: [u32; 2] = [0; 2];
53 let mut sw = self.stopwatch(&mut times);
54 f();
55 sw.lap().lap_time(1).unwrap()
56 }
57}
58
59#[derive(Clone, Copy)]
60pub struct Delay {
61 clock: Hertz,
62}
63impl Delay {
64 pub fn delay(duration: ClockDuration) {
66 let ticks = duration.ticks as u64;
67 Delay::delay_ticks(DWT::cycle_count(), ticks);
68 }
69 fn delay_ticks(mut start: u32, ticks: u64) {
72 if ticks < (u32::MAX / 2) as u64 {
73 let ticks = ticks as u32;
75 while (DWT::cycle_count().wrapping_sub(start)) < ticks {}
76 } else if ticks <= u32::MAX as u64 {
77 let mut ticks = ticks as u32;
79 ticks -= u32::MAX / 2;
80 while (DWT::cycle_count().wrapping_sub(start)) < u32::MAX / 2 {}
81 start -= u32::MAX / 2;
82 while (DWT::cycle_count().wrapping_sub(start)) < ticks {}
83 } else {
84 let mut rest = (ticks >> 32) as u32;
86 let ticks = (ticks & u32::MAX as u64) as u32;
87 loop {
88 while (DWT::cycle_count().wrapping_sub(start)) < ticks {}
89 if rest == 0 {
90 break;
91 }
92 rest -= 1;
93 while (DWT::cycle_count().wrapping_sub(start)) > ticks {}
94 }
95 }
96 }
97}
98
99impl<T: Into<u64>> embedded_hal_02::blocking::delay::DelayUs<T> for Delay {
101 fn delay_us(&mut self, us: T) {
102 let start = DWT::cycle_count();
104 let ticks = (us.into() * self.clock.raw() as u64) / 1_000_000;
105 Delay::delay_ticks(start, ticks);
106 }
107}
108impl<T: Into<u64>> embedded_hal_02::blocking::delay::DelayMs<T> for Delay {
109 fn delay_ms(&mut self, ms: T) {
110 let start = DWT::cycle_count();
112 let ticks = (ms.into() * self.clock.raw() as u64) / 1_000;
113 Delay::delay_ticks(start, ticks);
114 }
115}
116
117impl embedded_hal::delay::DelayNs for Delay {
118 fn delay_ns(&mut self, ns: u32) {
119 let start = DWT::cycle_count();
121 let ticks = (ns as u64 * self.clock.raw() as u64) / 1_000_000_000;
122 Delay::delay_ticks(start, ticks);
123 }
124
125 fn delay_us(&mut self, us: u32) {
126 let start = DWT::cycle_count();
128 let ticks = (us as u64 * self.clock.raw() as u64) / 1_000_000;
129 Delay::delay_ticks(start, ticks);
130 }
131
132 fn delay_ms(&mut self, ms: u32) {
133 let start = DWT::cycle_count();
135 let ticks = (ms as u64 * self.clock.raw() as u64) / 1_000;
136 Delay::delay_ticks(start, ticks);
137 }
138}
139
140pub struct StopWatch<'l> {
146 times: &'l mut [u32],
147 timei: usize,
148 clock: Hertz,
149}
150impl<'l> StopWatch<'l> {
151 fn new(times: &'l mut [u32], clock: Hertz) -> Self {
156 assert!(times.len() >= 2);
157 let mut sw = StopWatch {
158 times,
159 timei: 0,
160 clock,
161 };
162 sw.reset();
163 sw
164 }
165 pub fn lap_count(&self) -> usize {
167 self.timei
168 }
169 pub fn reset(&mut self) {
171 self.timei = 0;
172 self.times[0] = DWT::cycle_count();
173 }
174 pub fn lap(&mut self) -> &mut Self {
178 let c = DWT::cycle_count();
179 if self.timei < self.times.len() {
180 self.timei += 1;
181 }
182 self.times[self.timei] = c;
183 self
184 }
185 pub fn lap_time(&self, n: usize) -> Option<ClockDuration> {
189 if (n < 1) || (self.timei < n) {
190 None
191 } else {
192 Some(ClockDuration {
193 ticks: self.times[n].wrapping_sub(self.times[n - 1]),
194 clock: self.clock,
195 })
196 }
197 }
198}
199
200#[derive(Clone, Copy)]
202pub struct ClockDuration {
203 ticks: u32,
204 clock: Hertz,
205}
206impl ClockDuration {
207 pub fn as_ticks(self) -> u32 {
209 self.ticks
210 }
211 pub fn as_millis(self) -> u64 {
213 self.ticks as u64 * 1_000 / self.clock.raw() as u64
214 }
215 pub fn as_micros(self) -> u64 {
217 self.ticks as u64 * 1_000_000 / self.clock.raw() as u64
218 }
219 pub fn as_nanos(self) -> u64 {
221 self.ticks as u64 * 1_000_000_000 / self.clock.raw() as u64
222 }
223 pub fn as_secs_f32(self) -> f32 {
225 self.ticks as f32 / self.clock.raw() as f32
226 }
227 pub fn as_secs_f64(self) -> f64 {
229 self.ticks as f64 / self.clock.raw() as f64
230 }
231}
232
233#[derive(Clone, Copy)]
240pub struct MonoTimer {
241 frequency: Hertz,
242}
243
244impl MonoTimer {
245 pub fn new(mut dwt: DWT, mut dcb: DCB, clocks: &Clocks) -> Self {
247 dcb.enable_trace();
248 dwt.enable_cycle_counter();
249
250 MonoTimer {
253 frequency: clocks.hclk(),
254 }
255 }
256
257 pub fn frequency(self) -> Hertz {
259 self.frequency
260 }
261
262 pub fn now(self) -> Instant {
264 Instant {
265 now: DWT::cycle_count(),
266 }
267 }
268}
269
270#[derive(Clone, Copy)]
272pub struct Instant {
273 now: u32,
274}
275
276impl Instant {
277 pub fn elapsed(self) -> u32 {
279 DWT::cycle_count().wrapping_sub(self.now)
280 }
281}