diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index f582c13da..5ff8db91d 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -28,6 +28,10 @@ harness = false name = "spi_full_duplex" harness = false +[[test]] +name = "spi_full_duplex_dma" +harness = false + [[test]] name = "rsa" harness = false diff --git a/hil-test/tests/spi_full_duplex.rs b/hil-test/tests/spi_full_duplex.rs index 1b85d45ea..c6d7e50ff 100644 --- a/hil-test/tests/spi_full_duplex.rs +++ b/hil-test/tests/spi_full_duplex.rs @@ -62,7 +62,8 @@ mod tests { } #[test] - fn test_symestric_transfer(mut ctx: Context) { + #[timeout(3)] + fn test_symmetric_transfer(mut ctx: Context) { let write = [0xde, 0xad, 0xbe, 0xef]; let mut read: [u8; 4] = [0x00u8; 4]; @@ -72,7 +73,8 @@ mod tests { } #[test] - fn test_asymestric_transfer(mut ctx: Context) { + #[timeout(3)] + fn test_asymmetric_transfer(mut ctx: Context) { let write = [0xde, 0xad, 0xbe, 0xef]; let mut read: [u8; 4] = [0x00; 4]; @@ -83,7 +85,8 @@ mod tests { } #[test] - fn test_symestric_transfer_huge_buffer(mut ctx: Context) { + #[timeout(3)] + fn test_symmetric_transfer_huge_buffer(mut ctx: Context) { let mut write = [0x55u8; 4096]; for byte in 0..write.len() { write[byte] = byte as u8; @@ -96,7 +99,7 @@ mod tests { #[test] #[timeout(3)] - fn test_symestric_transfer_huge_buffer_no_alloc(mut ctx: Context) { + fn test_symmetric_transfer_huge_buffer_no_alloc(mut ctx: Context) { let mut write = [0x55u8; 4096]; for byte in 0..write.len() { write[byte] = byte as u8; diff --git a/hil-test/tests/spi_full_duplex_dma.rs b/hil-test/tests/spi_full_duplex_dma.rs new file mode 100644 index 000000000..14078c3f3 --- /dev/null +++ b/hil-test/tests/spi_full_duplex_dma.rs @@ -0,0 +1,172 @@ +//! SPI Full Duplex DMA Test +//! +//! Folowing pins are used: +//! SCLK GPIO0 +//! MISO GPIO2 +//! MOSI GPIO4 +//! CS GPIO5 +//! +//! Connect MISO (GPIO2) and MOSI (GPIO4) pins. + +//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 + +#![no_std] +#![no_main] + +use defmt_rtt as _; +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, + dma::{Dma, DmaPriority}, + dma_buffers, + gpio::IO, + peripherals::Peripherals, + prelude::*, + spi::{ + master::{prelude::*, Spi}, + SpiMode, + }, +}; + +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use defmt::assert_eq; + + use super::*; + + #[test] + #[timeout(3)] + fn test_symmetric_dma_transfer() { + const DMA_BUFFER_SIZE: usize = 4; + + let peripherals = Peripherals::take(); + let system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio0; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio4; + let cs = io.pins.gpio5; + + let dma = Dma::new(peripherals.DMA); + + #[cfg(any(feature = "esp32", feature = "esp32s2"))] + let dma_channel = dma.spi2channel; + #[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 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, + )); + + // DMA buffer require a static life-time + let mut send = tx_buffer; + let mut receive = rx_buffer; + + send.copy_from_slice(&[0xde, 0xad, 0xbe, 0xef]); + + let transfer = spi.dma_transfer(&mut send, &mut receive).unwrap(); + transfer.wait().unwrap(); + assert_eq!(send, receive); + } + + #[test] + #[timeout(3)] + fn test_asymmetric_dma_transfer() { + let peripherals = Peripherals::take(); + let system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio0; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio4; + let cs = io.pins.gpio5; + + let dma = Dma::new(peripherals.DMA); + + #[cfg(any(feature = "esp32", feature = "esp32s2"))] + let dma_channel = dma.spi2channel; + #[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 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, + )); + + // DMA buffer require a static life-time + let mut send = tx_buffer; + let mut receive = rx_buffer; + + send.copy_from_slice(&[0xde, 0xad, 0xbe, 0xef]); + + let transfer = spi.dma_transfer(&mut send, &mut receive).unwrap(); + transfer.wait().unwrap(); + assert_eq!(send[0], receive[0]); + } + + #[test] + #[timeout(3)] + fn test_symmetric_dma_transfer_huge_buffer() { + const DMA_BUFFER_SIZE: usize = 4096; + + let peripherals = Peripherals::take(); + let system = peripherals.SYSTEM.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio0; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio4; + let cs = io.pins.gpio5; + + let dma = Dma::new(peripherals.DMA); + + #[cfg(any(feature = "esp32", feature = "esp32s2"))] + let dma_channel = dma.spi2channel; + #[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 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, + )); + + // DMA buffer require a static life-time + let mut send = tx_buffer; + let mut receive = rx_buffer; + + send.copy_from_slice(&[0x55u8; 4096]); + for byte in 0..send.len() { + send[byte] = byte as u8; + } + + let transfer = spi.dma_transfer(&mut send, &mut receive).unwrap(); + transfer.wait().unwrap(); + assert_eq!(send, receive); + } +}