From 7d5377e97080642edbc0482b0753a86be448a3a9 Mon Sep 17 00:00:00 2001 From: Dominic Fischer Date: Wed, 26 Jun 2024 00:28:01 +0100 Subject: [PATCH] [2/3] DMA Move API: Move DMA descriptors to peripheral drivers --- esp-hal/CHANGELOG.md | 1 + esp-hal/src/aes/mod.rs | 51 ++-- esp-hal/src/dma/gdma.rs | 18 +- esp-hal/src/dma/mod.rs | 336 ++++++++++--------------- esp-hal/src/dma/pdma.rs | 36 +-- esp-hal/src/i2s.rs | 124 ++++++--- esp-hal/src/lcd_cam/cam.rs | 38 ++- esp-hal/src/lcd_cam/lcd/i8080.rs | 23 +- esp-hal/src/parl_io.rs | 53 +++- esp-hal/src/spi/master.rs | 154 +++++++++--- esp-hal/src/spi/slave.rs | 65 +++-- examples/src/bin/embassy_i2s_read.rs | 11 +- examples/src/bin/embassy_i2s_sound.rs | 11 +- examples/src/bin/embassy_parl_io_rx.rs | 10 +- examples/src/bin/embassy_parl_io_tx.rs | 10 +- examples/src/bin/embassy_spi.rs | 13 +- examples/src/bin/i2s_read.rs | 11 +- examples/src/bin/i2s_sound.rs | 11 +- examples/src/bin/lcd_cam_ov2640.rs | 22 +- examples/src/bin/lcd_i8080.rs | 10 +- examples/src/bin/parl_io_rx.rs | 10 +- examples/src/bin/parl_io_tx.rs | 10 +- examples/src/bin/qspi_flash.rs | 13 +- examples/src/bin/spi_loopback_dma.rs | 13 +- examples/src/bin/spi_slave_dma.rs | 13 +- hil-test/tests/aes_dma.rs | 56 ++--- hil-test/tests/i2s.rs | 12 +- hil-test/tests/spi_full_duplex_dma.rs | 81 +++--- 28 files changed, 650 insertions(+), 566 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 9b31e0faf33..46d866fad6f 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - esp-hal-embassy: make executor code optional (but default) again - Improved interrupt latency on RISC-V based chips (#1679) - `esp_wifi::initialize` no longer requires running maximum CPU clock, instead check it runs above 80MHz. (#1688) +- Move DMA descriptors from DMA Channel to each individual peripheral driver. (#1719) ### Removed - uart: Removed `configure_pins` methods (#1592) diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 20e56b9311a..c859b538dcb 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -225,6 +225,8 @@ pub mod dma { AesPeripheral, Channel, ChannelTypes, + DescriptorChain, + DmaDescriptor, DmaPeripheral, DmaTransferTxRx, RxPrivate, @@ -259,6 +261,8 @@ pub mod dma { pub aes: super::Aes<'d>, pub(crate) channel: Channel<'d, C, crate::Blocking>, + tx_chain: DescriptorChain, + rx_chain: DescriptorChain, } pub trait WithDmaAes<'d, C> @@ -266,7 +270,12 @@ pub mod dma { C: ChannelTypes, C::P: AesPeripheral, { - fn with_dma(self, channel: Channel<'d, C, crate::Blocking>) -> AesDma<'d, C>; + fn with_dma( + self, + channel: Channel<'d, C, crate::Blocking>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], + ) -> AesDma<'d, C>; } impl<'d, C> WithDmaAes<'d, C> for crate::aes::Aes<'d> @@ -274,10 +283,20 @@ pub mod dma { C: ChannelTypes, C::P: AesPeripheral, { - fn with_dma(self, mut channel: Channel<'d, C, crate::Blocking>) -> AesDma<'d, C> { + fn with_dma( + self, + mut channel: Channel<'d, C, crate::Blocking>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], + ) -> AesDma<'d, C> { channel.tx.init_channel(); // no need to call this for both, TX and RX - AesDma { aes: self, channel } + AesDma { + aes: self, + channel, + tx_chain: DescriptorChain::new(tx_descriptors), + rx_chain: DescriptorChain::new(rx_descriptors), + } } } @@ -321,6 +340,10 @@ pub mod dma { fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.tx_chain + } } impl<'d, C> DmaSupportRx for AesDma<'d, C> @@ -333,6 +356,10 @@ pub mod dma { fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.rx_chain + } } impl<'d, C> AesDma<'d, C> @@ -413,24 +440,18 @@ pub mod dma { self.channel.rx.is_done(); unsafe { + self.tx_chain + .fill_for_tx(false, write_buffer_ptr, write_buffer_len)?; self.channel .tx - .prepare_transfer_without_start( - self.dma_peripheral(), - false, - write_buffer_ptr, - write_buffer_len, - ) + .prepare_transfer_without_start(self.dma_peripheral(), &self.tx_chain) .and_then(|_| self.channel.tx.start_transfer())?; + self.rx_chain + .fill_for_rx(false, read_buffer_ptr, read_buffer_len)?; self.channel .rx - .prepare_transfer_without_start( - false, - self.dma_peripheral(), - read_buffer_ptr, - read_buffer_len, - ) + .prepare_transfer_without_start(self.dma_peripheral(), &self.rx_chain) .and_then(|_| self.channel.rx.start_transfer())?; } self.enable_dma(true); diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index cc9305fd3f6..0449f6c71dd 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -494,8 +494,6 @@ macro_rules! impl_channel { pub fn configure<'a>( self, burst_mode: bool, - tx_descriptors: &'a mut [DmaDescriptor], - rx_descriptors: &'a mut [DmaDescriptor], priority: DmaPriority, ) -> crate::dma::Channel<'a, Channel<$num>, crate::Blocking> { let mut tx_impl = ChannelTxImpl {}; @@ -504,12 +502,9 @@ macro_rules! impl_channel { let mut rx_impl = ChannelRxImpl {}; rx_impl.init(burst_mode, priority); - let tx_chain = DescriptorChain::new(tx_descriptors); - let rx_chain = DescriptorChain::new(rx_descriptors); - crate::dma::Channel { - tx: ChannelTx::new(tx_chain, tx_impl, burst_mode), - rx: ChannelRx::new(rx_chain, rx_impl, burst_mode), + tx: ChannelTx::new(tx_impl, burst_mode), + rx: ChannelRx::new(rx_impl, burst_mode), phantom: PhantomData, } } @@ -522,8 +517,6 @@ macro_rules! impl_channel { pub fn configure_for_async<'a>( self, burst_mode: bool, - tx_descriptors: &'a mut [DmaDescriptor], - rx_descriptors: &'a mut [DmaDescriptor], priority: DmaPriority, ) -> crate::dma::Channel<'a, Channel<$num>, $crate::Async> { let mut tx_impl = ChannelTxImpl {}; @@ -532,14 +525,11 @@ macro_rules! impl_channel { let mut rx_impl = ChannelRxImpl {}; rx_impl.init(burst_mode, priority); - let tx_chain = DescriptorChain::new(tx_descriptors); - let rx_chain = DescriptorChain::new(rx_descriptors); - as ChannelTypes>::Binder::set_isr($async_handler); crate::dma::Channel { - tx: ChannelTx::new(tx_chain, tx_impl, burst_mode), - rx: ChannelRx::new(rx_chain, rx_impl, burst_mode), + tx: ChannelTx::new(tx_impl, burst_mode), + rx: ChannelRx::new(rx_impl, burst_mode), phantom: PhantomData, } } diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 7b74305d6ed..88291fb9eae 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -31,17 +31,15 @@ //! let mosi = io.pins.gpio4; //! let cs = io.pins.gpio5; //! -//! let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = +//! let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = //! dma_buffers!(32000); //! //! let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) //! .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) //! .with_dma(dma_channel.configure( //! false, -//! &mut tx_descriptors, -//! &mut rx_descriptors, //! DmaPriority::Priority0, -//! )); +//! ), tx_descriptors, rx_descriptors); //! # } //! ``` //! @@ -143,21 +141,23 @@ const CHUNK_SIZE: usize = 4092; /// ## Usage /// ```rust,ignore /// // TX and RX buffers are 32000 bytes - passing only one parameter makes TX and RX the same size -/// let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(32000, 32000); +/// let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(32000, 32000); /// ``` #[macro_export] macro_rules! dma_buffers { ($tx_size:expr, $rx_size:expr) => {{ static mut TX_BUFFER: [u8; $tx_size] = [0u8; $tx_size]; static mut RX_BUFFER: [u8; $rx_size] = [0u8; $rx_size]; - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($tx_size + 4091) / 4092]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($rx_size + 4091) / 4092]; + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($tx_size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($tx_size + 4091) / 4092]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($rx_size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($rx_size + 4091) / 4092]; unsafe { ( &mut TX_BUFFER, - tx_descriptors, + &mut TX_DESCRIPTORS, &mut RX_BUFFER, - rx_descriptors, + &mut RX_DESCRIPTORS, ) } }}; @@ -165,14 +165,16 @@ macro_rules! dma_buffers { ($size:expr) => {{ static mut TX_BUFFER: [u8; $size] = [0u8; $size]; static mut RX_BUFFER: [u8; $size] = [0u8; $size]; - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; unsafe { ( &mut TX_BUFFER, - tx_descriptors, + &mut TX_DESCRIPTORS, &mut RX_BUFFER, - rx_descriptors, + &mut RX_DESCRIPTORS, ) } }}; @@ -183,7 +185,7 @@ macro_rules! dma_buffers { /// ## Usage /// ```rust,ignore /// // TX and RX buffers are 32000 bytes - passing only one parameter makes TX and RX the same size -/// let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = +/// let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = /// dma_circular_buffers!(32000, 32000); /// ``` #[macro_export] @@ -204,14 +206,16 @@ macro_rules! dma_circular_buffers { 3 }; - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; tx_descriptor_len]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; rx_descriptor_len]; + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; tx_descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; tx_descriptor_len]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; rx_descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; rx_descriptor_len]; unsafe { ( &mut TX_BUFFER, - tx_descriptors, + &mut TX_DESCRIPTORS, &mut RX_BUFFER, - rx_descriptors, + &mut RX_DESCRIPTORS, ) } }}; @@ -226,14 +230,16 @@ macro_rules! dma_circular_buffers { 3 }; - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; unsafe { ( &mut TX_BUFFER, - tx_descriptors, + &mut TX_DESCRIPTORS, &mut RX_BUFFER, - rx_descriptors, + &mut RX_DESCRIPTORS, ) } }}; @@ -244,20 +250,24 @@ macro_rules! dma_circular_buffers { /// ## Usage /// ```rust,ignore /// // Create TX and RX descriptors for transactions up to 32000 bytes - passing only one parameter assumes TX and RX are the same size -/// let (mut tx_descriptors, mut rx_descriptors) = dma_descriptors!(32000, 32000); +/// let (tx_descriptors, rx_descriptors) = dma_descriptors!(32000, 32000); /// ``` #[macro_export] macro_rules! dma_descriptors { ($tx_size:expr, $rx_size:expr) => {{ - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($tx_size + 4091) / 4092]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($rx_size + 4091) / 4092]; - (tx_descriptors, rx_descriptors) + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($tx_size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($tx_size + 4091) / 4092]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($rx_size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($rx_size + 4091) / 4092]; + unsafe { (&mut TX_DESCRIPTORS, &mut RX_DESCRIPTORS) } }}; ($size:expr) => {{ - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; - (tx_descriptors, rx_descriptors) + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; ($size + 4091) / 4092] = + [$crate::dma::DmaDescriptor::EMPTY; ($size + 4091) / 4092]; + unsafe { (&mut TX_DESCRIPTORS, &mut RX_DESCRIPTORS) } }}; } @@ -266,7 +276,7 @@ macro_rules! dma_descriptors { /// ## Usage /// ```rust,ignore /// // Create TX and RX descriptors for transactions up to 32000 bytes - passing only one parameter assumes TX and RX are the same size -/// let (mut tx_descriptors, mut rx_descriptors) = dma_circular_descriptors!(32000, 32000); +/// let (tx_descriptors, rx_descriptors) = dma_circular_descriptors!(32000, 32000); /// ``` #[macro_export] macro_rules! dma_circular_descriptors { @@ -283,9 +293,11 @@ macro_rules! dma_circular_descriptors { 3 }; - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; tx_descriptor_len]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; rx_descriptor_len]; - (tx_descriptors, rx_descriptors) + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; tx_descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; tx_descriptor_len]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; rx_descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; rx_descriptor_len]; + unsafe { (&mut TX_DESCRIPTORS, &mut RX_DESCRIPTORS) } }}; ($size:expr) => {{ @@ -295,9 +307,11 @@ macro_rules! dma_circular_descriptors { 3 }; - let tx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; - let rx_descriptors = [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; - (tx_descriptors, rx_descriptors) + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; descriptor_len] = + [$crate::dma::DmaDescriptor::EMPTY; descriptor_len]; + unsafe { (&mut TX_DESCRIPTORS, &mut RX_DESCRIPTORS) } }}; } @@ -444,12 +458,12 @@ pub trait Tx: TxPrivate {} pub trait PeripheralMarker {} #[doc(hidden)] -pub struct DescriptorChain<'a> { - pub(crate) descriptors: &'a mut [DmaDescriptor], +pub struct DescriptorChain { + pub(crate) descriptors: &'static mut [DmaDescriptor], } -impl<'a> DescriptorChain<'a> { - pub fn new(descriptors: &'a mut [DmaDescriptor]) -> Self { +impl DescriptorChain { + pub fn new(descriptors: &'static mut [DmaDescriptor]) -> Self { Self { descriptors } } @@ -621,33 +635,31 @@ impl<'a> DescriptorChain<'a> { pub(crate) struct TxCircularState { write_offset: usize, write_descr_ptr: *mut DmaDescriptor, - available: usize, + pub(crate) available: usize, last_seen_handled_descriptor_ptr: *mut DmaDescriptor, buffer_start: *const u8, buffer_len: usize, + + first_desc_ptr: *mut DmaDescriptor, } impl TxCircularState { - fn new( - write_descr_ptr: *mut DmaDescriptor, - last_seen_handled_descriptor_ptr: *mut DmaDescriptor, - buffer_start: *const u8, - buffer_len: usize, - ) -> Self { + pub(crate) fn new(chain: &mut DescriptorChain) -> Self { Self { write_offset: 0, - write_descr_ptr, + write_descr_ptr: chain.first_mut(), available: 0, - last_seen_handled_descriptor_ptr, - buffer_start, - buffer_len, + last_seen_handled_descriptor_ptr: chain.first_mut(), + buffer_start: chain.descriptors[0].buffer as _, + buffer_len: chain.descriptors.iter().map(|d| d.len()).sum(), + + first_desc_ptr: chain.first_mut(), } } - fn update(&mut self, channel: &T, chain: &mut DescriptorChain) + pub(crate) fn update(&mut self, channel: &T) where - T: TxChannel, - R: RegisterAccess, + T: TxPrivate, { if channel.descriptors_handled() { channel.reset_descriptors_handled(); @@ -664,7 +676,7 @@ impl TxCircularState { } } else { unsafe { - while !((*ptr).next.is_null() || (*ptr).next == chain.first_mut()) { + while !((*ptr).next.is_null() || (*ptr).next == self.first_desc_ptr) { let dw0 = ptr.read_volatile(); self.available += dw0.len(); ptr = ptr.offset(1); @@ -675,8 +687,8 @@ impl TxCircularState { self.available += dw0.len(); // in circular mode we need to honor the now available bytes at start - if (*ptr).next == chain.first_mut() { - ptr = chain.first_mut(); + if (*ptr).next == self.first_desc_ptr { + ptr = self.first_desc_ptr; while ptr < descr_address { let dw0 = ptr.read_volatile(); self.available += dw0.len(); @@ -695,7 +707,7 @@ impl TxCircularState { self.write_offset = (self.write_offset + segment_len) % self.buffer_len; self.write_descr_ptr = if next_descriptor.is_null() { - chain.first_mut() + self.first_desc_ptr } else { next_descriptor } @@ -706,7 +718,7 @@ impl TxCircularState { } } - fn push(&mut self, chain: &mut DescriptorChain, data: &[u8]) -> Result { + pub(crate) fn push(&mut self, data: &[u8]) -> Result { let avail = self.available; if avail < data.len() { @@ -716,7 +728,7 @@ impl TxCircularState { let mut remaining = data.len(); let mut offset = 0; while self.available >= remaining && remaining > 0 { - let written = self.push_with(chain, |buffer| { + let written = self.push_with(|buffer| { let len = usize::min(buffer.len(), data.len() - offset); buffer[..len].copy_from_slice(&data[offset..][..len]); len @@ -728,9 +740,8 @@ impl TxCircularState { Ok(data.len()) } - fn push_with( + pub(crate) fn push_with( &mut self, - chain: &mut DescriptorChain, f: impl FnOnce(&mut [u8]) -> usize, ) -> Result { let written = unsafe { @@ -746,7 +757,7 @@ impl TxCircularState { let dw0 = self.write_descr_ptr.read_volatile(); let segment_len = dw0.len(); self.write_descr_ptr = if dw0.next.is_null() { - chain.first_mut() + self.first_desc_ptr } else { dw0.next }; @@ -768,24 +779,26 @@ impl TxCircularState { pub(crate) struct RxCircularState { read_descr_ptr: *mut DmaDescriptor, - available: usize, + pub(crate) available: usize, last_seen_handled_descriptor_ptr: *mut DmaDescriptor, + last_descr_ptr: *mut DmaDescriptor, } impl RxCircularState { - fn new(read_descr_ptr: *mut DmaDescriptor) -> Self { + pub(crate) fn new(chain: &mut DescriptorChain) -> Self { Self { - read_descr_ptr, + read_descr_ptr: chain.first_mut(), available: 0, last_seen_handled_descriptor_ptr: core::ptr::null_mut(), + last_descr_ptr: chain.last_mut(), } } - fn update(&mut self, chain: &mut DescriptorChain) { + pub(crate) fn update(&mut self) { if self.last_seen_handled_descriptor_ptr.is_null() { // initially start at last descriptor (so that next will be the first // descriptor) - self.last_seen_handled_descriptor_ptr = chain.last_mut(); + self.last_seen_handled_descriptor_ptr = self.last_descr_ptr; } let mut current_in_descr_ptr = @@ -802,7 +815,7 @@ impl RxCircularState { } } - fn pop(&mut self, data: &mut [u8]) -> Result { + pub(crate) fn pop(&mut self, data: &mut [u8]) -> Result { let len = data.len(); let mut avail = self.available; @@ -847,42 +860,6 @@ impl RxCircularState { self.available = avail; Ok(len - remaining_buffer.len()) } - - fn drain_buffer( - &mut self, - chain: &DescriptorChain, - mut dst: &mut [u8], - ) -> Result { - let mut len = 0; - let mut idx = 0; - loop { - let descriptor = &chain.descriptors[idx]; - let chunk_len = dst.len().min(descriptor.len()); - if chunk_len == 0 { - break; - } - - let buffer_ptr = descriptor.buffer; - let next_dscr = descriptor.next; - - // Copy data to destination - let (dst_chunk, dst_remaining) = dst.split_at_mut(chunk_len); - dst = dst_remaining; - - dst_chunk - .copy_from_slice(unsafe { core::slice::from_raw_parts(buffer_ptr, chunk_len) }); - - len += chunk_len; - - if next_dscr.is_null() { - break; - } - - idx += 3; - } - - Ok(len) - } } /// The functions here are not meant to be used outside the HAL @@ -894,10 +871,8 @@ pub trait RxPrivate: crate::private::Sealed { unsafe fn prepare_transfer_without_start( &mut self, - circular: bool, peri: DmaPeripheral, - data: *mut u8, - len: usize, + chain: &DescriptorChain, ) -> Result<(), DmaError>; fn start_transfer(&mut self) -> Result<(), DmaError>; @@ -920,12 +895,6 @@ pub trait RxPrivate: crate::private::Sealed { fn unlisten_eof(&self); - fn available(&mut self) -> usize; - - fn pop(&mut self, data: &mut [u8]) -> Result; - - fn drain_buffer(&mut self, dst: &mut [u8]) -> Result; - /// Descriptor error detected fn has_error(&self) -> bool; @@ -1010,11 +979,9 @@ where T: RxChannel, R: RegisterAccess, { - pub(crate) chain: DescriptorChain<'a>, pub(crate) burst_mode: bool, pub(crate) rx_impl: T, - pub(crate) circular_state: Option, - pub(crate) _phantom: PhantomData, + pub(crate) _phantom: PhantomData<&'a R>, } impl<'a, T, R> ChannelRx<'a, T, R> @@ -1022,12 +989,10 @@ where T: RxChannel, R: RegisterAccess, { - fn new(chain: DescriptorChain<'a>, rx_impl: T, burst_mode: bool) -> Self { + fn new(rx_impl: T, burst_mode: bool) -> Self { Self { - chain, burst_mode, rx_impl, - circular_state: None, _phantom: PhantomData, } } @@ -1058,21 +1023,19 @@ where unsafe fn prepare_transfer_without_start( &mut self, - circular: bool, peri: DmaPeripheral, - data: *mut u8, - len: usize, + chain: &DescriptorChain, ) -> Result<(), DmaError> { - if self.burst_mode && (len % 4 != 0 || data as u32 % 4 != 0) { + if self.burst_mode + && chain + .descriptors + .iter() + .any(|d| d.len() % 4 != 0 || d.buffer as u32 % 4 != 0) + { return Err(DmaError::InvalidAlignment); } - self.chain.fill_for_rx(circular, data, len)?; - - self.circular_state = Some(RxCircularState::new(self.chain.first_mut())); - - self.rx_impl - .prepare_transfer_without_start(&self.chain, peri) + self.rx_impl.prepare_transfer_without_start(chain, peri) } fn start_transfer(&mut self) -> Result<(), DmaError> { @@ -1107,22 +1070,6 @@ where R::init_channel(); } - fn available(&mut self) -> usize { - let state = self.circular_state.as_mut().unwrap(); - state.update(&mut self.chain); - state.available - } - - fn pop(&mut self, data: &mut [u8]) -> Result { - let state = self.circular_state.as_mut().unwrap(); - state.pop(data) - } - - fn drain_buffer(&mut self, dst: &mut [u8]) -> Result { - let state = self.circular_state.as_mut().unwrap(); - state.drain_buffer(&self.chain, dst) - } - fn is_listening_eof(&self) -> bool { R::is_listening_in_eof() } @@ -1203,9 +1150,7 @@ pub trait TxPrivate: crate::private::Sealed { unsafe fn prepare_transfer_without_start( &mut self, peri: DmaPeripheral, - circular: bool, - data: *const u8, - len: usize, + chain: &DescriptorChain, ) -> Result<(), DmaError>; fn start_transfer(&mut self) -> Result<(), DmaError>; @@ -1234,18 +1179,18 @@ pub trait TxPrivate: crate::private::Sealed { fn unlisten_out_descriptor_error(&self); - fn available(&mut self) -> usize; - fn has_error(&self) -> bool; - fn push(&mut self, data: &[u8]) -> Result; - - fn push_with(&mut self, f: impl FnOnce(&mut [u8]) -> usize) -> Result; - fn clear_interrupts(&self); #[cfg(feature = "async")] fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker; + + fn descriptors_handled(&self) -> bool; + + fn reset_descriptors_handled(&self); + + fn last_out_dscr_address(&self) -> usize; } #[doc(hidden)] @@ -1330,12 +1275,10 @@ where T: TxChannel, R: RegisterAccess, { - pub(crate) chain: DescriptorChain<'a>, #[allow(unused)] pub(crate) burst_mode: bool, pub(crate) tx_impl: T, - pub(crate) circular_state: Option, - pub(crate) _phantom: PhantomData, + pub(crate) _phantom: PhantomData<(&'a (), R)>, } impl<'a, T, R> ChannelTx<'a, T, R> @@ -1343,12 +1286,10 @@ where T: TxChannel, R: RegisterAccess, { - fn new(chain: DescriptorChain<'a>, tx_impl: T, burst_mode: bool) -> Self { + fn new(tx_impl: T, burst_mode: bool) -> Self { Self { - chain, burst_mode, tx_impl, - circular_state: None, _phantom: PhantomData, } } @@ -1384,21 +1325,9 @@ where unsafe fn prepare_transfer_without_start( &mut self, peri: DmaPeripheral, - circular: bool, - data: *const u8, - len: usize, + chain: &DescriptorChain, ) -> Result<(), DmaError> { - self.chain.fill_for_tx(circular, data, len)?; - - self.circular_state = Some(TxCircularState::new( - self.chain.first_mut(), - self.chain.first_mut(), - data, - len, - )); - - self.tx_impl - .prepare_transfer_without_start(&self.chain, peri) + self.tx_impl.prepare_transfer_without_start(chain, peri) } fn start_transfer(&mut self) -> Result<(), DmaError> { @@ -1429,24 +1358,6 @@ where self.tx_impl.is_done() } - fn available(&mut self) -> usize { - let state = self.circular_state.as_mut().unwrap(); - state.update(&self.tx_impl, &mut self.chain); - state.available - } - - fn push(&mut self, data: &[u8]) -> Result { - let state = self.circular_state.as_mut().unwrap(); - state.update(&self.tx_impl, &mut self.chain); - state.push(&mut self.chain, data) - } - - fn push_with(&mut self, f: impl FnOnce(&mut [u8]) -> usize) -> Result { - let state = self.circular_state.as_mut().unwrap(); - state.update(&self.tx_impl, &mut self.chain); - state.push_with(&mut self.chain, f) - } - fn is_listening_eof(&self) -> bool { R::is_listening_out_eof() } @@ -1483,6 +1394,18 @@ where fn clear_interrupts(&self) { R::clear_out_interrupts(); } + + fn descriptors_handled(&self) -> bool { + self.tx_impl.descriptors_handled() + } + + fn reset_descriptors_handled(&self) { + self.tx_impl.reset_descriptors_handled() + } + + fn last_out_dscr_address(&self) -> usize { + self.tx_impl.last_out_dscr_address() + } } #[doc(hidden)] @@ -1655,12 +1578,16 @@ pub(crate) mod dma_private { type TX: Tx; fn tx(&mut self) -> &mut Self::TX; + + fn chain(&mut self) -> &mut DescriptorChain; } pub trait DmaSupportRx: DmaSupport { type RX: Rx; fn rx(&mut self) -> &mut Self::RX; + + fn chain(&mut self) -> &mut DescriptorChain; } } @@ -2024,6 +1951,7 @@ where I: dma_private::DmaSupportTx, { instance: &'a mut I, + state: TxCircularState, } impl<'a, I> DmaTransferTxCircular<'a, I> @@ -2032,17 +1960,20 @@ where { #[allow(unused)] // currently used by peripherals not available on all chips pub(crate) fn new(instance: &'a mut I) -> Self { - Self { instance } + let state = TxCircularState::new(instance.chain()); + Self { instance, state } } /// Amount of bytes which can be pushed. pub fn available(&mut self) -> usize { - self.instance.tx().available() + self.state.update(self.instance.tx()); + self.state.available } /// Push bytes into the DMA buffer. pub fn push(&mut self, data: &[u8]) -> Result { - self.instance.tx().push(data) + self.state.update(self.instance.tx()); + self.state.push(data) } /// Push bytes into the DMA buffer via the given closure. @@ -2050,7 +1981,8 @@ where /// The closure *might* get called with a slice which is smaller than the /// total available buffer. pub fn push_with(&mut self, f: impl FnOnce(&mut [u8]) -> usize) -> Result { - self.instance.tx().push_with(f) + self.state.update(self.instance.tx()); + self.state.push_with(f) } /// Stop the DMA transfer @@ -2083,6 +2015,7 @@ where I: dma_private::DmaSupportRx, { instance: &'a mut I, + state: RxCircularState, } impl<'a, I> DmaTransferRxCircular<'a, I> @@ -2091,7 +2024,8 @@ where { #[allow(unused)] // currently used by peripherals not available on all chips pub(crate) fn new(instance: &'a mut I) -> Self { - Self { instance } + let state = RxCircularState::new(instance.chain()); + Self { instance, state } } /// Amount of bytes which can be popped. @@ -2099,7 +2033,8 @@ where /// It's expected to call this before trying to [DmaTransferRxCircular::pop] /// data. pub fn available(&mut self) -> usize { - self.instance.rx().available() + self.state.update(); + self.state.available } /// Get available data. @@ -2111,7 +2046,8 @@ where /// Fails with [DmaError::BufferTooSmall] if the given buffer is too small /// to hold all available data pub fn pop(&mut self, data: &mut [u8]) -> Result { - self.instance.rx().pop(data) + self.state.update(); + self.state.pop(data) } } diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 14775f05921..46a9bf7f9ec 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -387,8 +387,6 @@ macro_rules! ImplSpiChannel { pub fn configure<'a>( self, burst_mode: bool, - tx_descriptors: &'a mut [DmaDescriptor], - rx_descriptors: &'a mut [DmaDescriptor], priority: DmaPriority, ) -> Channel<'a, [], $crate::Blocking> { let mut tx_impl = [] {}; @@ -397,12 +395,9 @@ macro_rules! ImplSpiChannel { let mut rx_impl = [] {}; rx_impl.init(burst_mode, priority); - let tx_chain = DescriptorChain::new(tx_descriptors); - let rx_chain = DescriptorChain::new(rx_descriptors); - Channel { - tx: ChannelTx::new(tx_chain, tx_impl, burst_mode), - rx: ChannelRx::new(rx_chain, rx_impl, burst_mode), + tx: ChannelTx::new(tx_impl, burst_mode), + rx: ChannelRx::new(rx_impl, burst_mode), phantom: PhantomData, } } @@ -415,8 +410,6 @@ macro_rules! ImplSpiChannel { pub fn configure_for_async<'a>( self, burst_mode: bool, - tx_descriptors: &'a mut [DmaDescriptor], - rx_descriptors: &'a mut [DmaDescriptor], priority: DmaPriority, ) -> Channel<'a, [], $crate::Async> { let mut tx_impl = [] {}; @@ -425,14 +418,11 @@ macro_rules! ImplSpiChannel { let mut rx_impl = [] {}; rx_impl.init(burst_mode, priority); - let tx_chain = DescriptorChain::new(tx_descriptors); - let rx_chain = DescriptorChain::new(rx_descriptors); - <[] as ChannelTypes>::Binder::set_isr(super::asynch::interrupt::[< interrupt_handler_spi $num _dma >]); Channel { - tx: ChannelTx::new(tx_chain, tx_impl, burst_mode), - rx: ChannelRx::new(rx_chain, rx_impl, burst_mode), + tx: ChannelTx::new(tx_impl, burst_mode), + rx: ChannelRx::new(rx_impl, burst_mode), phantom: PhantomData, } } @@ -787,8 +777,6 @@ macro_rules! ImplI2sChannel { pub fn configure<'a>( self, burst_mode: bool, - tx_descriptors: &'a mut [DmaDescriptor], - rx_descriptors: &'a mut [DmaDescriptor], priority: DmaPriority, ) -> Channel<'a, [], $crate::Blocking> { let mut tx_impl = [] {}; @@ -797,12 +785,9 @@ macro_rules! ImplI2sChannel { let mut rx_impl = [] {}; rx_impl.init(burst_mode, priority); - let tx_chain = DescriptorChain::new(tx_descriptors); - let rx_chain = DescriptorChain::new(rx_descriptors); - Channel { - tx: ChannelTx::new(tx_chain, tx_impl, burst_mode), - rx: ChannelRx::new(rx_chain, rx_impl, burst_mode), + tx: ChannelTx::new(tx_impl, burst_mode), + rx: ChannelRx::new(rx_impl, burst_mode), phantom: PhantomData, } } @@ -815,8 +800,6 @@ macro_rules! ImplI2sChannel { pub fn configure_for_async<'a>( self, burst_mode: bool, - tx_descriptors: &'a mut [DmaDescriptor], - rx_descriptors: &'a mut [DmaDescriptor], priority: DmaPriority, ) -> Channel<'a, [], $crate::Async> { let mut tx_impl = [] {}; @@ -825,14 +808,11 @@ macro_rules! ImplI2sChannel { let mut rx_impl = [] {}; rx_impl.init(burst_mode, priority); - let tx_chain = DescriptorChain::new(tx_descriptors); - let rx_chain = DescriptorChain::new(rx_descriptors); - <[] as ChannelTypes>::Binder::set_isr(super::asynch::interrupt::[< interrupt_handler_i2s $num >]); Channel { - tx: ChannelTx::new(tx_chain, tx_impl, burst_mode), - rx: ChannelRx::new(rx_chain, rx_impl, burst_mode), + tx: ChannelTx::new(tx_impl, burst_mode), + rx: ChannelRx::new(rx_impl, burst_mode), phantom: PhantomData, } } diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 7f782e6bb09..d60810860b0 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -38,7 +38,7 @@ //! let dma = Dma::new(peripherals.DMA); #![cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = dma.i2s0channel;")] #![cfg_attr(not(any(esp32, esp32s2)), doc = "let dma_channel = dma.channel0;")] -//! let (_, mut tx_descriptors, mut rx_buffer, mut rx_descriptors) = +//! let (_, tx_descriptors, mut rx_buffer, rx_descriptors) = //! dma_buffers!(0, 4 * 4092); //! //! let i2s = I2s::new( @@ -48,10 +48,10 @@ //! 44100.Hz(), //! dma_channel.configure( //! false, -//! &mut tx_descriptors, -//! &mut rx_descriptors, //! DmaPriority::Priority0, //! ), +//! tx_descriptors, +//! rx_descriptors, //! &clocks, //! ); #![cfg_attr(not(esp32), doc = "let i2s = i2s.with_mclk(io.pins.gpio0);")] @@ -88,6 +88,8 @@ use crate::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, Channel, ChannelTypes, + DescriptorChain, + DmaDescriptor, DmaError, DmaTransferRx, DmaTransferRxCircular, @@ -302,12 +304,15 @@ where CH: ChannelTypes, DmaMode: Mode, { + #[allow(clippy::too_many_arguments)] fn new_internal( _i2s: impl Peripheral

+ 'd, standard: Standard, data_format: DataFormat, sample_rate: impl Into, mut channel: Channel<'d, CH, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], clocks: &Clocks, ) -> Self { // on ESP32-C3 / ESP32-S3 and later RX and TX are independent and @@ -330,11 +335,13 @@ where i2s_tx: TxCreator { register_access: PhantomData, tx_channel: channel.tx, + descriptors: tx_descriptors, phantom: PhantomData, }, i2s_rx: RxCreator { register_access: PhantomData, rx_channel: channel.rx, + descriptors: rx_descriptors, phantom: PhantomData, }, phantom: PhantomData, @@ -385,12 +392,15 @@ where { /// Construct a new I2S peripheral driver instance for the first I2S /// peripheral + #[allow(clippy::too_many_arguments)] pub fn new( i2s: impl Peripheral

+ 'd, standard: Standard, data_format: DataFormat, sample_rate: impl Into, channel: Channel<'d, CH, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], clocks: &Clocks, ) -> Self where @@ -398,11 +408,21 @@ where CH::P: I2sPeripheral + I2s0Peripheral, DmaMode: Mode, { - Self::new_internal(i2s, standard, data_format, sample_rate, channel, clocks) + Self::new_internal( + i2s, + standard, + data_format, + sample_rate, + channel, + tx_descriptors, + rx_descriptors, + clocks, + ) } /// Construct a new I2S peripheral driver instance for the second I2S /// peripheral + #[allow(clippy::too_many_arguments)] #[cfg(any(esp32s3, esp32))] pub fn new_i2s1( i2s: impl Peripheral

+ 'd, @@ -410,13 +430,24 @@ where data_format: DataFormat, sample_rate: impl Into, channel: Channel<'d, CH, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], clocks: &Clocks, ) -> Self where I: I2s1Instance, CH::P: I2sPeripheral + I2s1Peripheral, { - Self::new_internal(i2s, standard, data_format, sample_rate, channel, clocks) + Self::new_internal( + i2s, + standard, + data_format, + sample_rate, + channel, + tx_descriptors, + rx_descriptors, + clocks, + ) } pub fn with_mclk(self, pin: impl Peripheral

+ 'd) -> Self { @@ -435,6 +466,7 @@ where { register_access: PhantomData, tx_channel: CH::Tx<'d>, + tx_chain: DescriptorChain, phantom: PhantomData, } @@ -475,6 +507,10 @@ where fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.tx_chain + } } impl<'d, T, CH, DmaMode> I2sTx<'d, T, CH, DmaMode> @@ -483,10 +519,11 @@ where CH: ChannelTypes, DmaMode: Mode, { - fn new(tx_channel: CH::Tx<'d>) -> Self { + fn new(tx_channel: CH::Tx<'d>, descriptors: &'static mut [DmaDescriptor]) -> Self { Self { register_access: PhantomData, tx_channel, + tx_chain: DescriptorChain::new(descriptors), phantom: PhantomData, } } @@ -501,8 +538,9 @@ where // configure DMA outlink unsafe { + self.tx_chain.fill_for_tx(false, ptr, data.len())?; self.tx_channel - .prepare_transfer_without_start(T::get_dma_peripheral(), false, ptr, data.len()) + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.tx_chain) .and_then(|_| self.tx_channel.start_transfer())?; } @@ -535,8 +573,9 @@ where // configure DMA outlink unsafe { + self.tx_chain.fill_for_tx(circular, ptr, len)?; self.tx_channel - .prepare_transfer_without_start(T::get_dma_peripheral(), circular, ptr, len) + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.tx_chain) .and_then(|_| self.tx_channel.start_transfer())?; } @@ -608,6 +647,7 @@ where { register_access: PhantomData, rx_channel: CH::Rx<'d>, + rx_chain: DescriptorChain, phantom: PhantomData, } @@ -648,6 +688,10 @@ where fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.rx_chain + } } impl<'d, T, CH, DmaMode> I2sRx<'d, T, CH, DmaMode> @@ -656,10 +700,11 @@ where CH: ChannelTypes, DmaMode: Mode, { - fn new(rx_channel: CH::Rx<'d>) -> Self { + fn new(rx_channel: CH::Rx<'d>, descriptors: &'static mut [DmaDescriptor]) -> Self { Self { register_access: PhantomData, rx_channel, + rx_chain: DescriptorChain::new(descriptors), phantom: PhantomData, } } @@ -674,8 +719,9 @@ where // configure DMA outlink unsafe { + self.rx_chain.fill_for_rx(false, ptr, data.len())?; self.rx_channel - .prepare_transfer_without_start(false, T::get_dma_peripheral(), ptr, data.len()) + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.rx_chain) .and_then(|_| self.rx_channel.start_transfer())?; } @@ -711,8 +757,9 @@ where // configure DMA outlink unsafe { + self.rx_chain.fill_for_rx(circular, ptr, len)?; self.rx_channel - .prepare_transfer_without_start(circular, T::get_dma_peripheral(), ptr, len) + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.rx_chain) .and_then(|_| self.rx_channel.start_transfer())?; } @@ -797,7 +844,7 @@ mod private { use crate::peripherals::{i2s1::RegisterBlock, I2S1}; use crate::{ clock::Clocks, - dma::{ChannelTypes, DmaPeripheral}, + dma::{ChannelTypes, DmaDescriptor, DmaPeripheral}, gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, interrupt::InterruptHandler, into_ref, @@ -815,6 +862,7 @@ mod private { { pub register_access: PhantomData, pub tx_channel: CH::Tx<'d>, + pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } @@ -825,7 +873,7 @@ mod private { DmaMode: Mode, { pub fn build(self) -> I2sTx<'d, T, CH, DmaMode> { - I2sTx::new(self.tx_channel) + I2sTx::new(self.tx_channel, self.descriptors) } pub fn with_bclk

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self @@ -867,6 +915,7 @@ mod private { { pub register_access: PhantomData, pub rx_channel: CH::Rx<'d>, + pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } @@ -877,7 +926,7 @@ mod private { DmaMode: Mode, { pub fn build(self) -> I2sRx<'d, T, CH, DmaMode> { - I2sRx::new(self.rx_channel) + I2sRx::new(self.rx_channel, self.descriptors) } pub fn with_bclk

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self @@ -2082,7 +2131,9 @@ pub mod asynch { dma::{ asynch::{DmaRxDoneChFuture, DmaRxFuture, DmaTxDoneChFuture, DmaTxFuture}, ChannelTypes, + RxCircularState, RxPrivate, + TxCircularState, TxPrivate, }, Async, @@ -2119,12 +2170,10 @@ pub mod asynch { let future = DmaTxFuture::new(&mut self.tx_channel); unsafe { - future.tx.prepare_transfer_without_start( - T::get_dma_peripheral(), - false, - ptr, - len, - )?; + self.tx_chain.fill_for_tx(false, ptr, len)?; + future + .tx + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.tx_chain)?; } future.tx.start_transfer()?; @@ -2150,8 +2199,9 @@ pub mod asynch { // configure DMA outlink unsafe { + self.tx_chain.fill_for_tx(true, ptr, len)?; self.tx_channel - .prepare_transfer_without_start(T::get_dma_peripheral(), true, ptr, len) + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.tx_chain) .and_then(|_| self.tx_channel.start_transfer())?; } @@ -2160,8 +2210,10 @@ pub mod asynch { // start: set I2S_TX_START T::tx_start(); + let state = TxCircularState::new(&mut self.tx_chain); Ok(I2sWriteDmaTransferAsync { i2s_tx: self, + state, _buffer: words, }) } @@ -2176,6 +2228,7 @@ pub mod asynch { CH: ChannelTypes, { i2s_tx: I2sTx<'d, T, CH, Async>, + state: TxCircularState, _buffer: BUFFER, } @@ -2188,7 +2241,8 @@ pub mod asynch { /// Will wait for more than 0 bytes available. pub async fn available(&mut self) -> Result { loop { - let res = self.i2s_tx.tx_channel.available(); + self.state.update(&mut self.i2s_tx.tx_channel); + let res = self.state.available; if res != 0 { break Ok(res); @@ -2202,7 +2256,7 @@ pub mod asynch { pub async fn push(&mut self, data: &[u8]) -> Result { let avail = self.available().await?; let to_send = usize::min(avail, data.len()); - Ok(self.i2s_tx.tx_channel.push(&data[..to_send])?) + Ok(self.state.push(&data[..to_send])?) } /// Push bytes into the DMA buffer via the given closure. @@ -2215,7 +2269,7 @@ pub mod asynch { f: impl FnOnce(&mut [u8]) -> usize, ) -> Result { let _avail = self.available().await; - Ok(self.i2s_tx.tx_channel.push_with(f)?) + Ok(self.state.push_with(f)?) } } @@ -2256,12 +2310,10 @@ pub mod asynch { // configure DMA outlink unsafe { - future.rx().prepare_transfer_without_start( - false, - T::get_dma_peripheral(), - ptr, - len, - )?; + self.rx_chain.fill_for_rx(false, ptr, len)?; + future + .rx() + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.rx_chain)?; } future.rx().start_transfer()?; @@ -2299,8 +2351,9 @@ pub mod asynch { // configure DMA outlink unsafe { + self.rx_chain.fill_for_rx(true, ptr, len)?; self.rx_channel - .prepare_transfer_without_start(true, T::get_dma_peripheral(), ptr, len) + .prepare_transfer_without_start(T::get_dma_peripheral(), &self.rx_chain) .and_then(|_| self.rx_channel.start_transfer())?; } @@ -2313,8 +2366,10 @@ pub mod asynch { #[cfg(esp32)] T::rx_start(len); + let state = RxCircularState::new(&mut self.rx_chain); Ok(I2sReadDmaTransferAsync { i2s_rx: self, + state, _buffer: words, }) } @@ -2329,6 +2384,7 @@ pub mod asynch { CH: ChannelTypes, { i2s_rx: I2sRx<'d, T, CH, Async>, + state: RxCircularState, _buffer: BUFFER, } @@ -2341,7 +2397,9 @@ pub mod asynch { /// Will wait for more than 0 bytes available. pub async fn available(&mut self) -> Result { loop { - let res = self.i2s_rx.rx_channel.available(); + self.state.update(); + + let res = self.state.available; if res != 0 { break Ok(res); @@ -2355,7 +2413,7 @@ pub mod asynch { pub async fn pop(&mut self, data: &mut [u8]) -> Result { let avail = self.available().await?; let to_rcv = usize::min(avail, data.len()); - Ok(self.i2s_rx.rx_channel.pop(&mut data[..to_rcv])?) + Ok(self.state.pop(&mut data[..to_rcv])?) } } } diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 6526ca12d67..0e559b50307 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -24,12 +24,10 @@ //! # let dma = Dma::new(peripherals.DMA); //! # let channel = dma.channel0; //! -//! # let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32678, 0); +//! # let (tx_buffer, tx_descriptors, _, rx_descriptors) = dma_buffers!(32678, 0); //! //! # let channel = channel.configure( //! # false, -//! # &mut tx_descriptors, -//! # &mut rx_descriptors, //! # DmaPriority::Priority0, //! # ); //! @@ -49,10 +47,17 @@ //! ); //! //! let lcd_cam = LcdCam::new(peripherals.LCD_CAM); -//! let mut camera = -//! Camera::new(lcd_cam.cam, channel.rx, data_pins, 20u32.MHz(), &clocks) -//! .with_master_clock(mclk_pin) // Remove this for slave mode. -//! .with_ctrl_pins(vsync_pin, href_pin, pclk_pin); +//! let mut camera = Camera::new( +//! lcd_cam.cam, +//! channel.rx, +//! rx_descriptors, +//! data_pins, +//! 20u32.MHz(), +//! &clocks +//! ) +//! // Remove this for slave mode. +//! .with_master_clock(mclk_pin) +//! .with_ctrl_pins(vsync_pin, href_pin, pclk_pin); //! # } //! ``` @@ -67,6 +72,8 @@ use crate::{ dma_private::{DmaSupport, DmaSupportRx}, ChannelRx, ChannelTypes, + DescriptorChain, + DmaDescriptor, DmaError, DmaPeripheral, DmaTransferRx, @@ -114,6 +121,7 @@ pub struct Cam<'d> { pub struct Camera<'d, RX> { lcd_cam: PeripheralRef<'d, LCD_CAM>, rx_channel: RX, + rx_chain: DescriptorChain, // 1 or 2 bus_width: usize, } @@ -127,6 +135,7 @@ where pub fn new( cam: Cam<'d>, mut channel: ChannelRx<'d, T, R>, + descriptors: &'static mut [DmaDescriptor], _pins: P, frequency: HertzU32, clocks: &Clocks, @@ -195,6 +204,7 @@ where Self { lcd_cam, rx_channel: channel, + rx_chain: DescriptorChain::new(descriptors), bus_width: P::BUS_WIDTH, } } @@ -223,6 +233,10 @@ impl<'d, RX: Rx> DmaSupportRx for Camera<'d, RX> { fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.rx_chain + } } impl<'d, RX: Rx> Camera<'d, RX> { @@ -330,12 +344,10 @@ impl<'d, RX: Rx> Camera<'d, RX> { assert_eq!(self.bus_width, size_of::()); unsafe { - self.rx_channel.prepare_transfer_without_start( - circular, - DmaPeripheral::LcdCam, - ptr as _, - len * size_of::(), - )?; + self.rx_chain + .fill_for_rx(circular, ptr as _, len * size_of::())?; + self.rx_channel + .prepare_transfer_without_start(DmaPeripheral::LcdCam, &self.rx_chain)?; } self.rx_channel.start_transfer() } diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 8150bb21723..c8b690e2ea4 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -22,12 +22,10 @@ //! # let dma = Dma::new(peripherals.DMA); //! # let channel = dma.channel0; //! -//! # let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32678, 0); +//! # let (tx_buffer, tx_descriptors, _, rx_descriptors) = dma_buffers!(32678, 0); //! //! # let channel = channel.configure( //! # false, -//! # &mut tx_descriptors, -//! # &mut rx_descriptors, //! # DmaPriority::Priority0, //! # ); //! @@ -46,6 +44,7 @@ //! let mut i8080 = I8080::new( //! lcd_cam.lcd, //! channel.tx, +//! tx_descriptors, //! tx_pins, //! 20.MHz(), //! Config::default(), @@ -68,6 +67,8 @@ use crate::{ dma_private::{DmaSupport, DmaSupportTx}, ChannelTx, ChannelTypes, + DescriptorChain, + DmaDescriptor, DmaError, DmaPeripheral, DmaTransferTx, @@ -92,6 +93,7 @@ use crate::{ pub struct I8080<'d, TX, P> { lcd_cam: PeripheralRef<'d, LCD_CAM>, tx_channel: TX, + tx_chain: DescriptorChain, _pins: P, } @@ -105,6 +107,7 @@ where pub fn new( lcd: Lcd<'d>, mut channel: ChannelTx<'d, T, R>, + descriptors: &'static mut [DmaDescriptor], mut pins: P, frequency: HertzU32, config: Config, @@ -248,6 +251,7 @@ where Self { lcd_cam, tx_channel: channel, + tx_chain: DescriptorChain::new(descriptors), _pins: pins, } } @@ -272,6 +276,10 @@ impl<'d, TX: Tx, P: TxPins> DmaSupportTx for I8080<'d, TX, P> { fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.tx_chain + } } impl<'d, TX: Tx, P: TxPins> I8080<'d, TX, P> @@ -462,12 +470,9 @@ impl<'d, TX: Tx, P> I8080<'d, TX, P> { }); unsafe { - self.tx_channel.prepare_transfer_without_start( - DmaPeripheral::LcdCam, - false, - ptr, - len, - )?; + self.tx_chain.fill_for_tx(false, ptr, len)?; + self.tx_channel + .prepare_transfer_without_start(DmaPeripheral::LcdCam, &self.tx_chain)?; } self.tx_channel.start_transfer()?; } diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 25a433c69de..9d9a0233844 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -25,8 +25,8 @@ //! # let dma = Dma::new(peripherals.DMA); //! # let dma_channel = dma.channel0; //! -//! let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = -//! dma_buffers!(32000, 0); let buffer = tx_buffer; +//! let (tx_buffer, tx_descriptors, _, _) = dma_buffers!(32000, 0); +//! let buffer = tx_buffer; //! //! // configure the data pins to use //! let tx_pins = TxFourBits::new(io.pins.gpio1, io.pins.gpio2, io.pins.gpio3, @@ -39,10 +39,9 @@ //! peripherals.PARL_IO, //! dma_channel.configure( //! false, -//! &mut tx_descriptors, -//! &mut rx_descriptors, //! DmaPriority::Priority0, //! ), +//! tx_descriptors, //! 1.MHz(), //! &clocks, //! ) @@ -85,17 +84,16 @@ //! let mut rx_pins = RxFourBits::new(io.pins.gpio1, io.pins.gpio2, //! io.pins.gpio3, io.pins.gpio4); //! -//! let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, -//! 32000); let mut buffer = rx_buffer; +//! let (_, _, rx_buffer, rx_descriptors) = dma_buffers!(0, 32000); +//! let mut buffer = rx_buffer; //! //! let parl_io = ParlIoRxOnly::new( //! peripherals.PARL_IO, //! dma_channel.configure( //! false, -//! &mut tx_descriptors, -//! &mut rx_descriptors, //! DmaPriority::Priority0, //! ), +//! rx_descriptors, //! 1.MHz(), //! &clocks, //! ) @@ -127,6 +125,8 @@ use crate::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, Channel, ChannelTypes, + DescriptorChain, + DmaDescriptor, DmaError, DmaPeripheral, DmaTransferRx, @@ -944,6 +944,7 @@ where Ok(ParlIoTx { tx_channel: self.tx_channel, + tx_chain: DescriptorChain::new(self.descriptors), phantom: PhantomData, }) } @@ -976,6 +977,7 @@ where Ok(ParlIoTx { tx_channel: self.tx_channel, + tx_chain: DescriptorChain::new(self.descriptors), phantom: PhantomData, }) } @@ -988,6 +990,7 @@ where DM: Mode, { tx_channel: CH::Tx<'d>, + tx_chain: DescriptorChain, phantom: PhantomData, } @@ -1026,6 +1029,7 @@ where Ok(ParlIoRx { rx_channel: self.rx_channel, + rx_chain: DescriptorChain::new(self.descriptors), phantom: PhantomData, }) } @@ -1056,6 +1060,7 @@ where Ok(ParlIoRx { rx_channel: self.rx_channel, + rx_chain: DescriptorChain::new(self.descriptors), phantom: PhantomData, }) } @@ -1068,6 +1073,7 @@ where DM: Mode, { rx_channel: CH::Rx<'d>, + rx_chain: DescriptorChain, phantom: PhantomData, } @@ -1195,6 +1201,8 @@ where pub fn new( _parl_io: impl Peripheral

+ 'd, mut dma_channel: Channel<'d, CH, DM>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, _clocks: &Clocks, ) -> Result { @@ -1203,10 +1211,12 @@ where Ok(Self { tx: TxCreatorFullDuplex { tx_channel: dma_channel.tx, + descriptors: tx_descriptors, phantom: PhantomData, }, rx: RxCreatorFullDuplex { rx_channel: dma_channel.rx, + descriptors: rx_descriptors, phantom: PhantomData, }, }) @@ -1268,6 +1278,7 @@ where pub fn new( _parl_io: impl Peripheral

+ 'd, mut dma_channel: Channel<'d, CH, DM>, + descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, _clocks: &Clocks, ) -> Result { @@ -1276,6 +1287,7 @@ where Ok(Self { tx: TxCreator { tx_channel: dma_channel.tx, + descriptors, phantom: PhantomData, }, }) @@ -1337,6 +1349,7 @@ where pub fn new( _parl_io: impl Peripheral

+ 'd, mut dma_channel: Channel<'d, CH, DM>, + descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, _clocks: &Clocks, ) -> Result { @@ -1345,6 +1358,7 @@ where Ok(Self { rx: RxCreator { rx_channel: dma_channel.rx, + descriptors, phantom: PhantomData, }, }) @@ -1475,8 +1489,9 @@ where self.tx_channel.is_done(); unsafe { + self.tx_chain.fill_for_tx(false, ptr, len)?; self.tx_channel - .prepare_transfer_without_start(DmaPeripheral::ParlIo, false, ptr, len) + .prepare_transfer_without_start(DmaPeripheral::ParlIo, &self.tx_chain) .and_then(|_| self.tx_channel.start_transfer())?; } @@ -1519,6 +1534,10 @@ where fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.tx_chain + } } impl<'d, CH, DM> ParlIoRx<'d, CH, DM> @@ -1548,13 +1567,14 @@ where return Err(Error::MaxDmaTransferSizeExceeded); } - Self::start_receive_bytes_dma(&mut self.rx_channel, ptr, len)?; + Self::start_receive_bytes_dma(&mut self.rx_channel, &mut self.rx_chain, ptr, len)?; Ok(DmaTransferRx::new(self)) } fn start_receive_bytes_dma( rx_channel: &mut CH::Rx<'d>, + rx_chain: &mut DescriptorChain, ptr: *mut u8, len: usize, ) -> Result<(), Error> { @@ -1568,8 +1588,9 @@ where Instance::set_rx_bytes(len as u16); unsafe { + rx_chain.fill_for_rx(false, ptr, len)?; rx_channel - .prepare_transfer_without_start(false, DmaPeripheral::ParlIo, ptr, len) + .prepare_transfer_without_start(DmaPeripheral::ParlIo, rx_chain) .and_then(|_| rx_channel.start_transfer())?; } @@ -1615,6 +1636,10 @@ where fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.rx_chain + } } /// Creates a TX channel @@ -1624,6 +1649,7 @@ where DM: Mode, { tx_channel: CH::Tx<'d>, + descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1634,6 +1660,7 @@ where DM: Mode, { rx_channel: CH::Rx<'d>, + descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1644,6 +1671,7 @@ where DM: Mode, { tx_channel: CH::Tx<'d>, + descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1654,6 +1682,7 @@ where DM: Mode, { rx_channel: CH::Rx<'d>, + descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1762,7 +1791,7 @@ pub mod asynch { } let future = DmaRxDoneChFuture::new(&mut self.rx_channel); - Self::start_receive_bytes_dma(future.rx, ptr, len)?; + Self::start_receive_bytes_dma(future.rx, &mut self.rx_chain, ptr, len)?; future.await?; Ok(()) diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 3e2b246123b..79c14d20e21 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -75,7 +75,7 @@ use super::{ }; use crate::{ clock::Clocks, - dma::{DmaPeripheral, Rx, Tx}, + dma::{DescriptorChain, DmaPeripheral, Rx, Tx}, gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, @@ -845,6 +845,8 @@ pub mod dma { dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, Channel, ChannelTypes, + DescriptorChain, + DmaDescriptor, DmaTransferRx, DmaTransferRxOwned, DmaTransferTx, @@ -868,6 +870,8 @@ pub mod dma { fn with_dma( self, channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI2, C, M, DmaMode>; } @@ -882,6 +886,8 @@ pub mod dma { fn with_dma( self, channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI3, C, M, DmaMode>; } @@ -895,12 +901,16 @@ pub mod dma { fn with_dma( self, mut channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI2, C, M, DmaMode> { channel.tx.init_channel(); // no need to call this for both, TX and RX SpiDma { spi: self.spi, channel, + tx_chain: DescriptorChain::new(tx_descriptors), + rx_chain: DescriptorChain::new(rx_descriptors), _mode: PhantomData, } } @@ -917,12 +927,16 @@ pub mod dma { fn with_dma( self, mut channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI3, C, M, DmaMode> { channel.tx.init_channel(); // no need to call this for both, TX and RX SpiDma { spi: self.spi, channel, + tx_chain: DescriptorChain::new(tx_descriptors), + rx_chain: DescriptorChain::new(rx_descriptors), _mode: PhantomData, } } @@ -938,6 +952,8 @@ pub mod dma { { pub(crate) spi: PeripheralRef<'d, T>, pub(crate) channel: Channel<'d, C, DmaMode>, + tx_chain: DescriptorChain, + rx_chain: DescriptorChain, _mode: PhantomData, } @@ -1037,6 +1053,10 @@ pub mod dma { fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.tx_chain + } } impl<'d, T, C, M, DmaMode> DmaSupportRx for SpiDma<'d, T, C, M, DmaMode> @@ -1052,6 +1072,10 @@ pub mod dma { fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.rx_chain + } } impl<'d, T, C, M, DmaMode> SpiDma<'d, T, C, M, DmaMode> @@ -1107,8 +1131,13 @@ pub mod dma { } unsafe { - self.spi - .start_write_bytes_dma(ptr, len, &mut self.channel.tx, false)?; + self.spi.start_write_bytes_dma( + &mut self.tx_chain, + ptr, + len, + &mut self.channel.tx, + false, + )?; } Ok(()) } @@ -1158,8 +1187,13 @@ pub mod dma { } unsafe { - self.spi - .start_read_bytes_dma(ptr, len, &mut self.channel.rx, false)?; + self.spi.start_read_bytes_dma( + &mut self.rx_chain, + ptr, + len, + &mut self.channel.rx, + false, + )?; } Ok(()) @@ -1218,6 +1252,8 @@ pub mod dma { unsafe { self.spi.start_transfer_dma( + &mut self.tx_chain, + &mut self.rx_chain, write_ptr, write_len, read_ptr, @@ -1308,8 +1344,13 @@ pub mod dma { } unsafe { - self.spi - .start_read_bytes_dma(ptr, len, &mut self.channel.rx, false)?; + self.spi.start_read_bytes_dma( + &mut self.rx_chain, + ptr, + len, + &mut self.channel.rx, + false, + )?; } Ok(DmaTransferRx::new(self)) } @@ -1383,8 +1424,13 @@ pub mod dma { } unsafe { - self.spi - .start_write_bytes_dma(ptr, len, &mut self.channel.tx, false)?; + self.spi.start_write_bytes_dma( + &mut self.tx_chain, + ptr, + len, + &mut self.channel.tx, + false, + )?; } Ok(DmaTransferTx::new(self)) } @@ -1403,8 +1449,13 @@ pub mod dma { type Error = super::Error; fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { - self.spi - .transfer_in_place_dma(words, &mut self.channel.tx, &mut self.channel.rx) + self.spi.transfer_in_place_dma( + &mut self.tx_chain, + &mut self.rx_chain, + words, + &mut self.channel.tx, + &mut self.channel.rx, + ) } } @@ -1421,7 +1472,8 @@ pub mod dma { type Error = super::Error; fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { - self.spi.write_bytes_dma(words, &mut self.channel.tx)?; + self.spi + .write_bytes_dma(&mut self.tx_chain, words, &mut self.channel.tx)?; self.spi.flush()?; Ok(()) } @@ -1496,6 +1548,7 @@ pub mod dma { let mut future = crate::dma::asynch::DmaRxFuture::new(&mut self.channel.rx); unsafe { self.spi.start_read_bytes_dma( + &mut self.rx_chain, words.as_mut_ptr(), words.len(), future.rx(), @@ -1512,6 +1565,7 @@ pub mod dma { let mut future = crate::dma::asynch::DmaTxFuture::new(&mut self.channel.tx); unsafe { self.spi.start_write_bytes_dma( + &mut self.tx_chain, chunk.as_ptr(), chunk.len(), future.tx(), @@ -1540,6 +1594,8 @@ pub mod dma { unsafe { self.spi.start_transfer_dma( + &mut self.tx_chain, + &mut self.rx_chain, write.as_ptr().offset(write_idx), write_len, read.as_mut_ptr().offset(read_idx), @@ -1573,6 +1629,8 @@ pub mod dma { unsafe { self.spi.start_transfer_dma( + &mut self.tx_chain, + &mut self.rx_chain, chunk.as_ptr(), chunk.len(), chunk.as_mut_ptr(), @@ -1670,19 +1728,32 @@ pub mod dma { M: IsFullDuplex, { fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { - self.spi - .transfer_dma(&[], words, &mut self.channel.tx, &mut self.channel.rx)?; + self.spi.transfer_dma( + &mut self.tx_chain, + &mut self.rx_chain, + &[], + words, + &mut self.channel.tx, + &mut self.channel.rx, + )?; self.flush() } fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { - self.spi.write_bytes_dma(words, &mut self.channel.tx)?; + self.spi + .write_bytes_dma(&mut self.tx_chain, words, &mut self.channel.tx)?; self.flush() } fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { - self.spi - .transfer_dma(write, read, &mut self.channel.tx, &mut self.channel.rx)?; + self.spi.transfer_dma( + &mut self.tx_chain, + &mut self.rx_chain, + write, + read, + &mut self.channel.tx, + &mut self.channel.rx, + )?; self.flush() } @@ -1694,6 +1765,8 @@ pub mod dma { /// [`read`](SpiBus::read). fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.spi.transfer_in_place_dma( + &mut self.tx_chain, + &mut self.rx_chain, words, &mut self.channel.tx, &mut self.channel.rx, @@ -1857,6 +1930,8 @@ where { fn transfer_in_place_dma<'w>( &mut self, + tx_chain: &mut DescriptorChain, + rx_chain: &mut DescriptorChain, words: &'w mut [u8], tx: &mut TX, rx: &mut RX, @@ -1864,6 +1939,8 @@ where for chunk in words.chunks_mut(MAX_DMA_SIZE) { unsafe { self.start_transfer_dma( + tx_chain, + rx_chain, chunk.as_ptr(), chunk.len(), chunk.as_mut_ptr(), @@ -1882,6 +1959,8 @@ where fn transfer_dma<'w>( &mut self, + tx_chain: &mut DescriptorChain, + rx_chain: &mut DescriptorChain, write_buffer: &'w [u8], read_buffer: &'w mut [u8], tx: &mut TX, @@ -1897,6 +1976,8 @@ where unsafe { self.start_transfer_dma( + tx_chain, + rx_chain, write_buffer.as_ptr().offset(write_idx), write_len, read_buffer.as_mut_ptr().offset(read_idx), @@ -1921,6 +2002,8 @@ where #[allow(clippy::too_many_arguments)] unsafe fn start_transfer_dma( &mut self, + tx_chain: &mut DescriptorChain, + rx_chain: &mut DescriptorChain, write_buffer_ptr: *const u8, write_buffer_len: usize, read_buffer_ptr: *mut u8, @@ -1938,20 +2021,12 @@ where self.update(); reset_dma_before_load_dma_dscr(reg_block); - tx.prepare_transfer_without_start( - self.dma_peripheral(), - false, - write_buffer_ptr, - write_buffer_len, - ) - .and_then(|_| tx.start_transfer())?; - rx.prepare_transfer_without_start( - false, - self.dma_peripheral(), - read_buffer_ptr, - read_buffer_len, - ) - .and_then(|_| rx.start_transfer())?; + tx_chain.fill_for_tx(false, write_buffer_ptr, write_buffer_len)?; + tx.prepare_transfer_without_start(self.dma_peripheral(), tx_chain) + .and_then(|_| tx.start_transfer())?; + rx_chain.fill_for_rx(false, read_buffer_ptr, read_buffer_len)?; + rx.prepare_transfer_without_start(self.dma_peripheral(), rx_chain) + .and_then(|_| rx.start_transfer())?; self.clear_dma_interrupts(); reset_dma_before_usr_cmd(reg_block); @@ -1961,10 +2036,15 @@ where Ok(()) } - fn write_bytes_dma<'w>(&mut self, words: &'w [u8], tx: &mut TX) -> Result<&'w [u8], Error> { + fn write_bytes_dma<'w>( + &mut self, + chain: &mut DescriptorChain, + words: &'w [u8], + tx: &mut TX, + ) -> Result<&'w [u8], Error> { for chunk in words.chunks(MAX_DMA_SIZE) { unsafe { - self.start_write_bytes_dma(chunk.as_ptr(), chunk.len(), tx, false)?; + self.start_write_bytes_dma(chain, chunk.as_ptr(), chunk.len(), tx, false)?; } while !tx.is_done() {} @@ -1977,6 +2057,7 @@ where #[cfg_attr(feature = "place-spi-driver-in-ram", ram)] unsafe fn start_write_bytes_dma( &mut self, + chain: &mut DescriptorChain, ptr: *const u8, len: usize, tx: &mut TX, @@ -1991,8 +2072,9 @@ where self.update(); reset_dma_before_load_dma_dscr(reg_block); + chain.fill_for_tx(false, ptr, len)?; unsafe { - tx.prepare_transfer_without_start(self.dma_peripheral(), false, ptr, len) + tx.prepare_transfer_without_start(self.dma_peripheral(), chain) .and_then(|_| tx.start_transfer())?; } @@ -2010,6 +2092,7 @@ where #[cfg_attr(feature = "place-spi-driver-in-ram", ram)] unsafe fn start_read_bytes_dma( &mut self, + chain: &mut DescriptorChain, ptr: *mut u8, len: usize, rx: &mut RX, @@ -2024,7 +2107,8 @@ where self.update(); reset_dma_before_load_dma_dscr(reg_block); - rx.prepare_transfer_without_start(false, self.dma_peripheral(), ptr, len) + chain.fill_for_rx(false, ptr, len)?; + rx.prepare_transfer_without_start(self.dma_peripheral(), chain) .and_then(|_| rx.start_transfer())?; self.clear_dma_interrupts(); diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index c24c772fd2a..d737abc8438 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -33,7 +33,7 @@ //! let mosi = io.pins.gpio2; //! let cs = io.pins.gpio3; //! -//! let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = +//! let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = //! dma_buffers!(32000); let mut spi = Spi::new( //! peripherals.SPI2, //! sclk, @@ -44,10 +44,8 @@ //! ) //! .with_dma(dma_channel.configure( //! false, -//! &mut tx_descriptors, -//! &mut rx_descriptors, //! DmaPriority::Priority0, -//! )); +//! ), tx_descriptors, rx_descriptors); //! //! let mut send = tx_buffer; //! let mut receive = rx_buffer; @@ -64,7 +62,7 @@ use core::marker::PhantomData; use super::{Error, FullDuplexMode, SpiMode}; use crate::{ - dma::{DmaPeripheral, Rx, Tx}, + dma::{DescriptorChain, DmaPeripheral, Rx, Tx}, gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, @@ -151,6 +149,8 @@ pub mod dma { dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, Channel, ChannelTypes, + DescriptorChain, + DmaDescriptor, DmaTransferRx, DmaTransferTx, DmaTransferTxRx, @@ -171,6 +171,8 @@ pub mod dma { fn with_dma( self, channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI2, C, DmaMode>; } @@ -184,6 +186,8 @@ pub mod dma { fn with_dma( self, channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI3, C, DmaMode>; } @@ -197,12 +201,16 @@ pub mod dma { fn with_dma( self, mut channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI2, C, DmaMode> { channel.tx.init_channel(); // no need to call this for both, TX and RX SpiDma { spi: self.spi, channel, + tx_chain: DescriptorChain::new(tx_descriptors), + rx_chain: DescriptorChain::new(rx_descriptors), } } } @@ -218,12 +226,16 @@ pub mod dma { fn with_dma( self, mut channel: Channel<'d, C, DmaMode>, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI3, C, DmaMode> { channel.tx.init_channel(); // no need to call this for both, TX and RX SpiDma { spi: self.spi, channel, + tx_chain: DescriptorChain::new(tx_descriptors), + rx_chain: DescriptorChain::new(rx_descriptors), } } } @@ -237,6 +249,8 @@ pub mod dma { { pub(crate) spi: PeripheralRef<'d, T>, pub(crate) channel: Channel<'d, C, DmaMode>, + tx_chain: DescriptorChain, + rx_chain: DescriptorChain, } impl<'d, T, C, DmaMode> core::fmt::Debug for SpiDma<'d, T, C, DmaMode> @@ -283,6 +297,10 @@ pub mod dma { fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.tx_chain + } } impl<'d, T, C, DmaMode> DmaSupportRx for SpiDma<'d, T, C, DmaMode> @@ -297,6 +315,10 @@ pub mod dma { fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx } + + fn chain(&mut self) -> &mut DescriptorChain { + &mut self.rx_chain + } } impl<'d, T, C, DmaMode> SpiDma<'d, T, C, DmaMode> @@ -327,7 +349,7 @@ pub mod dma { unsafe { self.spi - .start_write_bytes_dma(ptr, len, &mut self.channel.tx) + .start_write_bytes_dma(&mut self.tx_chain, ptr, len, &mut self.channel.tx) .map(move |_| DmaTransferTx::new(self)) } } @@ -353,7 +375,7 @@ pub mod dma { unsafe { self.spi - .start_read_bytes_dma(ptr, len, &mut self.channel.rx) + .start_read_bytes_dma(&mut self.rx_chain, ptr, len, &mut self.channel.rx) .map(move |_| DmaTransferRx::new(self)) } } @@ -384,6 +406,8 @@ pub mod dma { unsafe { self.spi .start_transfer_dma( + &mut self.tx_chain, + &mut self.rx_chain, write_ptr, write_len, read_ptr, @@ -403,8 +427,11 @@ where TX: Tx, RX: Rx, { + #[allow(clippy::too_many_arguments)] unsafe fn start_transfer_dma( &mut self, + tx_chain: &mut DescriptorChain, + rx_chain: &mut DescriptorChain, write_buffer_ptr: *const u8, write_buffer_len: usize, read_buffer_ptr: *mut u8, @@ -421,19 +448,11 @@ where reset_dma_before_load_dma_dscr(reg_block); - tx.prepare_transfer_without_start( - self.dma_peripheral(), - false, - write_buffer_ptr, - write_buffer_len, - )?; + tx_chain.fill_for_tx(false, write_buffer_ptr, write_buffer_len)?; + tx.prepare_transfer_without_start(self.dma_peripheral(), tx_chain)?; - rx.prepare_transfer_without_start( - false, - self.dma_peripheral(), - read_buffer_ptr, - read_buffer_len, - )?; + rx_chain.fill_for_rx(false, read_buffer_ptr, read_buffer_len)?; + rx.prepare_transfer_without_start(self.dma_peripheral(), rx_chain)?; reset_dma_before_usr_cmd(reg_block); @@ -453,6 +472,7 @@ where unsafe fn start_write_bytes_dma( &mut self, + tx_chain: &mut DescriptorChain, ptr: *const u8, len: usize, tx: &mut TX, @@ -465,7 +485,8 @@ where reset_dma_before_load_dma_dscr(reg_block); - tx.prepare_transfer_without_start(self.dma_peripheral(), false, ptr, len)?; + tx_chain.fill_for_tx(false, ptr, len)?; + tx.prepare_transfer_without_start(self.dma_peripheral(), tx_chain)?; reset_dma_before_usr_cmd(reg_block); @@ -484,6 +505,7 @@ where unsafe fn start_read_bytes_dma( &mut self, + rx_chain: &mut DescriptorChain, ptr: *mut u8, len: usize, rx: &mut RX, @@ -495,7 +517,8 @@ where self.enable_dma(); reset_dma_before_load_dma_dscr(reg_block); - rx.prepare_transfer_without_start(false, self.dma_peripheral(), ptr, len)?; + rx_chain.fill_for_rx(false, ptr, len)?; + rx.prepare_transfer_without_start(self.dma_peripheral(), rx_chain)?; reset_dma_before_usr_cmd(reg_block); diff --git a/examples/src/bin/embassy_i2s_read.rs b/examples/src/bin/embassy_i2s_read.rs index 5bcf799eafe..4bd9587e079 100644 --- a/examples/src/bin/embassy_i2s_read.rs +++ b/examples/src/bin/embassy_i2s_read.rs @@ -50,19 +50,16 @@ async fn main(_spawner: Spawner) { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, 4092 * 4); + let (_, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(0, 4092 * 4); let i2s = I2s::new( peripherals.I2S0, Standard::Philips, DataFormat::Data16Channel16, 44100u32.Hz(), - dma_channel.configure_for_async( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure_for_async(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, &clocks, ); diff --git a/examples/src/bin/embassy_i2s_sound.rs b/examples/src/bin/embassy_i2s_sound.rs index 7d1cf0b0a1f..ffb60bad792 100644 --- a/examples/src/bin/embassy_i2s_sound.rs +++ b/examples/src/bin/embassy_i2s_sound.rs @@ -73,19 +73,16 @@ async fn main(_spawner: Spawner) { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32000, 0); + let (tx_buffer, tx_descriptors, _, rx_descriptors) = dma_buffers!(32000, 0); let i2s = I2s::new( peripherals.I2S0, Standard::Philips, DataFormat::Data16Channel16, 44100u32.Hz(), - dma_channel.configure_for_async( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure_for_async(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, &clocks, ); diff --git a/examples/src/bin/embassy_parl_io_rx.rs b/examples/src/bin/embassy_parl_io_rx.rs index f51a7c9a624..b1f178f9c31 100644 --- a/examples/src/bin/embassy_parl_io_rx.rs +++ b/examples/src/bin/embassy_parl_io_rx.rs @@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, 32000); + let (_, _, rx_buffer, rx_descriptors) = dma_buffers!(0, 32000); let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; @@ -46,12 +46,8 @@ async fn main(_spawner: Spawner) { let parl_io = ParlIoRxOnly::new( peripherals.PARL_IO, - dma_channel.configure_for_async( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure_for_async(false, DmaPriority::Priority0), + rx_descriptors, 1.MHz(), &clocks, ) diff --git a/examples/src/bin/embassy_parl_io_tx.rs b/examples/src/bin/embassy_parl_io_tx.rs index 941cc7f3762..a3973232296 100644 --- a/examples/src/bin/embassy_parl_io_tx.rs +++ b/examples/src/bin/embassy_parl_io_tx.rs @@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32000, 0); + let (tx_buffer, mut tx_descriptors, _, _) = dma_buffers!(32000, 0); let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; @@ -59,12 +59,8 @@ async fn main(_spawner: Spawner) { let parl_io = ParlIoTxOnly::new( peripherals.PARL_IO, - dma_channel.configure_for_async( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure_for_async(false, DmaPriority::Priority0), + tx_descriptors, 1.MHz(), &clocks, ) diff --git a/examples/src/bin/embassy_spi.rs b/examples/src/bin/embassy_spi.rs index 794b5000898..6e65ba9044f 100644 --- a/examples/src/bin/embassy_spi.rs +++ b/examples/src/bin/embassy_spi.rs @@ -61,16 +61,15 @@ async fn main(_spawner: Spawner) { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (mut descriptors, mut rx_descriptors) = dma_descriptors!(32000); + let (descriptors, rx_descriptors) = dma_descriptors!(32000); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure_for_async( - false, - &mut descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure_for_async(false, DmaPriority::Priority0), + descriptors, + rx_descriptors, + ); let send_buffer = [0, 1, 2, 3, 4, 5, 6, 7]; loop { diff --git a/examples/src/bin/i2s_read.rs b/examples/src/bin/i2s_read.rs index 746aec745c9..b87c3ccb138 100644 --- a/examples/src/bin/i2s_read.rs +++ b/examples/src/bin/i2s_read.rs @@ -43,7 +43,7 @@ fn main() -> ! { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (_, mut tx_descriptors, mut rx_buffer, mut rx_descriptors) = dma_buffers!(0, 4 * 4092); + let (_, tx_descriptors, mut rx_buffer, rx_descriptors) = dma_buffers!(0, 4 * 4092); // Here we test that the type is // 1) reasonably simple (or at least this will flag changes that may make it @@ -54,12 +54,9 @@ fn main() -> ! { Standard::Philips, DataFormat::Data16Channel16, 44100.Hz(), - dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, &clocks, ); diff --git a/examples/src/bin/i2s_sound.rs b/examples/src/bin/i2s_sound.rs index f4f87c884e6..e7805fd5237 100644 --- a/examples/src/bin/i2s_sound.rs +++ b/examples/src/bin/i2s_sound.rs @@ -65,19 +65,16 @@ fn main() -> ! { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32000, 0); + let (tx_buffer, tx_descriptors, _, rx_descriptors) = dma_buffers!(32000, 0); let i2s = I2s::new( peripherals.I2S0, Standard::Philips, DataFormat::Data16Channel16, 44100.Hz(), - dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, &clocks, ); diff --git a/examples/src/bin/lcd_cam_ov2640.rs b/examples/src/bin/lcd_cam_ov2640.rs index b1c9860936e..147b1bb8ae9 100644 --- a/examples/src/bin/lcd_cam_ov2640.rs +++ b/examples/src/bin/lcd_cam_ov2640.rs @@ -54,14 +54,9 @@ fn main() -> ! { let dma = Dma::new(peripherals.DMA); let channel = dma.channel0; - let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, 32678); + let (_, _, rx_buffer, rx_descriptors) = dma_buffers!(0, 32678); - let channel = channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ); + let channel = channel.configure(false, DmaPriority::Priority0); let cam_siod = io.pins.gpio4; let cam_sioc = io.pins.gpio5; @@ -81,9 +76,16 @@ fn main() -> ! { ); let lcd_cam = LcdCam::new(peripherals.LCD_CAM); - let mut camera = Camera::new(lcd_cam.cam, channel.rx, cam_data_pins, 20u32.MHz(), &clocks) - .with_master_clock(cam_xclk) - .with_ctrl_pins(cam_vsync, cam_href, cam_pclk); + let mut camera = Camera::new( + lcd_cam.cam, + channel.rx, + rx_descriptors, + cam_data_pins, + 20u32.MHz(), + &clocks, + ) + .with_master_clock(cam_xclk) + .with_ctrl_pins(cam_vsync, cam_href, cam_pclk); let delay = Delay::new(&clocks); diff --git a/examples/src/bin/lcd_i8080.rs b/examples/src/bin/lcd_i8080.rs index b654094552b..b3af04980f8 100644 --- a/examples/src/bin/lcd_i8080.rs +++ b/examples/src/bin/lcd_i8080.rs @@ -56,14 +56,9 @@ fn main() -> ! { let dma = Dma::new(peripherals.DMA); let channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32678, 0); + let (tx_buffer, tx_descriptors, _, _) = dma_buffers!(32678, 0); - let channel = channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ); + let channel = channel.configure(false, DmaPriority::Priority0); let delay = Delay::new(&clocks); @@ -85,6 +80,7 @@ fn main() -> ! { let mut i8080 = I8080::new( lcd_cam.lcd, channel.tx, + tx_descriptors, tx_pins, 20.MHz(), Config::default(), diff --git a/examples/src/bin/parl_io_rx.rs b/examples/src/bin/parl_io_rx.rs index 08ae9858306..60090088578 100644 --- a/examples/src/bin/parl_io_rx.rs +++ b/examples/src/bin/parl_io_rx.rs @@ -30,7 +30,7 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(0, 32000); + let (_, _, rx_buffer, rx_descriptors) = dma_buffers!(0, 32000); let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; @@ -39,12 +39,8 @@ fn main() -> ! { let parl_io = ParlIoRxOnly::new( peripherals.PARL_IO, - dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure(false, DmaPriority::Priority0), + rx_descriptors, 1.MHz(), &clocks, ) diff --git a/examples/src/bin/parl_io_tx.rs b/examples/src/bin/parl_io_tx.rs index f75791c5ee6..df61841a170 100644 --- a/examples/src/bin/parl_io_tx.rs +++ b/examples/src/bin/parl_io_tx.rs @@ -41,7 +41,7 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(32000, 0); + let (tx_buffer, tx_descriptors, _, _) = dma_buffers!(32000, 0); let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; @@ -52,12 +52,8 @@ fn main() -> ! { let parl_io = ParlIoTxOnly::new( peripherals.PARL_IO, - dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, 1.MHz(), &clocks, ) diff --git a/examples/src/bin/qspi_flash.rs b/examples/src/bin/qspi_flash.rs index e4c96e6f77e..c44229c32bd 100644 --- a/examples/src/bin/qspi_flash.rs +++ b/examples/src/bin/qspi_flash.rs @@ -76,7 +76,7 @@ fn main() -> ! { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(256, 320); + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(256, 320); let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins( @@ -87,12 +87,11 @@ fn main() -> ! { Some(sio3), Some(cs), ) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let delay = Delay::new(&clocks); diff --git a/examples/src/bin/spi_loopback_dma.rs b/examples/src/bin/spi_loopback_dma.rs index 1698db8026a..8385a53bb44 100644 --- a/examples/src/bin/spi_loopback_dma.rs +++ b/examples/src/bin/spi_loopback_dma.rs @@ -54,16 +54,15 @@ fn main() -> ! { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(32000); + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(32000); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let delay = Delay::new(&clocks); diff --git a/examples/src/bin/spi_slave_dma.rs b/examples/src/bin/spi_slave_dma.rs index 7d95f9702f5..54a9d69f197 100644 --- a/examples/src/bin/spi_slave_dma.rs +++ b/examples/src/bin/spi_slave_dma.rs @@ -74,7 +74,7 @@ fn main() -> ! { } } - let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(32000); + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(32000); let mut spi = Spi::new( peripherals.SPI2, @@ -84,12 +84,11 @@ fn main() -> ! { slave_cs, SpiMode::Mode0, ) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let delay = Delay::new(&clocks); diff --git a/hil-test/tests/aes_dma.rs b/hil-test/tests/aes_dma.rs index 97b84bc2f79..54c4d2d5d64 100644 --- a/hil-test/tests/aes_dma.rs +++ b/hil-test/tests/aes_dma.rs @@ -38,15 +38,13 @@ mod tests { let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; - let (input, mut tx_descriptors, mut output, mut rx_descriptors) = - dma_buffers!(DMA_BUFFER_SIZE); + let (input, tx_descriptors, mut output, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let mut aes = Aes::new(peripherals.AES).with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + let mut aes = Aes::new(peripherals.AES).with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let keytext = "SUp4SeCp@sSw0rd".as_bytes(); let mut keybuf = [0_u8; 16]; @@ -84,15 +82,13 @@ mod tests { let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; - let (input, mut tx_descriptors, mut output, mut rx_descriptors) = - dma_buffers!(DMA_BUFFER_SIZE); + let (input, tx_descriptors, mut output, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let mut aes = Aes::new(peripherals.AES).with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + let mut aes = Aes::new(peripherals.AES).with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let keytext = "SUp4SeCp@sSw0rd".as_bytes(); let mut keybuf = [0_u8; 16]; @@ -129,15 +125,13 @@ mod tests { let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; - let (input, mut tx_descriptors, mut output, mut rx_descriptors) = - dma_buffers!(DMA_BUFFER_SIZE); + let (input, tx_descriptors, mut output, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let mut aes = Aes::new(peripherals.AES).with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + let mut aes = Aes::new(peripherals.AES).with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let keytext = "SUp4SeCp@sSw0rd".as_bytes(); let mut keybuf = [0_u8; 16]; @@ -175,15 +169,13 @@ mod tests { let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; - let (input, mut tx_descriptors, mut output, mut rx_descriptors) = - dma_buffers!(DMA_BUFFER_SIZE); + let (input, tx_descriptors, mut output, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let mut aes = Aes::new(peripherals.AES).with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + let mut aes = Aes::new(peripherals.AES).with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let keytext = "SUp4SeCp@sSw0rd".as_bytes(); let mut keybuf = [0_u8; 16]; diff --git a/hil-test/tests/i2s.rs b/hil-test/tests/i2s.rs index c545045fbc9..c9fe3228dbe 100644 --- a/hil-test/tests/i2s.rs +++ b/hil-test/tests/i2s.rs @@ -53,20 +53,16 @@ mod tests { let dma = Dma::new(peripherals.DMA); let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, mut rx_buffer, mut rx_descriptors) = - dma_buffers!(16000, 16000); + let (tx_buffer, tx_descriptors, mut rx_buffer, rx_descriptors) = dma_buffers!(16000, 16000); let i2s = I2s::new( peripherals.I2S0, Standard::Philips, DataFormat::Data16Channel16, 16000.Hz(), - dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - ), + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, &clocks, ); diff --git a/hil-test/tests/spi_full_duplex_dma.rs b/hil-test/tests/spi_full_duplex_dma.rs index 8542a9d199e..47ccef4918b 100644 --- a/hil-test/tests/spi_full_duplex_dma.rs +++ b/hil-test/tests/spi_full_duplex_dma.rs @@ -58,17 +58,15 @@ mod tests { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = - dma_buffers!(DMA_BUFFER_SIZE); + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); // DMA buffer require a static life-time let mut send = tx_buffer; @@ -101,16 +99,15 @@ mod tests { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(4, 2); + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4, 2); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); // DMA buffer require a static life-time let mut send = tx_buffer; @@ -145,17 +142,15 @@ mod tests { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = - dma_buffers!(DMA_BUFFER_SIZE); + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); // DMA buffer require a static life-time let mut send = tx_buffer; @@ -193,7 +188,7 @@ mod tests { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (_, mut tx_descriptors, rx_buffer, mut rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); + let (_, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let tx_buffer = { // using `static`, not `static mut`, places the array in .rodata @@ -203,12 +198,11 @@ mod tests { let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let mut receive = rx_buffer; @@ -242,7 +236,7 @@ mod tests { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, _, mut rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); + let (tx_buffer, tx_descriptors, _, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let rx_buffer = { // using `static`, not `static mut`, places the array in .rodata @@ -252,12 +246,11 @@ mod tests { let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); let mut receive = rx_buffer; assert!(matches!( @@ -290,17 +283,15 @@ mod tests { #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] let dma_channel = dma.channel0; - let (tx_buffer, mut tx_descriptors, rx_buffer, mut rx_descriptors) = - dma_buffers!(DMA_BUFFER_SIZE); + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) - .with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); + .with_dma( + dma_channel.configure(false, DmaPriority::Priority0), + tx_descriptors, + rx_descriptors, + ); // DMA buffer require a static life-time let send = tx_buffer;