diff options
Diffstat (limited to 'embassy-stm32/src/timer')
| -rw-r--r-- | embassy-stm32/src/timer/mod.rs | 138 |
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)] | ||
| 2 | use core::ops; | ||
| 3 | |||
| 1 | use stm32_metapac::timer::vals; | 4 | use stm32_metapac::timer::vals; |
| 2 | 5 | ||
| 3 | use crate::interrupt; | 6 | use 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)] | ||
| 70 | pub(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)] | ||
| 82 | impl 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)] | ||
| 102 | impl 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 { |
