diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 91cec235a97..e471e1b1884 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -670,6 +670,24 @@ mod m2m { } } + /// Create a new Mem2Mem instance with specific chunk size. + pub fn new_with_chunk_size( + mut channel: Channel<'d, C, MODE>, + peripheral: impl DmaEligible, + tx_descriptors: &'static mut [DmaDescriptor], + rx_descriptors: &'static mut [DmaDescriptor], + chunk_size: usize, + ) -> Self { + channel.tx.init_channel(); + channel.rx.init_channel(); + Mem2Mem { + channel, + peripheral: peripheral.dma_peripheral(), + tx_chain: DescriptorChain::new_with_chunk_size(tx_descriptors, chunk_size), + rx_chain: DescriptorChain::new_with_chunk_size(rx_descriptors, chunk_size), + } + } + /// Create a new Mem2Mem instance. /// /// # Safety diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 749d8db0278..0008ba49fa4 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -43,8 +43,8 @@ //! # } //! ``` //! -//! ⚠️ Note: Descriptors should be sized as `(CHUNK_SIZE + 4091) / 4092`. -//! I.e., to transfer buffers of size `1..=4092`, you need 1 descriptor. +//! ⚠️ Note: Descriptors should be sized as `(max_transfer_size + CHUNK_SIZE - 1) / CHUNK_SIZE`. +//! I.e., to transfer buffers of size `1..=CHUNK_SIZE`, you need 1 descriptor. //! //! For convenience you can use the [crate::dma_buffers] macro. #![warn(missing_docs)] @@ -145,7 +145,8 @@ pub enum DmaInterrupt { RxDone, } -const CHUNK_SIZE: usize = 4092; +/// The default CHUNK_SIZE used for DMA transfers +pub const CHUNK_SIZE: usize = 4092; /// Convenience macro to create DMA buffers and descriptors /// @@ -156,39 +157,12 @@ const CHUNK_SIZE: usize = 4092; /// ``` #[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]; - 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, - &mut TX_DESCRIPTORS, - &mut RX_BUFFER, - &mut RX_DESCRIPTORS, - ) - } - }}; - - ($size:expr) => {{ - static mut TX_BUFFER: [u8; $size] = [0u8; $size]; - static mut RX_BUFFER: [u8; $size] = [0u8; $size]; - 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, - &mut TX_DESCRIPTORS, - &mut RX_BUFFER, - &mut RX_DESCRIPTORS, - ) - } - }}; + ($tx_size:expr, $rx_size:expr) => { + $crate::dma_buffers_chunk_size!($tx_size, $rx_size, $crate::dma::CHUNK_SIZE) + }; + ($size:expr) => { + $crate::dma_buffers_chunk_size!($size, $crate::dma::CHUNK_SIZE) + }; } /// Convenience macro to create circular DMA buffers and descriptors @@ -201,105 +175,163 @@ macro_rules! dma_buffers { /// ``` #[macro_export] macro_rules! dma_circular_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]; + ($tx_size:expr, $rx_size:expr) => { + $crate::dma_circular_buffers_chunk_size!($tx_size, $rx_size, $crate::dma::CHUNK_SIZE) + }; - const tx_descriptor_len: usize = if $tx_size > 4092 * 2 { - ($tx_size + 4091) / 4092 - } else { - 3 - }; + ($size:expr) => { + $crate::dma_circular_buffers_chunk_size!($size, $size, $crate::dma::CHUNK_SIZE) + }; +} - const rx_descriptor_len: usize = if $rx_size > 4092 * 2 { - ($rx_size + 4091) / 4092 - } else { - 3 - }; +/// Convenience macro to create 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 (tx_descriptors, rx_descriptors) = dma_descriptors!(32000, 32000); +/// ``` +#[macro_export] +macro_rules! dma_descriptors { + ($tx_size:expr, $rx_size:expr) => { + $crate::dma_descriptors_chunk_size!($tx_size, $rx_size, CHUNK_SIZE) + }; - 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]; + ($size:expr) => { + $crate::dma_descriptors_chunk_size!($size, $size, CHUNK_SIZE) + }; +} + +/// Convenience macro to create circular 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 (tx_descriptors, rx_descriptors) = dma_circular_descriptors!(32000, 32000); +/// ``` +#[macro_export] +macro_rules! dma_circular_descriptors { + ($tx_size:expr, $rx_size:expr) => { + $crate::dma_circular_descriptors_chunk_size!($tx_size, $rx_size, $crate::dma::CHUNK_SIZE) + }; + + ($size:expr) => { + $crate::dma_circular_descriptors_chunk_size!($size, $size, $crate::dma::CHUNK_SIZE) + }; +} + +/// Convenience macro to create DMA buffers and descriptors with specific chunk +/// size +/// +/// ## Usage +/// ```rust,ignore +/// // TX and RX buffers are 32000 bytes - passing only one parameter makes TX and RX the same size +/// let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(32000, 32000, 4032); +/// ``` +#[macro_export] +macro_rules! dma_buffers_chunk_size { + ($tx_size:expr, $rx_size:expr, $chunk_size:expr) => {{ + static mut TX_BUFFER: [u8; $tx_size] = [0u8; $tx_size]; + static mut RX_BUFFER: [u8; $rx_size] = [0u8; $rx_size]; + let (mut tx_descriptors, mut rx_descriptors) = + $crate::dma_descriptors_chunk_size!($tx_size, $rx_size, $chunk_size); unsafe { ( &mut TX_BUFFER, - &mut TX_DESCRIPTORS, + tx_descriptors, &mut RX_BUFFER, - &mut RX_DESCRIPTORS, + rx_descriptors, ) } }}; - ($size:expr) => {{ - static mut TX_BUFFER: [u8; $size] = [0u8; $size]; - static mut RX_BUFFER: [u8; $size] = [0u8; $size]; - - const descriptor_len: usize = if $size > 4092 * 2 { - ($size + 4091) / 4092 - } else { - 3 - }; + ($size:expr, $chunk_size:expr) => { + $crate::dma_buffers_chunk_size!($size, $size, $chunk_size) + }; +} - 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]; +/// Convenience macro to create circular DMA buffers and descriptors with +/// specific chunk size +/// +/// ## Usage +/// ```rust,ignore +/// // TX and RX buffers are 32000 bytes - passing only one parameter makes TX and RX the same size +/// let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = +/// dma_circular_buffers!(32000, 32000, 4032); +/// ``` +#[macro_export] +macro_rules! dma_circular_buffers_chunk_size { + ($tx_size:expr, $rx_size:expr, $chunk_size:expr) => {{ + static mut TX_BUFFER: [u8; $tx_size] = [0u8; $tx_size]; + static mut RX_BUFFER: [u8; $rx_size] = [0u8; $rx_size]; + let (mut tx_descriptors, mut rx_descriptors) = + $crate::dma_circular_descriptors_chunk_size!($tx_size, $rx_size, $chunk_size); unsafe { ( &mut TX_BUFFER, - &mut TX_DESCRIPTORS, + tx_descriptors, &mut RX_BUFFER, - &mut RX_DESCRIPTORS, + rx_descriptors, ) } }}; + + ($size:expr, $chunk_size:expr) => {{ + $crate::dma_circular_buffers_chunk_size!($size, $size, $chunk_size) + }}; } -/// Convenience macro to create DMA descriptors +/// Convenience macro to create DMA descriptors with specific chunk size /// /// ## 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 (tx_descriptors, rx_descriptors) = dma_descriptors!(32000, 32000); +/// let (tx_descriptors, rx_descriptors) = dma_descriptors_chunk_size!(32000, 32000, 4032); /// ``` #[macro_export] -macro_rules! dma_descriptors { - ($tx_size:expr, $rx_size:expr) => {{ - 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]; +macro_rules! dma_descriptors_chunk_size { + ($tx_size:expr, $rx_size:expr, $chunk_size:expr) => {{ + // these will check for size at compile time + const _: () = assert!($chunk_size <= 4092, "chunk size must be <= 4092"); + const _: () = assert!($chunk_size > 9, "chunk size must be > 0"); + + static mut TX_DESCRIPTORS: [$crate::dma::DmaDescriptor; + ($tx_size + $chunk_size - 1) / $chunk_size] = + [$crate::dma::DmaDescriptor::EMPTY; ($tx_size + $chunk_size - 1) / $chunk_size]; + static mut RX_DESCRIPTORS: [$crate::dma::DmaDescriptor; + ($rx_size + $chunk_size - 1) / $chunk_size] = + [$crate::dma::DmaDescriptor::EMPTY; ($rx_size + $chunk_size - 1) / $chunk_size]; unsafe { (&mut TX_DESCRIPTORS, &mut RX_DESCRIPTORS) } }}; - ($size:expr) => {{ - 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) } - }}; + ($size:expr, $chunk_size:expr) => { + $crate::dma_descriptors_chunk_size!($size, $size, $chunk_size) + }; } -/// Convenience macro to create circular DMA descriptors +/// Convenience macro to create circular DMA descriptors with specific chunk +/// size /// /// ## 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 (tx_descriptors, rx_descriptors) = dma_circular_descriptors!(32000, 32000); +/// let (tx_descriptors, rx_descriptors) = dma_circular_descriptors!(32000, 32000, 4032); /// ``` #[macro_export] -macro_rules! dma_circular_descriptors { - ($tx_size:expr, $rx_size:expr) => {{ - const tx_descriptor_len: usize = if $tx_size > 4092 * 2 { - ($tx_size + 4091) / 4092 +macro_rules! dma_circular_descriptors_chunk_size { + ($tx_size:expr, $rx_size:expr, $chunk_size:expr) => {{ + // these will check for size at compile time + const _: () = assert!($chunk_size <= 4092, "chunk size must be <= 4092"); + const _: () = assert!($chunk_size > 9, "chunk size must be > 0"); + + const tx_descriptor_len: usize = if $tx_size > $chunk_size * 2 { + ($tx_size + $chunk_size - 1) / $chunk_size } else { 3 }; - const rx_descriptor_len: usize = if $rx_size > 4092 * 2 { - ($rx_size + 4091) / 4092 + const rx_descriptor_len: usize = if $rx_size > $chunk_size * 2 { + ($rx_size + $chunk_size - 1) / $chunk_size } else { 3 }; @@ -311,19 +343,9 @@ macro_rules! dma_circular_descriptors { unsafe { (&mut TX_DESCRIPTORS, &mut RX_DESCRIPTORS) } }}; - ($size:expr) => {{ - const descriptor_len: usize = if $size > 4092 * 2 { - ($size + 4091) / 4092 - } else { - 3 - }; - - 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) } - }}; + ($size:expr, $chunk_size:expr) => { + $crate::dma_circular_descriptors_chunk_size!($size, $size, $chunk_size) + }; } /// DMA Errors @@ -500,11 +522,25 @@ pub trait PeripheralMarker {} #[derive(Debug)] pub struct DescriptorChain { pub(crate) descriptors: &'static mut [DmaDescriptor], + chunk_size: usize, } impl DescriptorChain { pub fn new(descriptors: &'static mut [DmaDescriptor]) -> Self { - Self { descriptors } + Self { + descriptors, + chunk_size: CHUNK_SIZE, + } + } + + pub fn new_with_chunk_size( + descriptors: &'static mut [DmaDescriptor], + chunk_size: usize, + ) -> Self { + Self { + descriptors, + chunk_size, + } } pub fn first_mut(&mut self) -> *mut DmaDescriptor { @@ -538,7 +574,7 @@ impl DescriptorChain { return Err(DmaError::UnsupportedMemoryRegion); } - if self.descriptors.len() < len.div_ceil(CHUNK_SIZE) { + if self.descriptors.len() < len.div_ceil(self.chunk_size) { return Err(DmaError::OutOfDescriptors); } @@ -548,8 +584,8 @@ impl DescriptorChain { self.descriptors.fill(DmaDescriptor::EMPTY); - let max_chunk_size = if !circular || len > CHUNK_SIZE * 2 { - CHUNK_SIZE + let max_chunk_size = if !circular || len > self.chunk_size * 2 { + self.chunk_size } else { len / 3 + len % 3 }; @@ -614,14 +650,14 @@ impl DescriptorChain { return Err(DmaError::BufferTooSmall); } - if self.descriptors.len() < len.div_ceil(CHUNK_SIZE) { + if self.descriptors.len() < len.div_ceil(self.chunk_size) { return Err(DmaError::OutOfDescriptors); } self.descriptors.fill(DmaDescriptor::EMPTY); - let max_chunk_size = if !circular || len > CHUNK_SIZE * 2 { - CHUNK_SIZE + let max_chunk_size = if !circular || len > self.chunk_size * 2 { + self.chunk_size } else { len / 3 + len % 3 }; diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index 33a82775d36..577d9c206b4 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -24,6 +24,10 @@ harness = false name = "delay" harness = false +[[test]] +name = "dma_macros" +harness = false + [[test]] name = "dma_mem2mem" harness = false diff --git a/hil-test/tests/dma_macros.rs b/hil-test/tests/dma_macros.rs new file mode 100644 index 00000000000..12989806b62 --- /dev/null +++ b/hil-test/tests/dma_macros.rs @@ -0,0 +1,205 @@ +//! DMA Mem2Mem Tests + +//% CHIPS: esp32s3 esp32c2 esp32c3 esp32c6 esp32h2 + +#![no_std] +#![no_main] + +use defmt_rtt as _; +use esp_backtrace as _; + +const DATA_SIZE: usize = 1024 * 10; + +pub(crate) const fn compute_size(size: usize, chunk_size: usize) -> usize { + (size + chunk_size - 1) / chunk_size +} + +pub(crate) const fn compute_circular_size(size: usize, chunk_size: usize) -> usize { + if size > chunk_size * 2 { + (size + chunk_size - 1) / chunk_size + } else { + 3 + } +} + +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use defmt::assert_eq; + + use super::*; + + #[init] + fn init() {} + + #[test] + fn test_dma_descriptors_same_size() { + use esp_hal::dma::CHUNK_SIZE; + let (tx_descriptors, rx_descriptors) = esp_hal::dma_descriptors!(DATA_SIZE); + assert_eq!(tx_descriptors.len(), rx_descriptors.len()); + assert_eq!(tx_descriptors.len(), compute_size(DATA_SIZE, CHUNK_SIZE)); + assert_eq!(rx_descriptors.len(), compute_size(DATA_SIZE, CHUNK_SIZE)); + } + + #[test] + fn test_dma_descriptors_different_size() { + use esp_hal::dma::CHUNK_SIZE; + const TX_SIZE: usize = DATA_SIZE; + const RX_SIZE: usize = DATA_SIZE / 2; + let (tx_descriptors, rx_descriptors) = esp_hal::dma_descriptors!(TX_SIZE, RX_SIZE); + assert_eq!(tx_descriptors.len(), compute_size(TX_SIZE, CHUNK_SIZE)); + assert_eq!(rx_descriptors.len(), compute_size(RX_SIZE, CHUNK_SIZE)); + } + + #[test] + fn test_dma_circular_descriptors_same_size() { + use esp_hal::dma::CHUNK_SIZE; + let (tx_descriptors, rx_descriptors) = esp_hal::dma_circular_descriptors!(DATA_SIZE); + assert_eq!(tx_descriptors.len(), rx_descriptors.len()); + assert_eq!( + tx_descriptors.len(), + compute_circular_size(DATA_SIZE, CHUNK_SIZE) + ); + assert_eq!( + rx_descriptors.len(), + compute_circular_size(DATA_SIZE, CHUNK_SIZE) + ); + } + + #[test] + fn test_dma_circular_descriptors_different_size() { + use esp_hal::dma::CHUNK_SIZE; + const TX_SIZE: usize = CHUNK_SIZE * 2; + const RX_SIZE: usize = DATA_SIZE / 2; + let (tx_descriptors, rx_descriptors) = esp_hal::dma_circular_descriptors!(TX_SIZE, RX_SIZE); + assert_eq!( + tx_descriptors.len(), + compute_circular_size(TX_SIZE, CHUNK_SIZE) + ); + assert_eq!( + rx_descriptors.len(), + compute_circular_size(RX_SIZE, CHUNK_SIZE) + ); + } + + #[test] + fn test_dma_buffers_same_size() { + use esp_hal::dma::CHUNK_SIZE; + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = + esp_hal::dma_buffers!(DATA_SIZE); + assert_eq!(tx_buffer.len(), DATA_SIZE); + assert_eq!(rx_buffer.len(), DATA_SIZE); + assert_eq!(tx_descriptors.len(), rx_descriptors.len()); + assert_eq!(tx_descriptors.len(), compute_size(DATA_SIZE, CHUNK_SIZE)); + assert_eq!(rx_descriptors.len(), compute_size(DATA_SIZE, CHUNK_SIZE)); + } + + #[test] + fn test_dma_buffers_different_size() { + use esp_hal::dma::CHUNK_SIZE; + const TX_SIZE: usize = DATA_SIZE; + const RX_SIZE: usize = DATA_SIZE / 2; + + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = + esp_hal::dma_buffers!(TX_SIZE, RX_SIZE); + assert_eq!(tx_buffer.len(), TX_SIZE); + assert_eq!(rx_buffer.len(), RX_SIZE); + assert_eq!(tx_descriptors.len(), compute_size(TX_SIZE, CHUNK_SIZE)); + assert_eq!(rx_descriptors.len(), compute_size(RX_SIZE, CHUNK_SIZE)); + } + + #[test] + fn test_dma_circular_buffers_same_size() { + use esp_hal::dma::CHUNK_SIZE; + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = + esp_hal::dma_circular_buffers!(DATA_SIZE); + assert_eq!(tx_buffer.len(), DATA_SIZE); + assert_eq!(rx_buffer.len(), DATA_SIZE); + assert_eq!(tx_descriptors.len(), rx_descriptors.len()); + assert_eq!( + tx_descriptors.len(), + compute_circular_size(DATA_SIZE, CHUNK_SIZE) + ); + assert_eq!( + rx_descriptors.len(), + compute_circular_size(DATA_SIZE, CHUNK_SIZE) + ); + } + + #[test] + fn test_dma_circular_buffers_different_size() { + use esp_hal::dma::CHUNK_SIZE; + const TX_SIZE: usize = CHUNK_SIZE * 4; + const RX_SIZE: usize = CHUNK_SIZE * 2; + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = + esp_hal::dma_circular_buffers!(TX_SIZE, RX_SIZE); + assert_eq!(tx_buffer.len(), TX_SIZE); + assert_eq!(rx_buffer.len(), RX_SIZE); + assert_eq!( + tx_descriptors.len(), + compute_circular_size(TX_SIZE, CHUNK_SIZE) + ); + assert_eq!( + rx_descriptors.len(), + compute_circular_size(RX_SIZE, CHUNK_SIZE) + ); + } + + #[test] + fn test_dma_descriptors_chunk_size_same_size() { + const CHUNK_SIZE: usize = 2048; + let (tx_descriptors, rx_descriptors) = + esp_hal::dma_descriptors_chunk_size!(DATA_SIZE, CHUNK_SIZE); + assert_eq!(tx_descriptors.len(), rx_descriptors.len()); + assert_eq!(tx_descriptors.len(), compute_size(DATA_SIZE, CHUNK_SIZE)); + assert_eq!(rx_descriptors.len(), compute_size(DATA_SIZE, CHUNK_SIZE)); + } + + #[test] + fn test_dma_descriptors_chunk_size_different_size() { + const CHUNK_SIZE: usize = 2048; + const TX_SIZE: usize = DATA_SIZE; + const RX_SIZE: usize = DATA_SIZE / 2; + let (tx_descriptors, rx_descriptors) = + esp_hal::dma_descriptors_chunk_size!(TX_SIZE, RX_SIZE, CHUNK_SIZE); + assert_eq!(tx_descriptors.len(), compute_size(TX_SIZE, CHUNK_SIZE)); + assert_eq!(rx_descriptors.len(), compute_size(RX_SIZE, CHUNK_SIZE)); + } + + #[test] + fn test_dma_circular_buffers_chunk_size_same_size() { + const CHUNK_SIZE: usize = 2048; + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = + esp_hal::dma_circular_buffers_chunk_size!(DATA_SIZE, CHUNK_SIZE); + assert_eq!(tx_buffer.len(), DATA_SIZE); + assert_eq!(rx_buffer.len(), DATA_SIZE); + assert_eq!(tx_descriptors.len(), rx_descriptors.len()); + assert_eq!( + tx_descriptors.len(), + compute_circular_size(DATA_SIZE, CHUNK_SIZE) + ); + assert_eq!( + rx_descriptors.len(), + compute_circular_size(DATA_SIZE, CHUNK_SIZE) + ); + } + + #[test] + fn test_dma_circular_buffers_chunk_size_different_size() { + const CHUNK_SIZE: usize = 2048; + const TX_SIZE: usize = DATA_SIZE; + const RX_SIZE: usize = DATA_SIZE / 2; + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = + esp_hal::dma_circular_buffers_chunk_size!(TX_SIZE, RX_SIZE, CHUNK_SIZE); + assert_eq!(tx_buffer.len(), TX_SIZE); + assert_eq!(rx_buffer.len(), RX_SIZE); + assert_eq!( + tx_descriptors.len(), + compute_circular_size(TX_SIZE, CHUNK_SIZE) + ); + assert_eq!( + rx_descriptors.len(), + compute_circular_size(RX_SIZE, CHUNK_SIZE) + ); + } +} diff --git a/hil-test/tests/dma_mem2mem.rs b/hil-test/tests/dma_mem2mem.rs index 3869f4a9e55..6e833d3e50f 100644 --- a/hil-test/tests/dma_mem2mem.rs +++ b/hil-test/tests/dma_mem2mem.rs @@ -11,6 +11,7 @@ use esp_hal::{ clock::ClockControl, dma::{Dma, DmaPriority, Mem2Mem}, dma_buffers, + dma_buffers_chunk_size, peripherals::Peripherals, system::SystemControl, }; @@ -56,4 +57,35 @@ mod tests { assert_eq!(rx_buffer[i], tx_buffer[i]); } } + + #[test] + fn test_internal_mem2mem_chunk_size() { + const CHUNK_SIZE: usize = 2048; + let peripherals = Peripherals::take(); + let system = SystemControl::new(peripherals.SYSTEM); + let _clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let (tx_buffer, tx_descriptors, mut rx_buffer, rx_descriptors) = dma_buffers_chunk_size!(DATA_SIZE, CHUNK_SIZE); + + let dma = Dma::new(peripherals.DMA); + let channel = dma.channel0.configure(false, DmaPriority::Priority0); + #[cfg(any(feature = "esp32c2", feature = "esp32c3", feature = "esp32s3"))] + let dma_peripheral = peripherals.SPI2; + #[cfg(not(any(feature = "esp32c2", feature = "esp32c3", feature = "esp32s3")))] + let dma_peripheral = peripherals.MEM2MEM1; + + let mut mem2mem = Mem2Mem::new_with_chunk_size(channel, dma_peripheral, tx_descriptors, rx_descriptors, CHUNK_SIZE); + + for i in 0..core::mem::size_of_val(tx_buffer) { + tx_buffer[i] = (i % 256) as u8; + } + let dma_wait = mem2mem.start_transfer(&tx_buffer, &mut rx_buffer).unwrap(); + dma_wait.wait().unwrap(); + // explicitly drop to insure the mem2mem bit is not left set as this causes + // subsequent dma tests to fail. + drop(mem2mem); + for i in 0..core::mem::size_of_val(tx_buffer) { + assert_eq!(rx_buffer[i], tx_buffer[i]); + } + } }