diff options
| author | xoviat <[email protected]> | 2023-06-27 18:24:32 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-06-30 18:21:58 -0500 |
| commit | 348019e37f0ff5716d80199e33244c0a1a59b360 (patch) | |
| tree | 64cee936aacbc8b93883c4edf60aedf661228666 | |
| parent | b9eb3dfad7b601a7819377c2c94369ca74efc824 (diff) | |
stm32/hrtim: impl channel alloc type system
| -rw-r--r-- | embassy-stm32/src/pwm/advanced_pwm.rs | 167 | ||||
| -rw-r--r-- | embassy-stm32/src/pwm/mod.rs | 144 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/mod.rs | 149 |
3 files changed, 194 insertions, 266 deletions
diff --git a/embassy-stm32/src/pwm/advanced_pwm.rs b/embassy-stm32/src/pwm/advanced_pwm.rs index a08952248..c7b5f7482 100644 --- a/embassy-stm32/src/pwm/advanced_pwm.rs +++ b/embassy-stm32/src/pwm/advanced_pwm.rs | |||
| @@ -2,7 +2,6 @@ use core::marker::PhantomData; | |||
| 2 | 2 | ||
| 3 | use embassy_hal_common::{into_ref, PeripheralRef}; | 3 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 4 | 4 | ||
| 5 | use super::simple_pwm::*; | ||
| 6 | use super::*; | 5 | use super::*; |
| 7 | #[allow(unused_imports)] | 6 | #[allow(unused_imports)] |
| 8 | use crate::gpio::sealed::{AFType, Pin}; | 7 | use crate::gpio::sealed::{AFType, Pin}; |
| @@ -11,30 +10,34 @@ use crate::time::Hertz; | |||
| 11 | use crate::Peripheral; | 10 | use crate::Peripheral; |
| 12 | 11 | ||
| 13 | // Re-implement the channels for hrtim | 12 | // Re-implement the channels for hrtim |
| 14 | pub struct Master { | 13 | pub struct Master<T: AdvancedCaptureCompare16bitInstance> { |
| 15 | phantom: PhantomData<bool>, | 14 | phantom: PhantomData<T>, |
| 16 | } | 15 | } |
| 17 | pub struct ChA { | 16 | pub struct ChA<T: AdvancedCaptureCompare16bitInstance> { |
| 18 | phantom: PhantomData<bool>, | 17 | phantom: PhantomData<T>, |
| 19 | } | 18 | } |
| 20 | pub struct ChB { | 19 | pub struct ChB<T: AdvancedCaptureCompare16bitInstance> { |
| 21 | phantom: PhantomData<bool>, | 20 | phantom: PhantomData<T>, |
| 22 | } | 21 | } |
| 23 | pub struct ChC { | 22 | pub struct ChC<T: AdvancedCaptureCompare16bitInstance> { |
| 24 | phantom: PhantomData<bool>, | 23 | phantom: PhantomData<T>, |
| 25 | } | 24 | } |
| 26 | pub struct ChD { | 25 | pub struct ChD<T: AdvancedCaptureCompare16bitInstance> { |
| 27 | phantom: PhantomData<bool>, | 26 | phantom: PhantomData<T>, |
| 28 | } | 27 | } |
| 29 | pub struct ChE { | 28 | pub struct ChE<T: AdvancedCaptureCompare16bitInstance> { |
| 30 | phantom: PhantomData<bool>, | 29 | phantom: PhantomData<T>, |
| 31 | } | 30 | } |
| 32 | 31 | ||
| 33 | mod sealed { | 32 | mod sealed { |
| 34 | pub trait AdvancedChannel {} | 33 | use crate::pwm::AdvancedCaptureCompare16bitInstance; |
| 34 | |||
| 35 | pub trait AdvancedChannel<T: AdvancedCaptureCompare16bitInstance> {} | ||
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | pub trait AdvancedChannel: sealed::AdvancedChannel {} | 38 | pub trait AdvancedChannel<T: AdvancedCaptureCompare16bitInstance>: sealed::AdvancedChannel<T> { |
| 39 | fn raw() -> usize; | ||
| 40 | } | ||
| 38 | 41 | ||
| 39 | pub struct PwmPin<'d, Perip, Channel> { | 42 | pub struct PwmPin<'d, Perip, Channel> { |
| 40 | _pin: PeripheralRef<'d, AnyPin>, | 43 | _pin: PeripheralRef<'d, AnyPin>, |
| @@ -47,8 +50,8 @@ pub struct ComplementaryPwmPin<'d, Perip, Channel> { | |||
| 47 | } | 50 | } |
| 48 | 51 | ||
| 49 | macro_rules! advanced_channel_impl { | 52 | macro_rules! advanced_channel_impl { |
| 50 | ($new_chx:ident, $channel:ident, $pin_trait:ident, $complementary_pin_trait:ident) => { | 53 | ($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => { |
| 51 | impl<'d, Perip: AdvancedCaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { | 54 | impl<'d, Perip: AdvancedCaptureCompare16bitInstance> PwmPin<'d, Perip, $channel<Perip>> { |
| 52 | pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { | 55 | pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { |
| 53 | into_ref!(pin); | 56 | into_ref!(pin); |
| 54 | critical_section::with(|_| { | 57 | critical_section::with(|_| { |
| @@ -64,7 +67,7 @@ macro_rules! advanced_channel_impl { | |||
| 64 | } | 67 | } |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | impl<'d, Perip: AdvancedCaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { | 70 | impl<'d, Perip: AdvancedCaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel<Perip>> { |
| 68 | pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { | 71 | pub fn $new_chx(pin: impl Peripheral<P = impl $complementary_pin_trait<Perip>> + 'd) -> Self { |
| 69 | into_ref!(pin); | 72 | into_ref!(pin); |
| 70 | critical_section::with(|_| { | 73 | critical_section::with(|_| { |
| @@ -80,39 +83,45 @@ macro_rules! advanced_channel_impl { | |||
| 80 | } | 83 | } |
| 81 | } | 84 | } |
| 82 | 85 | ||
| 83 | impl sealed::AdvancedChannel for $channel {} | 86 | impl<T: AdvancedCaptureCompare16bitInstance> sealed::AdvancedChannel<T> for $channel<T> {} |
| 84 | impl AdvancedChannel for $channel {} | 87 | impl<T: AdvancedCaptureCompare16bitInstance> AdvancedChannel<T> for $channel<T> { |
| 88 | fn raw() -> usize { | ||
| 89 | $ch_num | ||
| 90 | } | ||
| 91 | } | ||
| 85 | }; | 92 | }; |
| 86 | } | 93 | } |
| 87 | 94 | ||
| 88 | advanced_channel_impl!(new_cha, ChA, ChannelAPin, ChannelAComplementaryPin); | 95 | advanced_channel_impl!(new_cha, ChA, 0, ChannelAPin, ChannelAComplementaryPin); |
| 89 | advanced_channel_impl!(new_chb, ChB, ChannelBPin, ChannelBComplementaryPin); | 96 | advanced_channel_impl!(new_chb, ChB, 1, ChannelBPin, ChannelBComplementaryPin); |
| 90 | advanced_channel_impl!(new_chc, ChC, ChannelCPin, ChannelCComplementaryPin); | 97 | advanced_channel_impl!(new_chc, ChC, 2, ChannelCPin, ChannelCComplementaryPin); |
| 91 | advanced_channel_impl!(new_chd, ChD, ChannelDPin, ChannelDComplementaryPin); | 98 | advanced_channel_impl!(new_chd, ChD, 3, ChannelDPin, ChannelDComplementaryPin); |
| 92 | advanced_channel_impl!(new_che, ChE, ChannelEPin, ChannelEComplementaryPin); | 99 | advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin); |
| 93 | 100 | ||
| 94 | /// Struct used to divide a high resolution timer into multiple channels | 101 | /// Struct used to divide a high resolution timer into multiple channels |
| 95 | pub struct AdvancedPwm<'d, T> { | 102 | pub struct AdvancedPwm<'d, T: AdvancedCaptureCompare16bitInstance> { |
| 96 | inner: PeripheralRef<'d, T>, | 103 | _inner: PeripheralRef<'d, T>, |
| 97 | pub master: Master, | 104 | pub master: Master<T>, |
| 98 | pub ch_a: ChA, | 105 | pub ch_a: ChA<T>, |
| 99 | pub ch_b: ChB, | 106 | pub ch_b: ChB<T>, |
| 100 | pub ch_c: ChC, | 107 | pub ch_c: ChC<T>, |
| 101 | pub ch_d: ChD, | 108 | pub ch_d: ChD<T>, |
| 102 | pub ch_e: ChE, | 109 | pub ch_e: ChE<T>, |
| 103 | } | 110 | } |
| 104 | 111 | ||
| 105 | impl<'d, T: ComplementaryCaptureCompare16bitInstance> AdvancedPwm<'d, T> { | 112 | impl<'d, T: AdvancedCaptureCompare16bitInstance> AdvancedPwm<'d, T> { |
| 106 | pub fn new( | 113 | pub fn new( |
| 107 | tim: impl Peripheral<P = T> + 'd, | 114 | tim: impl Peripheral<P = T> + 'd, |
| 108 | _ch1: Option<PwmPin<'d, T, Ch1>>, | 115 | _cha: Option<PwmPin<'d, T, ChA<T>>>, |
| 109 | _ch1n: Option<ComplementaryPwmPin<'d, T, Ch1>>, | 116 | _chan: Option<ComplementaryPwmPin<'d, T, ChA<T>>>, |
| 110 | _ch2: Option<PwmPin<'d, T, Ch2>>, | 117 | _chb: Option<PwmPin<'d, T, ChB<T>>>, |
| 111 | _ch2n: Option<ComplementaryPwmPin<'d, T, Ch2>>, | 118 | _chbn: Option<ComplementaryPwmPin<'d, T, ChB<T>>>, |
| 112 | _ch3: Option<PwmPin<'d, T, Ch3>>, | 119 | _chc: Option<PwmPin<'d, T, ChC<T>>>, |
| 113 | _ch3n: Option<ComplementaryPwmPin<'d, T, Ch3>>, | 120 | _chcn: Option<ComplementaryPwmPin<'d, T, ChC<T>>>, |
| 114 | _ch4: Option<PwmPin<'d, T, Ch4>>, | 121 | _chd: Option<PwmPin<'d, T, ChD<T>>>, |
| 115 | _ch4n: Option<ComplementaryPwmPin<'d, T, Ch4>>, | 122 | _chdn: Option<ComplementaryPwmPin<'d, T, ChD<T>>>, |
| 123 | _che: Option<PwmPin<'d, T, ChE<T>>>, | ||
| 124 | _chen: Option<ComplementaryPwmPin<'d, T, ChE<T>>>, | ||
| 116 | ) -> Self { | 125 | ) -> Self { |
| 117 | Self::new_inner(tim) | 126 | Self::new_inner(tim) |
| 118 | } | 127 | } |
| @@ -124,7 +133,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> AdvancedPwm<'d, T> { | |||
| 124 | <T as crate::rcc::sealed::RccPeripheral>::reset(); | 133 | <T as crate::rcc::sealed::RccPeripheral>::reset(); |
| 125 | 134 | ||
| 126 | Self { | 135 | Self { |
| 127 | inner: tim, | 136 | _inner: tim, |
| 128 | master: Master { phantom: PhantomData }, | 137 | master: Master { phantom: PhantomData }, |
| 129 | ch_a: ChA { phantom: PhantomData }, | 138 | ch_a: ChA { phantom: PhantomData }, |
| 130 | ch_b: ChB { phantom: PhantomData }, | 139 | ch_b: ChB { phantom: PhantomData }, |
| @@ -132,48 +141,11 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> AdvancedPwm<'d, T> { | |||
| 132 | ch_d: ChD { phantom: PhantomData }, | 141 | ch_d: ChD { phantom: PhantomData }, |
| 133 | ch_e: ChE { phantom: PhantomData }, | 142 | ch_e: ChE { phantom: PhantomData }, |
| 134 | } | 143 | } |
| 135 | // | ||
| 136 | // this.inner.set_frequency(freq); | ||
| 137 | // this.inner.start(); | ||
| 138 | // | ||
| 139 | // this.inner.enable_outputs(true); | ||
| 140 | // | ||
| 141 | // this.inner | ||
| 142 | // .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); | ||
| 143 | // this.inner | ||
| 144 | // .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); | ||
| 145 | // this.inner | ||
| 146 | // .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); | ||
| 147 | // this.inner | ||
| 148 | // .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); | ||
| 149 | } | 144 | } |
| 150 | 145 | ||
| 151 | // pub fn enable(&mut self, channel: AdvancedChannel) { | ||
| 152 | // // self.inner.enable_channel(channel, true); | ||
| 153 | // // self.inner.enable_complementary_channel(channel, true); | ||
| 154 | // } | ||
| 155 | // | ||
| 156 | // pub fn disable(&mut self, channel: AdvancedChannel) { | ||
| 157 | // // self.inner.enable_complementary_channel(channel, false); | ||
| 158 | // // self.inner.enable_channel(channel, false); | ||
| 159 | // } | ||
| 160 | // | ||
| 161 | // pub fn set_freq(&mut self, freq: Hertz) { | ||
| 162 | // // self.inner.set_frequency(freq); | ||
| 163 | // } | ||
| 164 | // | ||
| 165 | // pub fn get_max_duty(&self) -> u16 { | ||
| 166 | // todo!() | ||
| 167 | // // self.inner.get_max_compare_value() | ||
| 168 | // } | ||
| 169 | // | ||
| 170 | // pub fn set_duty(&mut self, channel: AdvancedChannel, duty: u16) { | ||
| 171 | // // assert!(duty < self.get_max_duty()); | ||
| 172 | // // self.inner.set_compare_value(channel, duty) | ||
| 173 | // } | ||
| 174 | |||
| 175 | /// Set the dead time as a proportion of max_duty | 146 | /// Set the dead time as a proportion of max_duty |
| 176 | pub fn set_dead_time(&mut self, value: u16) { | 147 | pub fn set_dead_time(&mut self, _value: u16) { |
| 148 | todo!() | ||
| 177 | // let (ckd, value) = compute_dead_time_value(value); | 149 | // let (ckd, value) = compute_dead_time_value(value); |
| 178 | // | 150 | // |
| 179 | // self.inner.set_dead_time_clock_division(ckd); | 151 | // self.inner.set_dead_time_clock_division(ckd); |
| @@ -182,28 +154,39 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> AdvancedPwm<'d, T> { | |||
| 182 | } | 154 | } |
| 183 | 155 | ||
| 184 | // Represents a fixed-frequency bridge converter | 156 | // Represents a fixed-frequency bridge converter |
| 185 | pub struct BridgeConverter<T: AdvancedChannel> { | 157 | pub struct BridgeConverter<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> { |
| 186 | pub ch: T, | 158 | phantom: PhantomData<T>, |
| 159 | pub ch: C, | ||
| 187 | } | 160 | } |
| 188 | 161 | ||
| 189 | impl<T: AdvancedChannel> BridgeConverter<T> { | 162 | impl<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> { |
| 190 | pub fn new(channel: T, frequency: Hertz) -> Self { | 163 | pub fn new(channel: C, frequency: Hertz) -> Self { |
| 191 | Self { ch: channel } | 164 | Self { |
| 165 | phantom: PhantomData, | ||
| 166 | ch: channel, | ||
| 167 | } | ||
| 192 | } | 168 | } |
| 193 | 169 | ||
| 194 | pub fn set_duty(&mut self, primary: u16, secondary: u16) { | 170 | pub fn set_duty(&mut self, primary: u16, secondary: u16) { |
| 171 | let _ = T::regs(); | ||
| 172 | let _ = C::raw(); | ||
| 173 | |||
| 195 | todo!() | 174 | todo!() |
| 196 | } | 175 | } |
| 197 | } | 176 | } |
| 198 | 177 | ||
| 199 | // Represents a variable-frequency resonant converter | 178 | // Represents a variable-frequency resonant converter |
| 200 | pub struct ResonantConverter<T: AdvancedChannel> { | 179 | pub struct ResonantConverter<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> { |
| 201 | pub ch: T, | 180 | phantom: PhantomData<T>, |
| 181 | pub ch: C, | ||
| 202 | } | 182 | } |
| 203 | 183 | ||
| 204 | impl<T: AdvancedChannel> ResonantConverter<T> { | 184 | impl<T: AdvancedCaptureCompare16bitInstance, C: AdvancedChannel<T>> ResonantConverter<T, C> { |
| 205 | pub fn new(channel: T, min_frequency: Hertz) -> Self { | 185 | pub fn new(channel: C, min_frequency: Hertz) -> Self { |
| 206 | Self { ch: channel } | 186 | Self { |
| 187 | phantom: PhantomData, | ||
| 188 | ch: channel, | ||
| 189 | } | ||
| 207 | } | 190 | } |
| 208 | 191 | ||
| 209 | pub fn set_frequency(&mut self, frequency: Hertz) { | 192 | pub fn set_frequency(&mut self, frequency: Hertz) { |
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index 1838bfdfe..67009e788 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs | |||
| @@ -3,8 +3,14 @@ pub mod advanced_pwm; | |||
| 3 | pub mod complementary_pwm; | 3 | pub mod complementary_pwm; |
| 4 | pub mod simple_pwm; | 4 | pub mod simple_pwm; |
| 5 | 5 | ||
| 6 | #[cfg(hrtim_v1)] | ||
| 7 | use core::ops; | ||
| 8 | |||
| 6 | use stm32_metapac::timer::vals::Ckd; | 9 | use stm32_metapac::timer::vals::Ckd; |
| 7 | 10 | ||
| 11 | #[cfg(hrtim_v1)] | ||
| 12 | use crate::time::Hertz; | ||
| 13 | |||
| 8 | #[cfg(feature = "unstable-pac")] | 14 | #[cfg(feature = "unstable-pac")] |
| 9 | pub mod low_level { | 15 | pub mod low_level { |
| 10 | pub use super::sealed::*; | 16 | pub use super::sealed::*; |
| @@ -30,27 +36,6 @@ impl Channel { | |||
| 30 | } | 36 | } |
| 31 | 37 | ||
| 32 | #[derive(Clone, Copy)] | 38 | #[derive(Clone, Copy)] |
| 33 | pub enum AdvancedChannel { | ||
| 34 | ChA, | ||
| 35 | ChB, | ||
| 36 | ChC, | ||
| 37 | ChD, | ||
| 38 | ChE, | ||
| 39 | } | ||
| 40 | |||
| 41 | impl AdvancedChannel { | ||
| 42 | pub fn raw(&self) -> usize { | ||
| 43 | match self { | ||
| 44 | AdvancedChannel::ChA => 0, | ||
| 45 | AdvancedChannel::ChB => 1, | ||
| 46 | AdvancedChannel::ChC => 2, | ||
| 47 | AdvancedChannel::ChD => 3, | ||
| 48 | AdvancedChannel::ChE => 4, | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | #[derive(Clone, Copy)] | ||
| 54 | pub enum OutputCompareMode { | 39 | pub enum OutputCompareMode { |
| 55 | Frozen, | 40 | Frozen, |
| 56 | ActiveOnMatch, | 41 | ActiveOnMatch, |
| @@ -77,16 +62,87 @@ impl From<OutputCompareMode> for stm32_metapac::timer::vals::Ocm { | |||
| 77 | } | 62 | } |
| 78 | } | 63 | } |
| 79 | 64 | ||
| 65 | #[cfg(hrtim_v1)] | ||
| 66 | #[derive(Clone, Copy)] | ||
| 67 | pub(crate) enum HighResolutionControlPrescaler { | ||
| 68 | Div1, | ||
| 69 | Div2, | ||
| 70 | Div4, | ||
| 71 | Div8, | ||
| 72 | Div16, | ||
| 73 | Div32, | ||
| 74 | Div64, | ||
| 75 | Div128, | ||
| 76 | } | ||
| 77 | |||
| 78 | #[cfg(hrtim_v1)] | ||
| 79 | impl ops::Div<HighResolutionControlPrescaler> for Hertz { | ||
| 80 | type Output = Hertz; | ||
| 81 | |||
| 82 | fn div(self, rhs: HighResolutionControlPrescaler) -> Self::Output { | ||
| 83 | let divisor = match rhs { | ||
| 84 | HighResolutionControlPrescaler::Div1 => 1, | ||
| 85 | HighResolutionControlPrescaler::Div2 => 2, | ||
| 86 | HighResolutionControlPrescaler::Div4 => 4, | ||
| 87 | HighResolutionControlPrescaler::Div8 => 8, | ||
| 88 | HighResolutionControlPrescaler::Div16 => 16, | ||
| 89 | HighResolutionControlPrescaler::Div32 => 32, | ||
| 90 | HighResolutionControlPrescaler::Div64 => 64, | ||
| 91 | HighResolutionControlPrescaler::Div128 => 128, | ||
| 92 | }; | ||
| 93 | |||
| 94 | Hertz(self.0 / divisor) | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | #[cfg(hrtim_v1)] | ||
| 99 | impl From<HighResolutionControlPrescaler> for u8 { | ||
| 100 | fn from(val: HighResolutionControlPrescaler) -> Self { | ||
| 101 | match val { | ||
| 102 | HighResolutionControlPrescaler::Div1 => 0b000, | ||
| 103 | HighResolutionControlPrescaler::Div2 => 0b001, | ||
| 104 | HighResolutionControlPrescaler::Div4 => 0b010, | ||
| 105 | HighResolutionControlPrescaler::Div8 => 0b011, | ||
| 106 | HighResolutionControlPrescaler::Div16 => 0b100, | ||
| 107 | HighResolutionControlPrescaler::Div32 => 0b101, | ||
| 108 | HighResolutionControlPrescaler::Div64 => 0b110, | ||
| 109 | HighResolutionControlPrescaler::Div128 => 0b111, | ||
| 110 | } | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | #[cfg(hrtim_v1)] | ||
| 115 | impl HighResolutionControlPrescaler { | ||
| 116 | pub fn compute_min(base_f: Hertz, frequency: Hertz) -> Self { | ||
| 117 | *[ | ||
| 118 | HighResolutionControlPrescaler::Div1, | ||
| 119 | HighResolutionControlPrescaler::Div2, | ||
| 120 | HighResolutionControlPrescaler::Div4, | ||
| 121 | HighResolutionControlPrescaler::Div8, | ||
| 122 | HighResolutionControlPrescaler::Div16, | ||
| 123 | HighResolutionControlPrescaler::Div32, | ||
| 124 | HighResolutionControlPrescaler::Div64, | ||
| 125 | HighResolutionControlPrescaler::Div128, | ||
| 126 | ] | ||
| 127 | .iter() | ||
| 128 | .skip_while(|psc| frequency <= base_f / **psc) | ||
| 129 | .next() | ||
| 130 | .unwrap() | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 80 | pub(crate) mod sealed { | 134 | pub(crate) mod sealed { |
| 81 | use super::*; | 135 | use super::*; |
| 82 | 136 | ||
| 83 | #[cfg(hrtim_v1)] | 137 | #[cfg(hrtim_v1)] |
| 84 | pub trait AdvancedCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance { | 138 | pub trait AdvancedCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance { |
| 85 | fn enable_outputs(&mut self, enable: bool); | 139 | fn set_master_frequency(frequency: Hertz); |
| 86 | 140 | ||
| 87 | fn set_output_compare_mode(&mut self, channel: AdvancedChannel, mode: OutputCompareMode); | 141 | fn set_channel_frequency(channnel: usize, frequency: Hertz); |
| 88 | 142 | ||
| 89 | fn enable_channel(&mut self, channel: AdvancedChannel, enable: bool); | 143 | // fn enable_outputs(enable: bool); |
| 144 | // | ||
| 145 | // fn enable_channel(&mut self, channel: usize, enable: bool); | ||
| 90 | } | 146 | } |
| 91 | 147 | ||
| 92 | pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { | 148 | pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { |
| @@ -288,11 +344,45 @@ foreach_interrupt! { | |||
| 288 | 344 | ||
| 289 | ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { | 345 | ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { |
| 290 | impl crate::pwm::sealed::AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst { | 346 | impl crate::pwm::sealed::AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst { |
| 291 | fn enable_outputs(&mut self, enable: bool) { todo!() } | 347 | fn set_master_frequency(frequency: Hertz) { |
| 348 | use crate::rcc::sealed::RccPeripheral; | ||
| 349 | use crate::timer::sealed::HighResolutionControlInstance; | ||
| 350 | |||
| 351 | let f = frequency.0; | ||
| 352 | // TODO: fix frequency source | ||
| 353 | // let timer_f = Self::frequency().0; | ||
| 354 | let timer_f = Hertz(144_000_000).0; | ||
| 355 | let base_f = Hertz((32 * timer_f as u64 / u16::MAX as u64) as u32); | ||
| 356 | let psc = HighResolutionControlPrescaler::compute_min(base_f, frequency); | ||
| 357 | |||
| 358 | let psc_timer_f = Hertz(timer_f) / psc; | ||
| 359 | let per: u16 = (psc_timer_f / f).0 as u16; | ||
| 360 | |||
| 361 | let regs = Self::regs(); | ||
| 362 | |||
| 363 | regs.mcr().modify(|w| w.set_ckpsc(psc.into())); | ||
| 364 | regs.mper().modify(|w| w.set_mper(per)); | ||
| 365 | } | ||
| 366 | |||
| 367 | fn set_channel_frequency(channel: usize, frequency: Hertz) { | ||
| 368 | use crate::rcc::sealed::RccPeripheral; | ||
| 369 | use crate::timer::sealed::HighResolutionControlInstance; | ||
| 370 | |||
| 371 | let f = frequency.0; | ||
| 372 | // TODO: fix frequency source | ||
| 373 | // let timer_f = Self::frequency().0; | ||
| 374 | let timer_f = Hertz(144_000_000).0; | ||
| 375 | let base_f = Hertz((32 * timer_f as u64 / u16::MAX as u64) as u32); | ||
| 376 | let psc = HighResolutionControlPrescaler::compute_min(base_f, frequency); | ||
| 292 | 377 | ||
| 293 | fn set_output_compare_mode(&mut self, channel: AdvancedChannel, mode: OutputCompareMode) { todo!() } | 378 | let psc_timer_f = Hertz(timer_f) / psc; |
| 379 | let per: u16 = (psc_timer_f / f).0 as u16; | ||
| 294 | 380 | ||
| 295 | fn enable_channel(&mut self, channel: AdvancedChannel, enable: bool) { todo!() } | 381 | let regs = Self::regs(); |
| 382 | |||
| 383 | regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); | ||
| 384 | regs.tim(channel).per().modify(|w| w.set_per(per)); | ||
| 385 | } | ||
| 296 | } | 386 | } |
| 297 | 387 | ||
| 298 | impl AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst { | 388 | impl AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst { |
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 03b9b3cf8..89cb16668 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs | |||
| @@ -51,66 +51,7 @@ pub(crate) mod sealed { | |||
| 51 | pub trait HighResolutionControlInstance: RccPeripheral { | 51 | pub trait HighResolutionControlInstance: RccPeripheral { |
| 52 | type Interrupt: interrupt::typelevel::Interrupt; | 52 | type Interrupt: interrupt::typelevel::Interrupt; |
| 53 | 53 | ||
| 54 | fn regs_highres() -> crate::pac::hrtim::Hrtim; | 54 | fn regs() -> crate::pac::hrtim::Hrtim; |
| 55 | |||
| 56 | fn set_master_frequency(&mut self, frequency: Hertz); | ||
| 57 | |||
| 58 | fn set_channel_frequency(&mut self, channel: usize, frequency: Hertz); | ||
| 59 | |||
| 60 | fn start(&mut self); | ||
| 61 | |||
| 62 | fn stop(&mut self); | ||
| 63 | |||
| 64 | fn reset(&mut self); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 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 | } | ||
| 114 | } | 55 | } |
| 115 | } | 56 | } |
| 116 | 57 | ||
| @@ -285,95 +226,9 @@ foreach_interrupt! { | |||
| 285 | impl sealed::HighResolutionControlInstance for crate::peripherals::$inst { | 226 | impl sealed::HighResolutionControlInstance for crate::peripherals::$inst { |
| 286 | type Interrupt = crate::interrupt::typelevel::$irq; | 227 | type Interrupt = crate::interrupt::typelevel::$irq; |
| 287 | 228 | ||
| 288 | fn regs_highres() -> crate::pac::hrtim::Hrtim { | 229 | fn regs() -> crate::pac::hrtim::Hrtim { |
| 289 | crate::pac::$inst | 230 | crate::pac::$inst |
| 290 | } | 231 | } |
| 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 | |||
| 372 | fn start(&mut self) { todo!() } | ||
| 373 | |||
| 374 | fn stop(&mut self) { todo!() } | ||
| 375 | |||
| 376 | fn reset(&mut self) { todo!() } | ||
| 377 | } | 232 | } |
| 378 | 233 | ||
| 379 | impl HighResolutionControlInstance for crate::peripherals::$inst { | 234 | impl HighResolutionControlInstance for crate::peripherals::$inst { |
