From ff526e1604f4e9edc682f4bc270ddc815a860e48 Mon Sep 17 00:00:00 2001 From: Liu Hancheng Date: Sat, 4 Jan 2025 20:16:34 +0800 Subject: refactor: update DMA transfer functions to use separate memory and peripheral sizes --- embassy-stm32/src/dma/dma_bdma.rs | 38 ++++++++++++++++++++++++----------- embassy-stm32/src/timer/simple_pwm.rs | 26 +++++++++--------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs index 1945c3587..8b4b454c0 100644 --- a/embassy-stm32/src/dma/dma_bdma.rs +++ b/embassy-stm32/src/dma/dma_bdma.rs @@ -340,7 +340,8 @@ impl AnyChannel { mem_addr: *mut u32, mem_len: usize, incr_mem: bool, - data_size: WordSize, + mem_size: WordSize, + peripheral_size: WordSize, options: TransferOptions, ) { let info = self.info(); @@ -380,8 +381,8 @@ impl AnyChannel { }); ch.cr().write(|w| { w.set_dir(dir.into()); - w.set_msize(data_size.into()); - w.set_psize(data_size.into()); + w.set_msize(mem_size.into()); + w.set_psize(peripheral_size.into()); w.set_pl(options.priority.into()); w.set_minc(incr_mem); w.set_pinc(false); @@ -414,8 +415,8 @@ impl AnyChannel { ch.mar().write_value(mem_addr as u32); ch.ndtr().write(|w| w.set_ndt(mem_len as u16)); ch.cr().write(|w| { - w.set_psize(data_size.into()); - w.set_msize(data_size.into()); + w.set_psize(peripheral_size.into()); + w.set_msize(mem_size.into()); w.set_minc(incr_mem); w.set_dir(dir.into()); w.set_teie(true); @@ -602,27 +603,28 @@ impl<'a> Transfer<'a> { buf.len(), true, W::size(), + W::size(), options, ) } /// Create a new write DMA transfer (memory to peripheral). - pub unsafe fn new_write( + pub unsafe fn new_write( channel: impl Peripheral

+ 'a, request: Request, - buf: &'a [W], - peri_addr: *mut W, + buf: &'a [MW], + peri_addr: *mut PW, options: TransferOptions, ) -> Self { Self::new_write_raw(channel, request, buf, peri_addr, options) } /// Create a new write DMA transfer (memory to peripheral), using raw pointers. - pub unsafe fn new_write_raw( + pub unsafe fn new_write_raw( channel: impl Peripheral

+ 'a, request: Request, buf: *const [W], - peri_addr: *mut W, + peri_addr: *mut PW, options: TransferOptions, ) -> Self { into_ref!(channel); @@ -636,6 +638,7 @@ impl<'a> Transfer<'a> { buf.len(), true, W::size(), + W::size(), options, ) } @@ -660,6 +663,7 @@ impl<'a> Transfer<'a> { count, false, W::size(), + W::size(), options, ) } @@ -673,15 +677,23 @@ impl<'a> Transfer<'a> { mem_len: usize, incr_mem: bool, data_size: WordSize, + peripheral_size: WordSize, options: TransferOptions, ) -> Self { assert!(mem_len > 0 && mem_len <= 0xFFFF); channel.configure( - _request, dir, peri_addr, mem_addr, mem_len, incr_mem, data_size, options, + _request, + dir, + peri_addr, + mem_addr, + mem_len, + incr_mem, + data_size, + peripheral_size, + options, ); channel.start(); - Self { channel } } @@ -814,6 +826,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { len, true, data_size, + data_size, options, ); @@ -966,6 +979,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { len, true, data_size, + data_size, options, ); diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index f36fa026c..8d3c9a131 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -334,7 +334,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { &mut dma, req, duty, - self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut _, + self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, dma_transfer_option, ) .await @@ -362,13 +362,7 @@ macro_rules! impl_waveform_chx { ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Generate a sequence of PWM waveform - /// - /// Note: - /// 1. you will need to provide corresponding TIMx_CHy DMA channel to use this method. - /// 2. Please make sure the duty data length is aligned to the timer data width(16-bit or 32-bit). - /// 3. Please notice the endianess of the duty data. STM32 use little endian, - /// for example, 0x12345678 as u32 will be stored as [0x78, 0x56, 0x34, 0x12] in memory. - pub async fn $fn_name(&mut self, dma: impl Peripheral

>, duty: &[u8]) { + pub async fn $fn_name(&mut self, dma: impl Peripheral

>, duty: &[u16]) { use crate::pac::timer::vals::Ccds; into_ref!(dma); @@ -411,32 +405,30 @@ macro_rules! impl_waveform_chx { match self.inner.bits() { TimerBits::Bits16 => { - // the data must be aligned to double words - assert!(duty.len() % 2 == 0); - let duty = core::slice::from_raw_parts(duty.as_ptr() as *const u16, duty.len() / 2); Transfer::new_write( &mut dma, req, duty, - self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16, dma_transfer_option, ) .await } - #[cfg(not(stm32l0))] + #[cfg(not(any(stm32l0, bdma, gpdma)))] TimerBits::Bits32 => { - // the data must be aligned to quad words - assert!(duty.len() % 4 == 0); - let duty = core::slice::from_raw_parts(duty.as_ptr() as *const u32, duty.len() / 4); Transfer::new_write( &mut dma, req, duty, - self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32, dma_transfer_option, ) .await } + #[cfg(any(stm32l0, bdma, gpdma))] + _ => { + panic!("unsupported timer bits") + } }; }; -- cgit