diff options
| author | xoviat <[email protected]> | 2023-06-26 19:59:10 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-06-30 18:21:57 -0500 |
| commit | 71513ccb3905965aef2ae29a841dfdf4dfffe69a (patch) | |
| tree | 7d5e5a9cb7758964aa19f9e61eb48d5ac856779a | |
| parent | cdb3fb059f32a5669856390cfe379da71092d545 (diff) | |
stm32/hrtim: impl. draft frequency computation
| -rw-r--r-- | embassy-stm32/src/pwm/mod.rs | 32 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/mod.rs | 138 |
2 files changed, 155 insertions, 15 deletions
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index 4c2031348..1838bfdfe 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs | |||
| @@ -29,7 +29,6 @@ impl Channel { | |||
| 29 | } | 29 | } |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | #[cfg(hrtim_v1)] | ||
| 33 | #[derive(Clone, Copy)] | 32 | #[derive(Clone, Copy)] |
| 34 | pub enum AdvancedChannel { | 33 | pub enum AdvancedChannel { |
| 35 | ChA, | 34 | ChA, |
| @@ -39,7 +38,6 @@ pub enum AdvancedChannel { | |||
| 39 | ChE, | 38 | ChE, |
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | #[cfg(hrtim_v1)] | ||
| 43 | impl AdvancedChannel { | 41 | impl AdvancedChannel { |
| 44 | pub fn raw(&self) -> usize { | 42 | pub fn raw(&self) -> usize { |
| 45 | match self { | 43 | match self { |
| @@ -82,6 +80,7 @@ impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm { | |||
| 82 | pub(crate) mod sealed { | 80 | pub(crate) mod sealed { |
| 83 | use super::*; | 81 | use super::*; |
| 84 | 82 | ||
| 83 | #[cfg(hrtim_v1)] | ||
| 85 | pub trait AdvancedCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance { | 84 | pub trait AdvancedCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance { |
| 86 | fn enable_outputs(&mut self, enable: bool); | 85 | fn enable_outputs(&mut self, enable: bool); |
| 87 | 86 | ||
| @@ -122,6 +121,7 @@ pub(crate) mod sealed { | |||
| 122 | } | 121 | } |
| 123 | } | 122 | } |
| 124 | 123 | ||
| 124 | #[cfg(hrtim_v1)] | ||
| 125 | pub trait AdvancedCaptureCompare16bitInstance: sealed::AdvancedCaptureCompare16bitInstance + 'static {} | 125 | pub trait AdvancedCaptureCompare16bitInstance: sealed::AdvancedCaptureCompare16bitInstance + 'static {} |
| 126 | 126 | ||
| 127 | pub trait CaptureCompare16bitInstance: | 127 | pub trait CaptureCompare16bitInstance: |
| @@ -317,13 +317,21 @@ pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance); | |||
| 317 | pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance); | 317 | pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance); |
| 318 | pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance); | 318 | pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance); |
| 319 | 319 | ||
| 320 | pin_trait!(ChannelAPin, AdvancedCaptureCompare16bitInstance); | 320 | #[cfg(hrtim_v1)] |
| 321 | pin_trait!(ChannelAComplementaryPin, AdvancedCaptureCompare16bitInstance); | 321 | mod hrtim_pins { |
| 322 | pin_trait!(ChannelBPin, AdvancedCaptureCompare16bitInstance); | 322 | use super::*; |
| 323 | pin_trait!(ChannelBComplementaryPin, AdvancedCaptureCompare16bitInstance); | 323 | |
| 324 | pin_trait!(ChannelCPin, AdvancedCaptureCompare16bitInstance); | 324 | pin_trait!(ChannelAPin, AdvancedCaptureCompare16bitInstance); |
| 325 | pin_trait!(ChannelCComplementaryPin, AdvancedCaptureCompare16bitInstance); | 325 | pin_trait!(ChannelAComplementaryPin, AdvancedCaptureCompare16bitInstance); |
| 326 | pin_trait!(ChannelDPin, AdvancedCaptureCompare16bitInstance); | 326 | pin_trait!(ChannelBPin, AdvancedCaptureCompare16bitInstance); |
| 327 | pin_trait!(ChannelDComplementaryPin, AdvancedCaptureCompare16bitInstance); | 327 | pin_trait!(ChannelBComplementaryPin, AdvancedCaptureCompare16bitInstance); |
| 328 | pin_trait!(ChannelEPin, AdvancedCaptureCompare16bitInstance); | 328 | pin_trait!(ChannelCPin, AdvancedCaptureCompare16bitInstance); |
| 329 | pin_trait!(ChannelEComplementaryPin, AdvancedCaptureCompare16bitInstance); | 329 | pin_trait!(ChannelCComplementaryPin, AdvancedCaptureCompare16bitInstance); |
| 330 | pin_trait!(ChannelDPin, AdvancedCaptureCompare16bitInstance); | ||
| 331 | pin_trait!(ChannelDComplementaryPin, AdvancedCaptureCompare16bitInstance); | ||
| 332 | pin_trait!(ChannelEPin, AdvancedCaptureCompare16bitInstance); | ||
| 333 | pin_trait!(ChannelEComplementaryPin, AdvancedCaptureCompare16bitInstance); | ||
| 334 | } | ||
| 335 | |||
| 336 | #[cfg(hrtim_v1)] | ||
| 337 | pub use hrtim_pins::*; | ||
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 { |
