diff options
| -rw-r--r-- | embassy-stm32/src/timer/complementary_pwm.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index a450705a2..07d5ec826 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs | |||
| @@ -134,6 +134,66 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { | |||
| 134 | self.inner.set_dead_time_clock_division(ckd); | 134 | self.inner.set_dead_time_clock_division(ckd); |
| 135 | self.inner.set_dead_time_value(value); | 135 | self.inner.set_dead_time_value(value); |
| 136 | } | 136 | } |
| 137 | |||
| 138 | /// Generate a sequence of PWM waveform | ||
| 139 | /// | ||
| 140 | /// Note: | ||
| 141 | /// you will need to provide corresponding TIMx_UP DMA channel to use this method. | ||
| 142 | pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { | ||
| 143 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | ||
| 144 | let req = dma.request(); | ||
| 145 | |||
| 146 | let original_duty_state = self.inner.get_compare_value(channel); | ||
| 147 | let original_enable_state = self.inner.get_channel_enable_state(channel); | ||
| 148 | let original_update_dma_state = self.inner.get_update_dma_state(); | ||
| 149 | |||
| 150 | if !original_update_dma_state { | ||
| 151 | self.inner.enable_update_dma(true); | ||
| 152 | } | ||
| 153 | |||
| 154 | if !original_enable_state { | ||
| 155 | self.inner.enable_channel(channel, true); | ||
| 156 | } | ||
| 157 | |||
| 158 | unsafe { | ||
| 159 | #[cfg(not(any(bdma, gpdma)))] | ||
| 160 | use crate::dma::{Burst, FifoThreshold}; | ||
| 161 | use crate::dma::{Transfer, TransferOptions}; | ||
| 162 | |||
| 163 | let dma_transfer_option = TransferOptions { | ||
| 164 | #[cfg(not(any(bdma, gpdma)))] | ||
| 165 | fifo_threshold: Some(FifoThreshold::Full), | ||
| 166 | #[cfg(not(any(bdma, gpdma)))] | ||
| 167 | mburst: Burst::Incr8, | ||
| 168 | ..Default::default() | ||
| 169 | }; | ||
| 170 | |||
| 171 | Transfer::new_write( | ||
| 172 | dma, | ||
| 173 | req, | ||
| 174 | duty, | ||
| 175 | self.inner.regs_gp16().ccr(channel.index()).as_ptr() as *mut u16, | ||
| 176 | dma_transfer_option, | ||
| 177 | ) | ||
| 178 | .await | ||
| 179 | }; | ||
| 180 | |||
| 181 | // restore output compare state | ||
| 182 | if !original_enable_state { | ||
| 183 | self.inner.enable_channel(channel, false); | ||
| 184 | } | ||
| 185 | |||
| 186 | self.inner.set_compare_value(channel, original_duty_state); | ||
| 187 | |||
| 188 | // Since DMA is closed before timer update event trigger DMA is turn off, | ||
| 189 | // this can almost always trigger a DMA FIFO error. | ||
| 190 | // | ||
| 191 | // optional TODO: | ||
| 192 | // clean FEIF after disable UDE | ||
| 193 | if !original_update_dma_state { | ||
| 194 | self.inner.enable_update_dma(false); | ||
| 195 | } | ||
| 196 | } | ||
| 137 | } | 197 | } |
| 138 | 198 | ||
| 139 | impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { | 199 | impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { |
