diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-09-05 16:56:18 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-09-05 16:56:18 +0200 |
| commit | 6438068c162298e1820875f31f61bae6a7e994d5 (patch) | |
| tree | 2c71ac1d269356a3dd683a8e9462ab1c414f7dcb | |
| parent | 4b27444e1cd8f56ec620a75275c22846b7f782d1 (diff) | |
| parent | 71ad56357925a3f2b98a20bcce3c1bdb0ac63be5 (diff) | |
Merge pull request #4368 from nikvoid/stm32-complementary-pwm-dma
stm32: add `waveform_up` function for complementary PWM too
| -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 7d6c2273e..68cdec302 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs | |||
| @@ -202,6 +202,66 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { | |||
| 202 | self.inner.set_dead_time_clock_division(ckd); | 202 | self.inner.set_dead_time_clock_division(ckd); |
| 203 | self.inner.set_dead_time_value(value); | 203 | self.inner.set_dead_time_value(value); |
| 204 | } | 204 | } |
| 205 | |||
| 206 | /// Generate a sequence of PWM waveform | ||
| 207 | /// | ||
| 208 | /// Note: | ||
| 209 | /// you will need to provide corresponding TIMx_UP DMA channel to use this method. | ||
| 210 | pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { | ||
| 211 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | ||
| 212 | let req = dma.request(); | ||
| 213 | |||
| 214 | let original_duty_state = self.inner.get_compare_value(channel); | ||
| 215 | let original_enable_state = self.inner.get_channel_enable_state(channel); | ||
| 216 | let original_update_dma_state = self.inner.get_update_dma_state(); | ||
| 217 | |||
| 218 | if !original_update_dma_state { | ||
| 219 | self.inner.enable_update_dma(true); | ||
| 220 | } | ||
| 221 | |||
| 222 | if !original_enable_state { | ||
| 223 | self.inner.enable_channel(channel, true); | ||
| 224 | } | ||
| 225 | |||
| 226 | unsafe { | ||
| 227 | #[cfg(not(any(bdma, gpdma)))] | ||
| 228 | use crate::dma::{Burst, FifoThreshold}; | ||
| 229 | use crate::dma::{Transfer, TransferOptions}; | ||
| 230 | |||
| 231 | let dma_transfer_option = TransferOptions { | ||
| 232 | #[cfg(not(any(bdma, gpdma)))] | ||
| 233 | fifo_threshold: Some(FifoThreshold::Full), | ||
| 234 | #[cfg(not(any(bdma, gpdma)))] | ||
| 235 | mburst: Burst::Incr8, | ||
| 236 | ..Default::default() | ||
| 237 | }; | ||
| 238 | |||
| 239 | Transfer::new_write( | ||
| 240 | dma, | ||
| 241 | req, | ||
| 242 | duty, | ||
| 243 | self.inner.regs_gp16().ccr(channel.index()).as_ptr() as *mut u16, | ||
| 244 | dma_transfer_option, | ||
| 245 | ) | ||
| 246 | .await | ||
| 247 | }; | ||
| 248 | |||
| 249 | // restore output compare state | ||
| 250 | if !original_enable_state { | ||
| 251 | self.inner.enable_channel(channel, false); | ||
| 252 | } | ||
| 253 | |||
| 254 | self.inner.set_compare_value(channel, original_duty_state); | ||
| 255 | |||
| 256 | // Since DMA is closed before timer update event trigger DMA is turn off, | ||
| 257 | // this can almost always trigger a DMA FIFO error. | ||
| 258 | // | ||
| 259 | // optional TODO: | ||
| 260 | // clean FEIF after disable UDE | ||
| 261 | if !original_update_dma_state { | ||
| 262 | self.inner.enable_update_dma(false); | ||
| 263 | } | ||
| 264 | } | ||
| 205 | } | 265 | } |
| 206 | 266 | ||
| 207 | impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { | 267 | impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { |
