aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaulIQ <[email protected]>2025-05-21 12:27:25 +0300
committerRaulIQ <[email protected]>2025-05-21 12:27:25 +0300
commit05c511355638c3a55ab509ef9b2e30f5564b6282 (patch)
tree966394083ec0626dc566e73b08c1f7ccb22b0e4d
parent7cbc9058bc726900571a7858c581f60cd8cb0266 (diff)
add waveform_up_multichannel using DMAR/DCR
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 8fd7e8df4..c6fd169fc 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -381,6 +381,74 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
381 self.inner.enable_update_dma(false); 381 self.inner.enable_update_dma(false);
382 } 382 }
383 } 383 }
384
385 /// Generate a multichannel sequence of PWM waveforms using DMA triggered by timer update events.
386 ///
387 /// This method utilizes the timer's DMA burst transfer capability to update multiple CCRx registers
388 /// in sequence on each update event (UEV). The data is written via the DMAR register using the
389 /// DMA base address (DBA) and burst length (DBL) configured in the DCR register.
390 ///
391 /// Note:
392 /// you will need to provide corresponding TIMx_UP DMA channel to use this method.
393 pub async fn waveform_up_multichannel(
394 &mut self,
395 dma: Peri<'_, impl super::UpDma<T>>,
396 starting_channel: Channel,
397 ending_channel: Channel,
398 duty: &[u16],
399 ) {
400 let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32;
401 let start_ch_index = starting_channel.index();
402 let end_ch_index = ending_channel.index();
403
404 assert!(start_ch_index <= end_ch_index);
405
406 let ccrx_addr = self.inner.regs_gp16().ccr(start_ch_index).as_ptr() as u32;
407 self.inner
408 .regs_gp16()
409 .dcr()
410 .modify(|w| w.set_dba(((ccrx_addr - cr1_addr) / 4) as u8));
411 self.inner
412 .regs_gp16()
413 .dcr()
414 .modify(|w| w.set_dbl((end_ch_index - start_ch_index) as u8));
415
416 #[allow(clippy::let_unit_value)] // eg. stm32f334
417 let req = dma.request();
418
419 let original_update_dma_state = self.inner.get_update_dma_state();
420 if !original_update_dma_state {
421 self.inner.enable_update_dma(true);
422 }
423
424 unsafe {
425 #[cfg(not(any(bdma, gpdma)))]
426 use crate::dma::{Burst, FifoThreshold};
427 use crate::dma::{Transfer, TransferOptions};
428
429 let dma_transfer_option = TransferOptions {
430 #[cfg(not(any(bdma, gpdma)))]
431 fifo_threshold: Some(FifoThreshold::Full),
432 #[cfg(not(any(bdma, gpdma)))]
433 mburst: Burst::Incr4,
434 ..Default::default()
435 };
436
437 Transfer::new_write(
438 dma,
439 req,
440 duty,
441 self.inner.regs_gp16().dmar().as_ptr() as *mut u16,
442 dma_transfer_option,
443 )
444 .await
445 };
446
447 if !original_update_dma_state {
448 self.inner.enable_update_dma(false);
449 }
450 }
451
384} 452}
385 453
386macro_rules! impl_waveform_chx { 454macro_rules! impl_waveform_chx {