aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-06-26 19:59:10 -0500
committerxoviat <[email protected]>2023-06-30 18:21:57 -0500
commit71513ccb3905965aef2ae29a841dfdf4dfffe69a (patch)
tree7d5e5a9cb7758964aa19f9e61eb48d5ac856779a /embassy-stm32/src/timer
parentcdb3fb059f32a5669856390cfe379da71092d545 (diff)
stm32/hrtim: impl. draft frequency computation
Diffstat (limited to 'embassy-stm32/src/timer')
-rw-r--r--embassy-stm32/src/timer/mod.rs138
1 files changed, 135 insertions, 3 deletions
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 34ad5db11..03b9b3cf8 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,3 +1,6 @@
1#[cfg(hrtim_v1)]
2use core::ops;
3
1use stm32_metapac::timer::vals; 4use stm32_metapac::timer::vals;
2 5
3use crate::interrupt; 6use crate::interrupt;
@@ -50,13 +53,64 @@ pub(crate) mod sealed {
50 53
51 fn regs_highres() -> crate::pac::hrtim::Hrtim; 54 fn regs_highres() -> crate::pac::hrtim::Hrtim;
52 55
56 fn set_master_frequency(&mut self, frequency: Hertz);
57
58 fn set_channel_frequency(&mut self, channel: usize, frequency: Hertz);
59
53 fn start(&mut self); 60 fn start(&mut self);
54 61
55 fn stop(&mut self); 62 fn stop(&mut self);
56 63
57 fn reset(&mut self); 64 fn reset(&mut self);
65 }
66}
58 67
59 fn set_frequency(&mut self, frequency: Hertz); 68#[cfg(hrtim_v1)]
69#[derive(Clone, Copy)]
70pub(crate) enum HighResolutionControlPrescaler {
71 Div1,
72 Div2,
73 Div4,
74 Div8,
75 Div16,
76 Div32,
77 Div64,
78 Div128,
79}
80
81#[cfg(hrtim_v1)]
82impl ops::Div<HighResolutionControlPrescaler> for Hertz {
83 type Output = Hertz;
84
85 fn div(self, rhs: HighResolutionControlPrescaler) -> Self::Output {
86 let divisor = match rhs {
87 HighResolutionControlPrescaler::Div1 => 1,
88 HighResolutionControlPrescaler::Div2 => 2,
89 HighResolutionControlPrescaler::Div4 => 4,
90 HighResolutionControlPrescaler::Div8 => 8,
91 HighResolutionControlPrescaler::Div16 => 16,
92 HighResolutionControlPrescaler::Div32 => 32,
93 HighResolutionControlPrescaler::Div64 => 64,
94 HighResolutionControlPrescaler::Div128 => 128,
95 };
96
97 Hertz(self.0 / divisor)
98 }
99}
100
101#[cfg(hrtim_v1)]
102impl From<HighResolutionControlPrescaler> for u8 {
103 fn from(val: HighResolutionControlPrescaler) -> Self {
104 match val {
105 HighResolutionControlPrescaler::Div1 => 0b000,
106 HighResolutionControlPrescaler::Div2 => 0b001,
107 HighResolutionControlPrescaler::Div4 => 0b010,
108 HighResolutionControlPrescaler::Div8 => 0b011,
109 HighResolutionControlPrescaler::Div16 => 0b100,
110 HighResolutionControlPrescaler::Div32 => 0b101,
111 HighResolutionControlPrescaler::Div64 => 0b110,
112 HighResolutionControlPrescaler::Div128 => 0b111,
113 }
60 } 114 }
61} 115}
62 116
@@ -235,13 +289,91 @@ foreach_interrupt! {
235 crate::pac::$inst 289 crate::pac::$inst
236 } 290 }
237 291
292 fn set_master_frequency(&mut self, frequency: Hertz) {
293 use crate::rcc::sealed::RccPeripheral;
294
295 // TODO: fix frequency source
296 let f = frequency.0;
297 let timer_f = Self::frequency().0;
298 // Ratio taken from RM0364 Table 81
299 let base_f = Hertz(timer_f * (70_300 / 144_000_000));
300
301 /*
302 Find the smallest prescaler that allows us to acheive our frequency
303 */
304 let psc = [
305 HighResolutionControlPrescaler::Div1,
306 HighResolutionControlPrescaler::Div2,
307 HighResolutionControlPrescaler::Div4,
308 HighResolutionControlPrescaler::Div8,
309 HighResolutionControlPrescaler::Div16,
310 HighResolutionControlPrescaler::Div32,
311 HighResolutionControlPrescaler::Div64,
312 HighResolutionControlPrescaler::Div128,
313 ]
314 .iter()
315 .skip_while(|psc| frequency < base_f / **psc)
316 .next()
317 .unwrap();
318
319 let psc_timer_f = Hertz(timer_f) / *psc;
320 let per: u16 = (psc_timer_f / f).0 as u16;
321
322 let regs = Self::regs_highres();
323
324 regs.mcr().modify(|w| w.set_ckpsc(((*psc).into())));
325 regs.mper().modify(|w| w.set_mper(per));
326
327 // regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
328 // regs.egr().write(|r| r.set_ug(true));
329 // regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
330 }
331
332 fn set_channel_frequency(&mut self, channel: usize, frequency: Hertz) {
333 use crate::rcc::sealed::RccPeripheral;
334
335 // TODO: fix frequency source
336 let f = frequency.0;
337 let timer_f = Self::frequency().0;
338 // Ratio taken from RM0364 Table 81
339 let base_f = Hertz(timer_f * (70_300 / 144_000_000));
340
341 /*
342 Find the smallest prescaler that allows us to acheive our frequency
343 */
344 let psc = [
345 HighResolutionControlPrescaler::Div1,
346 HighResolutionControlPrescaler::Div2,
347 HighResolutionControlPrescaler::Div4,
348 HighResolutionControlPrescaler::Div8,
349 HighResolutionControlPrescaler::Div16,
350 HighResolutionControlPrescaler::Div32,
351 HighResolutionControlPrescaler::Div64,
352 HighResolutionControlPrescaler::Div128,
353 ]
354 .iter()
355 .skip_while(|psc| frequency < base_f / **psc)
356 .next()
357 .unwrap();
358
359 let psc_timer_f = Hertz(timer_f) / *psc;
360 let per: u16 = (psc_timer_f / f).0 as u16;
361
362 let regs = Self::regs_highres();
363
364 regs.tim(channel).cr().modify(|w| w.set_ckpsc(((*psc).into())));
365 regs.tim(channel).per().modify(|w| w.set_per(per));
366
367 // regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
368 // regs.egr().write(|r| r.set_ug(true));
369 // regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
370 }
371
238 fn start(&mut self) { todo!() } 372 fn start(&mut self) { todo!() }
239 373
240 fn stop(&mut self) { todo!() } 374 fn stop(&mut self) { todo!() }
241 375
242 fn reset(&mut self) { todo!() } 376 fn reset(&mut self) { todo!() }
243
244 fn set_frequency(&mut self, frequency: Hertz) { todo!() }
245 } 377 }
246 378
247 impl HighResolutionControlInstance for crate::peripherals::$inst { 379 impl HighResolutionControlInstance for crate::peripherals::$inst {