From 02da66aec8432f71b8f3121a972044191df2d7e8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 15 Apr 2024 21:47:37 +0200 Subject: [PATCH] stm32/dma: add ChannelAndRequest helper. --- embassy-stm32/src/dma/mod.rs | 3 ++ embassy-stm32/src/dma/util.rs | 60 +++++++++++++++++++++++++++++++++++ embassy-stm32/src/spi/mod.rs | 40 +++++++++++------------ embassy-stm32/src/traits.rs | 7 ++-- 4 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 embassy-stm32/src/dma/util.rs diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 7e3681469..8766d0a60 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -16,6 +16,9 @@ mod dmamux; #[cfg(dmamux)] pub use dmamux::*; +mod util; +pub(crate) use util::*; + pub(crate) mod ringbuffer; pub mod word; diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs new file mode 100644 index 000000000..962ea2501 --- /dev/null +++ b/embassy-stm32/src/dma/util.rs @@ -0,0 +1,60 @@ +use embassy_hal_internal::PeripheralRef; + +use super::word::Word; +use super::{AnyChannel, Request, Transfer, TransferOptions}; + +/// Convenience wrapper, contains a channel and a request number. +/// +/// Commonly used in peripheral drivers that own DMA channels. +pub(crate) struct ChannelAndRequest<'d> { + pub channel: PeripheralRef<'d, AnyChannel>, + pub request: Request, +} + +impl<'d> ChannelAndRequest<'d> { + pub unsafe fn read<'a, W: Word>( + &'a mut self, + peri_addr: *mut W, + buf: &'a mut [W], + options: TransferOptions, + ) -> Transfer<'a> { + Transfer::new_read(&mut self.channel, self.request, peri_addr, buf, options) + } + + pub unsafe fn read_raw<'a, W: Word>( + &'a mut self, + peri_addr: *mut W, + buf: *mut [W], + options: TransferOptions, + ) -> Transfer<'a> { + Transfer::new_read_raw(&mut self.channel, self.request, peri_addr, buf, options) + } + + pub unsafe fn write<'a, W: Word>( + &'a mut self, + buf: &'a [W], + peri_addr: *mut W, + options: TransferOptions, + ) -> Transfer<'a> { + Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options) + } + + pub unsafe fn write_raw<'a, W: Word>( + &'a mut self, + buf: *const [W], + peri_addr: *mut W, + options: TransferOptions, + ) -> Transfer<'a> { + Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) + } + + pub unsafe fn write_repeated<'a, W: Word>( + &'a mut self, + repeated: &'a W, + count: usize, + peri_addr: *mut W, + options: TransferOptions, + ) -> Transfer<'a> { + Transfer::new_write_repeated(&mut self.channel, self.request, repeated, count, peri_addr, options) + } +} diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index a4465e289..303b85346 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -9,7 +9,7 @@ use embassy_futures::join::join; use embassy_hal_internal::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; -use crate::dma::{slice_ptr_parts, word, AnyChannel, Request, Transfer}; +use crate::dma::{slice_ptr_parts, word, ChannelAndRequest}; use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; use crate::mode::{Async, Blocking, Mode as PeriMode}; use crate::pac::spi::{regs, vals, Spi as Regs}; @@ -97,8 +97,8 @@ pub struct Spi<'d, T: Instance, M: PeriMode> { sck: Option>, mosi: Option>, miso: Option>, - txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, - rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, + txdma: Option>, + rxdma: Option>, _phantom: PhantomData, current_word_size: word_impl::Config, } @@ -109,8 +109,8 @@ impl<'d, T: Instance, M: PeriMode> Spi<'d, T, M> { sck: Option>, mosi: Option>, miso: Option>, - txdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, - rxdma: Option<(PeripheralRef<'d, AnyChannel>, Request)>, + txdma: Option>, + rxdma: Option>, config: Config, ) -> Self { into_ref!(peri); @@ -593,9 +593,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> { w.set_spe(false); }); - let (txdma, tx_request) = self.txdma.as_mut().unwrap(); let tx_dst = T::REGS.tx_ptr(); - let tx_f = unsafe { Transfer::new_write(txdma, *tx_request, data, tx_dst, Default::default()) }; + let tx_f = unsafe { self.txdma.as_mut().unwrap().write(data, tx_dst, Default::default()) }; set_txdmaen(T::REGS, true); T::REGS.cr1().modify(|w| { @@ -632,22 +631,16 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let clock_byte_count = data.len(); - let (rxdma, rx_request) = self.rxdma.as_mut().unwrap(); let rx_src = T::REGS.rx_ptr(); - let rx_f = unsafe { Transfer::new_read(rxdma, *rx_request, rx_src, data, Default::default()) }; + let rx_f = unsafe { self.rxdma.as_mut().unwrap().read(rx_src, data, Default::default()) }; - let (txdma, tx_request) = self.txdma.as_mut().unwrap(); let tx_dst = T::REGS.tx_ptr(); let clock_byte = 0x00u8; let tx_f = unsafe { - Transfer::new_write_repeated( - txdma, - *tx_request, - &clock_byte, - clock_byte_count, - tx_dst, - Default::default(), - ) + self.txdma + .as_mut() + .unwrap() + .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default()) }; set_txdmaen(T::REGS, true); @@ -685,13 +678,16 @@ impl<'d, T: Instance> Spi<'d, T, Async> { set_rxdmaen(T::REGS, true); - let (rxdma, rx_request) = self.rxdma.as_mut().unwrap(); let rx_src = T::REGS.rx_ptr(); - let rx_f = unsafe { Transfer::new_read_raw(rxdma, *rx_request, rx_src, read, Default::default()) }; + let rx_f = unsafe { self.rxdma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; - let (txdma, tx_request) = self.txdma.as_mut().unwrap(); let tx_dst = T::REGS.tx_ptr(); - let tx_f = unsafe { Transfer::new_write_raw(txdma, *tx_request, write, tx_dst, Default::default()) }; + let tx_f = unsafe { + self.txdma + .as_mut() + .unwrap() + .write_raw(write, tx_dst, Default::default()) + }; set_txdmaen(T::REGS, true); T::REGS.cr1().modify(|w| { diff --git a/embassy-stm32/src/traits.rs b/embassy-stm32/src/traits.rs index 539302c49..f603f661f 100644 --- a/embassy-stm32/src/traits.rs +++ b/embassy-stm32/src/traits.rs @@ -73,8 +73,11 @@ macro_rules! dma_trait_impl { macro_rules! new_dma { ($name:ident) => {{ let dma = $name.into_ref(); - let req = dma.request(); - Some((dma.map_into(), req)) + let request = dma.request(); + Some(crate::dma::ChannelAndRequest { + channel: dma.map_into(), + request, + }) }}; }