From 0d7ad38a4274c3824ac4fbc6e2a9bf771bddb40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 23 Aug 2024 18:01:49 +0200 Subject: [PATCH 1/5] Deduplicate spi_full_duplex_dma_async --- hil-test/tests/spi_full_duplex_dma_async.rs | 118 +++++++++----------- 1 file changed, 50 insertions(+), 68 deletions(-) diff --git a/hil-test/tests/spi_full_duplex_dma_async.rs b/hil-test/tests/spi_full_duplex_dma_async.rs index cc0c4db5935..a8d3ddcf7f7 100644 --- a/hil-test/tests/spi_full_duplex_dma_async.rs +++ b/hil-test/tests/spi_full_duplex_dma_async.rs @@ -22,33 +22,37 @@ use embedded_hal_async::spi::SpiBus; use esp_hal::{ clock::ClockControl, - dma::{Dma, DmaPriority}, + dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf, DmaChannel0}, dma_buffers, - gpio::{Io, Level, Output, Pull}, + gpio::{Io, GpioPin, Level, Output, Pull}, pcnt::{ channel::{EdgeMode, PcntInputConfig, PcntSource}, - Pcnt, + Pcnt, unit::Unit }, - peripherals::Peripherals, + peripherals::{Peripherals, SPI2}, prelude::*, - spi::{master::Spi, SpiMode}, + spi::{master::{Spi, dma::asynch::SpiDmaAsyncBus}, SpiMode}, system::SystemControl, }; use hil_test as _; +const DMA_BUFFER_SIZE: usize = 5; + +struct Context { + spi: SpiDmaAsyncBus<'static, SPI2, DmaChannel0>, + pcnt_unit: Unit<'static, 0>, + out_pin: Output<'static, GpioPin<5>>, + mosi_mirror: GpioPin<2>, +} + #[cfg(test)] #[embedded_test::tests(executor = esp_hal_embassy::Executor::new())] mod tests { - use defmt::assert_eq; - use esp_hal::dma::{DmaRxBuf, DmaTxBuf}; - use super::*; + use defmt::assert_eq; - #[test] - #[timeout(3)] - async fn test_async_dma_read_dma_write_pcnt() { - const DMA_BUFFER_SIZE: usize = 5; - + #[init] + fn init() -> Context { let peripherals = Peripherals::take(); let system = SystemControl::new(peripherals.SYSTEM); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); @@ -67,26 +71,39 @@ mod tests { 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; + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + let dma_channel = dma.spi2channel; + } else { + let dma_channel = dma.channel0; + } + } let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) + 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_for_async(false, DmaPriority::Priority0)) .with_buffers(dma_tx_buf, dma_rx_buf); - let unit = pcnt.unit0; - unit.channel0.set_edge_signal(PcntSource::from_pin( + Context { + spi, + pcnt_unit: pcnt.unit0, + out_pin, mosi_mirror, + } + } + + #[test] + #[timeout(3)] + async fn test_async_dma_read_dma_write_pcnt(mut ctx: Context) { + ctx.pcnt_unit.channel0.set_edge_signal(PcntSource::from_pin( + ctx.mosi_mirror, PcntInputConfig { pull: Pull::Down }, )); - unit.channel0 + ctx.pcnt_unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); let mut receive = [0; DMA_BUFFER_SIZE]; @@ -94,61 +111,26 @@ mod tests { // Fill the buffer where each byte has 3 pos edges. let transmit = [0b0110_1010; DMA_BUFFER_SIZE]; - assert_eq!(out_pin.is_set_low(), true); + assert_eq!(ctx.out_pin.is_set_low(), true); for i in 1..4 { receive.copy_from_slice(&[5, 5, 5, 5, 5]); - SpiBus::read(&mut spi, &mut receive).await.unwrap(); + SpiBus::read(&mut ctx.spi, &mut receive).await.unwrap(); assert_eq!(receive, [0, 0, 0, 0, 0]); - SpiBus::write(&mut spi, &transmit).await.unwrap(); - assert_eq!(unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); + SpiBus::write(&mut ctx.spi, &transmit).await.unwrap(); + assert_eq!(ctx.pcnt_unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); } } #[test] #[timeout(3)] - async fn test_async_dma_read_dma_transfer_pcnt() { - const DMA_BUFFER_SIZE: usize = 5; - - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pcnt = Pcnt::new(peripherals.PCNT); - let sclk = io.pins.gpio0; - let mosi_mirror = io.pins.gpio2; - let mosi = io.pins.gpio3; - let miso = io.pins.gpio6; - let cs = io.pins.gpio8; - - let mut out_pin = Output::new(io.pins.gpio5, Level::High); - out_pin.set_low(); - assert_eq!(out_pin.is_set_low(), true); - - 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, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); - let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - - 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, DmaPriority::Priority0)) - .with_buffers(dma_tx_buf, dma_rx_buf); - - let unit = pcnt.unit0; - unit.channel0.set_edge_signal(PcntSource::from_pin( - mosi_mirror, + async fn test_async_dma_read_dma_transfer_pcnt(mut ctx: Context) { + ctx.pcnt_unit.channel0.set_edge_signal(PcntSource::from_pin( + ctx.mosi_mirror, PcntInputConfig { pull: Pull::Down }, )); - unit.channel0 + ctx.pcnt_unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); let mut receive = [0; DMA_BUFFER_SIZE]; @@ -156,17 +138,17 @@ mod tests { // Fill the buffer where each byte has 3 pos edges. let transmit = [0b0110_1010; DMA_BUFFER_SIZE]; - assert_eq!(out_pin.is_set_low(), true); + assert_eq!(ctx.out_pin.is_set_low(), true); for i in 1..4 { receive.copy_from_slice(&[5, 5, 5, 5, 5]); - SpiBus::read(&mut spi, &mut receive).await.unwrap(); + SpiBus::read(&mut ctx.spi, &mut receive).await.unwrap(); assert_eq!(receive, [0, 0, 0, 0, 0]); - SpiBus::transfer(&mut spi, &mut receive, &transmit) + SpiBus::transfer(&mut ctx.spi, &mut receive, &transmit) .await .unwrap(); - assert_eq!(unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); + assert_eq!(ctx.pcnt_unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); } } } From cfa74f4b9f4963f0d59860538919edbb48cdea53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 23 Aug 2024 18:28:03 +0200 Subject: [PATCH 2/5] Refactor SPI tests --- hil-test/tests/spi_full_duplex.rs | 24 +- hil-test/tests/spi_full_duplex_dma.rs | 358 ++++++++------------ hil-test/tests/spi_full_duplex_dma_async.rs | 31 +- hil-test/tests/spi_half_duplex_read.rs | 91 +++-- hil-test/tests/spi_half_duplex_write.rs | 107 ++++-- 5 files changed, 297 insertions(+), 314 deletions(-) diff --git a/hil-test/tests/spi_full_duplex.rs b/hil-test/tests/spi_full_duplex.rs index fba38765583..0502f0c1da2 100644 --- a/hil-test/tests/spi_full_duplex.rs +++ b/hil-test/tests/spi_full_duplex.rs @@ -28,8 +28,15 @@ struct Context { spi: Spi<'static, esp_hal::peripherals::SPI2, FullDuplexMode>, } -impl Context { - pub fn init() -> Self { +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use defmt::assert_eq; + + use super::*; + + #[init] + fn init() -> Context { let peripherals = Peripherals::take(); let system = SystemControl::new(peripherals.SYSTEM); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); @@ -49,19 +56,6 @@ impl Context { Context { spi } } -} - -#[cfg(test)] -#[embedded_test::tests] -mod tests { - use defmt::assert_eq; - - use super::*; - - #[init] - fn init() -> Context { - Context::init() - } #[test] #[timeout(3)] diff --git a/hil-test/tests/spi_full_duplex_dma.rs b/hil-test/tests/spi_full_duplex_dma.rs index 938d2cec22a..7a61e6c54db 100644 --- a/hil-test/tests/spi_full_duplex_dma.rs +++ b/hil-test/tests/spi_full_duplex_dma.rs @@ -23,64 +23,148 @@ use esp_hal::{ clock::ClockControl, - dma::{Dma, DmaPriority}, + dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::Io, - peripherals::Peripherals, + peripherals::{Peripherals, SPI2}, prelude::*, - spi::{master::Spi, SpiMode}, + spi::{ + master::{dma::SpiDma, Spi}, + FullDuplexMode, + SpiMode, + }, system::SystemControl, + Blocking, +}; +#[cfg(any( + feature = "esp32", + feature = "esp32c6", + feature = "esp32h2", + feature = "esp32s3" +))] +use esp_hal::{ + gpio::{GpioPin, Level, Output, Pull}, + pcnt::{ + channel::{EdgeMode, PcntInputConfig, PcntSource}, + unit::Unit, + Pcnt, + }, }; use hil_test as _; +cfg_if::cfg_if! { + if #[cfg(any( + feature = "esp32", + ))] { + use esp_hal::dma::Spi2DmaChannel as DmaChannel0; + } else { + use esp_hal::dma::DmaChannel0; + } +} + +cfg_if::cfg_if! { + if #[cfg(any( + feature = "esp32", + feature = "esp32c6", + feature = "esp32h2", + feature = "esp32s3" + ))] { + struct Context { + spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>, + pcnt_unit: Unit<'static, 0>, + out_pin: Output<'static, GpioPin<5>>, + mosi_mirror: GpioPin<2>, + } + } else { + struct Context { + spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>, + } + } +} + #[cfg(test)] #[embedded_test::tests] mod tests { use defmt::assert_eq; - use esp_hal::{ - dma::{DmaRxBuf, DmaTxBuf}, - spi::master::dma::SpiDmaBus, - }; use super::*; - #[test] - #[timeout(3)] - fn test_symmetric_dma_transfer() { - const DMA_BUFFER_SIZE: usize = 4; - + #[init] + fn init() -> Context { let peripherals = Peripherals::take(); let system = SystemControl::new(peripherals.SYSTEM); 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.gpio3; + let miso = io.pins.gpio2; let cs = io.pins.gpio8; 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, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); - let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + let dma_channel = dma.spi2channel; + } else { + let dma_channel = dma.channel0; + } + } 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, DmaPriority::Priority0)); + #[cfg(any( + feature = "esp32", + feature = "esp32c6", + feature = "esp32h2", + feature = "esp32s3" + ))] + let pcnt = Pcnt::new(peripherals.PCNT); + + cfg_if::cfg_if! { + if #[cfg(any( + feature = "esp32", + feature = "esp32c6", + feature = "esp32h2", + feature = "esp32s3" + ))] { + + let mut out_pin = Output::new(io.pins.gpio5, Level::Low); + out_pin.set_low(); + assert_eq!(out_pin.is_set_low(), true); + let mosi_mirror = io.pins.gpio2; + + Context { + spi, + pcnt_unit: pcnt.unit0, + out_pin, + mosi_mirror, + } + } else { + Context { + spi + } + } + } + } + + #[test] + #[timeout(3)] + fn test_symmetric_dma_transfer(ctx: Context) { + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4); + let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); + let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); + dma_tx_buf.fill(&[0xde, 0xad, 0xbe, 0xef]); - let transfer = spi + let transfer = ctx + .spi .dma_transfer(dma_tx_buf, dma_rx_buf) .map_err(|e| e.0) .unwrap(); - (_, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); + let (_, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); assert_eq!(dma_tx_buf.as_slice(), dma_rx_buf.as_slice()); } @@ -88,81 +172,39 @@ mod tests { #[timeout(3)] // S3 is disabled due to https://github.com/esp-rs/esp-hal/issues/1524#issuecomment-2255306292 #[cfg(not(feature = "esp32s3"))] - fn test_asymmetric_dma_transfer() { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - 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.gpio3; - let cs = io.pins.gpio8; - - 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; - + fn test_asymmetric_dma_transfer(ctx: Context) { let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4, 2); let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); - let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - - 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, DmaPriority::Priority0)); + let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); dma_tx_buf.fill(&[0xde, 0xad, 0xbe, 0xef]); - let transfer = spi + let transfer = ctx + .spi .dma_transfer(dma_tx_buf, dma_rx_buf) .map_err(|e| e.0) .unwrap(); - (_, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); + let (_, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); assert_eq!(dma_tx_buf.as_slice()[0..1], dma_rx_buf.as_slice()[0..1]); } #[test] #[timeout(3)] - fn test_symmetric_dma_transfer_huge_buffer() { - const DMA_BUFFER_SIZE: usize = 4096; - - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - 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.gpio3; - let cs = io.pins.gpio8; - - 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, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); + fn test_symmetric_dma_transfer_huge_buffer(ctx: Context) { + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4096); let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); - let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - - 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, DmaPriority::Priority0)); + let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); for (i, d) in dma_tx_buf.as_mut_slice().iter_mut().enumerate() { *d = i as _; } - let transfer = spi + let transfer = ctx + .spi .dma_transfer(dma_tx_buf, dma_rx_buf) .map_err(|e| e.0) .unwrap(); - (_, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); + let (_, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); assert_eq!(dma_tx_buf.as_slice(), dma_rx_buf.as_slice()); } @@ -174,51 +216,17 @@ mod tests { feature = "esp32h2", feature = "esp32s3" ))] - fn test_dma_read_dma_write_pcnt() { - use esp_hal::{ - gpio::{Level, Output, Pull}, - pcnt::{ - channel::{EdgeMode, PcntInputConfig, PcntSource}, - Pcnt, - }, - }; - + fn test_dma_read_dma_write_pcnt(ctx: Context) { const DMA_BUFFER_SIZE: usize = 5; - - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pcnt = Pcnt::new(peripherals.PCNT); - let sclk = io.pins.gpio0; - let mosi_mirror = io.pins.gpio2; - let mosi = io.pins.gpio3; - let miso = io.pins.gpio6; - let cs = io.pins.gpio8; - - let mut out_pin = Output::new(io.pins.gpio5, Level::High); - out_pin.set_low(); - assert_eq!(out_pin.is_set_low(), true); - - 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, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - 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, DmaPriority::Priority0)); + let unit = ctx.pcnt_unit; + let mut spi = ctx.spi; - let unit = pcnt.unit0; unit.channel0.set_edge_signal(PcntSource::from_pin( - mosi_mirror, + ctx.mosi_mirror, PcntInputConfig { pull: Pull::Down }, )); unit.channel0 @@ -227,7 +235,7 @@ mod tests { // Fill the buffer where each byte has 3 pos edges. dma_tx_buf.as_mut_slice().fill(0b0110_1010); - assert_eq!(out_pin.is_set_low(), true); + assert_eq!(ctx.out_pin.is_set_low(), true); for i in 1..4 { dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); @@ -249,51 +257,17 @@ mod tests { feature = "esp32h2", feature = "esp32s3" ))] - fn test_dma_read_dma_transfer_pcnt() { - use esp_hal::{ - gpio::{Level, Output, Pull}, - pcnt::{ - channel::{EdgeMode, PcntInputConfig, PcntSource}, - Pcnt, - }, - }; - + fn test_dma_read_dma_transfer_pcnt(ctx: Context) { const DMA_BUFFER_SIZE: usize = 5; - - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pcnt = Pcnt::new(peripherals.PCNT); - let sclk = io.pins.gpio0; - let mosi_mirror = io.pins.gpio2; - let mosi = io.pins.gpio3; - let miso = io.pins.gpio6; - let cs = io.pins.gpio8; - - let mut out_pin = Output::new(io.pins.gpio5, Level::High); - out_pin.set_low(); - assert_eq!(out_pin.is_set_low(), true); - - 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, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - 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, DmaPriority::Priority0)); + let unit = ctx.pcnt_unit; + let mut spi = ctx.spi; - let unit = pcnt.unit0; unit.channel0.set_edge_signal(PcntSource::from_pin( - mosi_mirror, + ctx.mosi_mirror, PcntInputConfig { pull: Pull::Down }, )); unit.channel0 @@ -302,7 +276,7 @@ mod tests { // Fill the buffer where each byte has 3 pos edges. dma_tx_buf.as_mut_slice().fill(0b0110_1010); - assert_eq!(out_pin.is_set_low(), true); + assert_eq!(ctx.out_pin.is_set_low(), true); for i in 1..4 { dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); @@ -321,34 +295,12 @@ mod tests { #[test] #[timeout(3)] - fn test_dma_bus_symmetric_transfer() { - const DMA_BUFFER_SIZE: usize = 4; - - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - 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.gpio3; - let cs = io.pins.gpio8; - - 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, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); + fn test_dma_bus_symmetric_transfer(ctx: Context) { + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4); let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - 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, DmaPriority::Priority0)) - .with_buffers(dma_tx_buf, dma_rx_buf); + let mut spi = ctx.spi.with_buffers(dma_tx_buf, dma_rx_buf); let tx_buf = [0xde, 0xad, 0xbe, 0xef]; let mut rx_buf = [0; 4]; @@ -360,32 +312,12 @@ mod tests { #[test] #[timeout(3)] - fn test_dma_bus_asymmetric_transfer() { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - 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.gpio3; - let cs = io.pins.gpio8; - - 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; - + fn test_dma_bus_asymmetric_transfer(ctx: Context) { let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4); let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - 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, DmaPriority::Priority0)) - .with_buffers(dma_tx_buf, dma_rx_buf); + let mut spi = ctx.spi.with_buffers(dma_tx_buf, dma_rx_buf); let tx_buf = [0xde, 0xad, 0xbe, 0xef]; let mut rx_buf = [0; 4]; @@ -397,34 +329,14 @@ mod tests { #[test] #[timeout(3)] - fn test_dma_bus_symmetric_transfer_huge_buffer() { + fn test_dma_bus_symmetric_transfer_huge_buffer(ctx: Context) { const DMA_BUFFER_SIZE: usize = 4096; - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - 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.gpio3; - let cs = io.pins.gpio8; - - 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, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(40); let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - 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, DmaPriority::Priority0)) - .with_buffers(dma_tx_buf, dma_rx_buf); + let mut spi = ctx.spi.with_buffers(dma_tx_buf, dma_rx_buf); let tx_buf = core::array::from_fn(|i| i as _); let mut rx_buf = [0; DMA_BUFFER_SIZE]; diff --git a/hil-test/tests/spi_full_duplex_dma_async.rs b/hil-test/tests/spi_full_duplex_dma_async.rs index a8d3ddcf7f7..5dad92a461f 100644 --- a/hil-test/tests/spi_full_duplex_dma_async.rs +++ b/hil-test/tests/spi_full_duplex_dma_async.rs @@ -22,20 +22,34 @@ use embedded_hal_async::spi::SpiBus; use esp_hal::{ clock::ClockControl, - dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf, DmaChannel0}, + dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, - gpio::{Io, GpioPin, Level, Output, Pull}, + gpio::{GpioPin, Io, Level, Output, Pull}, pcnt::{ channel::{EdgeMode, PcntInputConfig, PcntSource}, - Pcnt, unit::Unit + unit::Unit, + Pcnt, }, peripherals::{Peripherals, SPI2}, prelude::*, - spi::{master::{Spi, dma::asynch::SpiDmaAsyncBus}, SpiMode}, + spi::{ + master::{dma::asynch::SpiDmaAsyncBus, Spi}, + SpiMode, + }, system::SystemControl, }; use hil_test as _; +cfg_if::cfg_if! { + if #[cfg(any( + feature = "esp32", + ))] { + use esp_hal::dma::Spi2DmaChannel as DmaChannel0; + } else { + use esp_hal::dma::DmaChannel0; + } +} + const DMA_BUFFER_SIZE: usize = 5; struct Context { @@ -48,9 +62,10 @@ struct Context { #[cfg(test)] #[embedded_test::tests(executor = esp_hal_embassy::Executor::new())] mod tests { - use super::*; use defmt::assert_eq; + use super::*; + #[init] fn init() -> Context { let peripherals = Peripherals::take(); @@ -103,7 +118,8 @@ mod tests { ctx.mosi_mirror, PcntInputConfig { pull: Pull::Down }, )); - ctx.pcnt_unit.channel0 + ctx.pcnt_unit + .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); let mut receive = [0; DMA_BUFFER_SIZE]; @@ -130,7 +146,8 @@ mod tests { ctx.mosi_mirror, PcntInputConfig { pull: Pull::Down }, )); - ctx.pcnt_unit.channel0 + ctx.pcnt_unit + .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); let mut receive = [0; DMA_BUFFER_SIZE]; diff --git a/hil-test/tests/spi_half_duplex_read.rs b/hil-test/tests/spi_half_duplex_read.rs index bcafe7cf922..299eceec2b7 100644 --- a/hil-test/tests/spi_half_duplex_read.rs +++ b/hil-test/tests/spi_half_duplex_read.rs @@ -13,34 +13,48 @@ #![no_std] #![no_main] +use esp_hal::{ + clock::ClockControl, + dma::{Dma, DmaPriority, DmaRxBuf}, + dma_buffers, + gpio::{GpioPin, Io, Level, Output}, + peripherals::{Peripherals, SPI2}, + prelude::*, + spi::{ + master::{dma::SpiDma, Address, Command, Spi}, + HalfDuplexMode, + SpiDataMode, + SpiMode, + }, + system::SystemControl, + Blocking, +}; use hil_test as _; +cfg_if::cfg_if! { + if #[cfg(any( + feature = "esp32", + ))] { + use esp_hal::dma::Spi2DmaChannel as DmaChannel0; + } else { + use esp_hal::dma::DmaChannel0; + } +} + +struct Context { + spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>, + miso_mirror: Output<'static, GpioPin<3>>, +} + #[cfg(test)] #[embedded_test::tests] mod tests { - use esp_hal::{ - clock::ClockControl, - dma::{Dma, DmaPriority, DmaRxBuf}, - dma_buffers, - gpio::{Io, Level, Output}, - peripherals::Peripherals, - prelude::_fugit_RateExtU32, - spi::{ - master::{Address, Command, Spi}, - SpiDataMode, - SpiMode, - }, - system::SystemControl, - }; - - #[init] - fn init() {} + use defmt::assert_eq; - #[test] - #[timeout(3)] - fn test_spi_reads_correctly_from_gpio_pin() { - const DMA_BUFFER_SIZE: usize = 4; + use super::*; + #[init] + fn init() -> Context { let peripherals = Peripherals::take(); let system = SystemControl::new(peripherals.SYSTEM); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); @@ -49,25 +63,38 @@ mod tests { let sclk = io.pins.gpio0; let miso = io.pins.gpio2; - let mut miso_mirror = Output::new(io.pins.gpio3, Level::High); + let miso_mirror = Output::new(io.pins.gpio3, Level::High); 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 (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0); - let mut dma_rx_buf = DmaRxBuf::new(descriptors, buffer).unwrap(); + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + let dma_channel = dma.spi2channel; + } else { + let dma_channel = dma.channel0; + } + } - let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) + let spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_sck(sclk) .with_miso(miso) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); + Context { spi, miso_mirror } + } + + #[test] + #[timeout(3)] + fn test_spi_reads_correctly_from_gpio_pin(mut ctx: Context) { + const DMA_BUFFER_SIZE: usize = 4; + + let (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0); + let mut dma_rx_buf = DmaRxBuf::new(descriptors, buffer).unwrap(); + // SPI should read '0's from the MISO pin - miso_mirror.set_low(); + ctx.miso_mirror.set_low(); + + let mut spi = ctx.spi; let transfer = spi .read( @@ -84,7 +111,7 @@ mod tests { assert_eq!(dma_rx_buf.as_slice(), &[0x00; DMA_BUFFER_SIZE]); // SPI should read '1's from the MISO pin - miso_mirror.set_high(); + ctx.miso_mirror.set_high(); let transfer = spi .read( diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index 06bb458be1d..33ac182eec5 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -13,66 +13,99 @@ #![no_std] #![no_main] +use esp_hal::{ + clock::ClockControl, + dma::{Dma, DmaPriority, DmaTxBuf}, + dma_buffers, + gpio::{GpioPin, Io, Pull}, + pcnt::{ + channel::{EdgeMode, PcntInputConfig, PcntSource}, + unit::Unit, + Pcnt, + }, + peripherals::{Peripherals, SPI2}, + prelude::*, + spi::{ + master::{dma::SpiDma, Address, Command, Spi}, + HalfDuplexMode, + SpiDataMode, + SpiMode, + }, + system::SystemControl, + Blocking, +}; use hil_test as _; +cfg_if::cfg_if! { + if #[cfg(any( + feature = "esp32", + ))] { + use esp_hal::dma::Spi2DmaChannel as DmaChannel0; + } else { + use esp_hal::dma::DmaChannel0; + } +} + +struct Context { + spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>, + pcnt_unit: Unit<'static, 0>, + mosi_mirror: GpioPin<3>, +} + #[cfg(test)] #[embedded_test::tests] mod tests { - use esp_hal::{ - clock::ClockControl, - dma::{Dma, DmaPriority, DmaTxBuf}, - dma_buffers, - gpio::{Io, Pull}, - pcnt::{ - channel::{EdgeMode, PcntInputConfig, PcntSource}, - Pcnt, - }, - peripherals::Peripherals, - prelude::_fugit_RateExtU32, - spi::{ - master::{Address, Command, Spi}, - SpiDataMode, - SpiMode, - }, - system::SystemControl, - }; + use defmt::assert_eq; - #[init] - fn init() {} - - #[test] - #[timeout(3)] - fn test_spi_writes_are_correctly_by_pcnt() { - const DMA_BUFFER_SIZE: usize = 4; + use super::*; + #[init] + fn init() -> Context { let peripherals = Peripherals::take(); let system = SystemControl::new(peripherals.SYSTEM); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pcnt = Pcnt::new(peripherals.PCNT); - let dma = Dma::new(peripherals.DMA); - let sclk = io.pins.gpio0; let mosi = io.pins.gpio2; let mosi_mirror = io.pins.gpio3; - #[cfg(any(feature = "esp32", feature = "esp32s2"))] - let dma_channel = dma.spi2channel; - #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] - let dma_channel = dma.channel0; + let pcnt = Pcnt::new(peripherals.PCNT); + let dma = Dma::new(peripherals.DMA); - let (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0); - let mut dma_tx_buf = DmaTxBuf::new(descriptors, buffer).unwrap(); + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + let dma_channel = dma.spi2channel; + } else { + let dma_channel = dma.channel0; + } + } - let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) + let spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks) .with_sck(sclk) .with_mosi(mosi) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); - let unit = pcnt.unit0; - unit.channel0.set_edge_signal(PcntSource::from_pin( + Context { + spi, mosi_mirror, + pcnt_unit: pcnt.unit0, + } + } + + #[test] + #[timeout(3)] + fn test_spi_writes_are_correctly_by_pcnt(ctx: Context) { + const DMA_BUFFER_SIZE: usize = 4; + + let (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0); + let mut dma_tx_buf = DmaTxBuf::new(descriptors, buffer).unwrap(); + + let unit = ctx.pcnt_unit; + let mut spi = ctx.spi; + + unit.channel0.set_edge_signal(PcntSource::from_pin( + ctx.mosi_mirror, PcntInputConfig { pull: Pull::Down }, )); unit.channel0 From d698140b3e7c81b4316229977b161ebf703c68fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 23 Aug 2024 19:05:52 +0200 Subject: [PATCH 3/5] Separate out PCNT tests --- hil-test/Cargo.toml | 4 + hil-test/tests/spi_full_duplex_dma.rs | 161 +----------------- hil-test/tests/spi_full_duplex_dma_pcnt.rs | 179 +++++++++++++++++++++ 3 files changed, 186 insertions(+), 158 deletions(-) create mode 100644 hil-test/tests/spi_full_duplex_dma_pcnt.rs diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index fad3a4f8f10..4fe49baa8ad 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -79,6 +79,10 @@ harness = false name = "spi_full_duplex_dma_async" harness = false +[[test]] +name = "spi_full_duplex_dma_pcnt" +harness = false + [[test]] name = "spi_half_duplex_read" harness = false diff --git a/hil-test/tests/spi_full_duplex_dma.rs b/hil-test/tests/spi_full_duplex_dma.rs index 7a61e6c54db..b7dc9a9e1fd 100644 --- a/hil-test/tests/spi_full_duplex_dma.rs +++ b/hil-test/tests/spi_full_duplex_dma.rs @@ -6,14 +6,6 @@ //! MOSI GPIO3 //! CS GPIO8 //! -//! Only for test_dma_read_dma_write_pcnt and test_dma_read_dma_transfer_pcnt -//! tests: -//! PCNT GPIO2 -//! OUTPUT GPIO5 (helper to keep MISO LOW) -//! -//! The idea of using PCNT (input) here is to connect MOSI to it and count the -//! edges of whatever SPI writes (in this test case 3 pos edges). -//! //! Connect MISO (GPIO2) and MOSI (GPIO3) pins. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s3 @@ -36,20 +28,6 @@ use esp_hal::{ system::SystemControl, Blocking, }; -#[cfg(any( - feature = "esp32", - feature = "esp32c6", - feature = "esp32h2", - feature = "esp32s3" -))] -use esp_hal::{ - gpio::{GpioPin, Level, Output, Pull}, - pcnt::{ - channel::{EdgeMode, PcntInputConfig, PcntSource}, - unit::Unit, - Pcnt, - }, -}; use hil_test as _; cfg_if::cfg_if! { @@ -62,24 +40,8 @@ cfg_if::cfg_if! { } } -cfg_if::cfg_if! { - if #[cfg(any( - feature = "esp32", - feature = "esp32c6", - feature = "esp32h2", - feature = "esp32s3" - ))] { - struct Context { - spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>, - pcnt_unit: Unit<'static, 0>, - out_pin: Output<'static, GpioPin<5>>, - mosi_mirror: GpioPin<2>, - } - } else { - struct Context { - spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>, - } - } +struct Context { + spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>, } #[cfg(test)] @@ -115,39 +77,7 @@ mod tests { .with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs)) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); - #[cfg(any( - feature = "esp32", - feature = "esp32c6", - feature = "esp32h2", - feature = "esp32s3" - ))] - let pcnt = Pcnt::new(peripherals.PCNT); - - cfg_if::cfg_if! { - if #[cfg(any( - feature = "esp32", - feature = "esp32c6", - feature = "esp32h2", - feature = "esp32s3" - ))] { - - let mut out_pin = Output::new(io.pins.gpio5, Level::Low); - out_pin.set_low(); - assert_eq!(out_pin.is_set_low(), true); - let mosi_mirror = io.pins.gpio2; - - Context { - spi, - pcnt_unit: pcnt.unit0, - out_pin, - mosi_mirror, - } - } else { - Context { - spi - } - } - } + Context { spi } } #[test] @@ -208,91 +138,6 @@ mod tests { assert_eq!(dma_tx_buf.as_slice(), dma_rx_buf.as_slice()); } - #[test] - #[timeout(3)] - #[cfg(any( - feature = "esp32", - feature = "esp32c6", - feature = "esp32h2", - feature = "esp32s3" - ))] - fn test_dma_read_dma_write_pcnt(ctx: Context) { - const DMA_BUFFER_SIZE: usize = 5; - let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); - let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - - let unit = ctx.pcnt_unit; - let mut spi = ctx.spi; - - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); - unit.channel0 - .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); - - // Fill the buffer where each byte has 3 pos edges. - dma_tx_buf.as_mut_slice().fill(0b0110_1010); - - assert_eq!(ctx.out_pin.is_set_low(), true); - - for i in 1..4 { - dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); - let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap(); - (spi, dma_rx_buf) = transfer.wait(); - assert_eq!(dma_rx_buf.as_slice(), &[0, 0, 0, 0, 0]); - - let transfer = spi.dma_write(dma_tx_buf).map_err(|e| e.0).unwrap(); - (spi, dma_tx_buf) = transfer.wait(); - assert_eq!(unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); - } - } - - #[test] - #[timeout(3)] - #[cfg(any( - feature = "esp32", - feature = "esp32c6", - feature = "esp32h2", - feature = "esp32s3" - ))] - fn test_dma_read_dma_transfer_pcnt(ctx: Context) { - const DMA_BUFFER_SIZE: usize = 5; - let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); - let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); - let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); - - let unit = ctx.pcnt_unit; - let mut spi = ctx.spi; - - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); - unit.channel0 - .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); - - // Fill the buffer where each byte has 3 pos edges. - dma_tx_buf.as_mut_slice().fill(0b0110_1010); - - assert_eq!(ctx.out_pin.is_set_low(), true); - - for i in 1..4 { - dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); - let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap(); - (spi, dma_rx_buf) = transfer.wait(); - assert_eq!(dma_rx_buf.as_slice(), &[0, 0, 0, 0, 0]); - - let transfer = spi - .dma_transfer(dma_tx_buf, dma_rx_buf) - .map_err(|e| e.0) - .unwrap(); - (spi, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); - assert_eq!(unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); - } - } - #[test] #[timeout(3)] fn test_dma_bus_symmetric_transfer(ctx: Context) { diff --git a/hil-test/tests/spi_full_duplex_dma_pcnt.rs b/hil-test/tests/spi_full_duplex_dma_pcnt.rs new file mode 100644 index 00000000000..314f2ccec48 --- /dev/null +++ b/hil-test/tests/spi_full_duplex_dma_pcnt.rs @@ -0,0 +1,179 @@ +//! SPI Full Duplex DMA ASYNC Test with PCNT readback. +//! +//! Folowing pins are used: +//! SCLK GPIO0 +//! MOSI GPIO3 +//! CS GPIO8 +//! PCNT GPIO2 +//! OUTPUT GPIO5 (helper to keep MISO LOW) +//! +//! The idea of using PCNT (input) here is to connect MOSI to it and count the +//! edges of whatever SPI writes (in this test case 3 pos edges). +//! +//! Connect MISO (GPIO2) and MOSI (GPIO3) pins. + +//% CHIPS: esp32 esp32c6 esp32h2 esp32s3 + +#![no_std] +#![no_main] + +use esp_hal::{ + clock::ClockControl, + dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, + dma_buffers, + gpio::{GpioPin, Io, Level, Output, Pull}, + pcnt::{ + channel::{EdgeMode, PcntInputConfig, PcntSource}, + unit::Unit, + Pcnt, + }, + peripherals::{Peripherals, SPI2}, + prelude::*, + spi::{ + master::{dma::SpiDma, Spi}, + FullDuplexMode, + SpiMode, + }, + system::SystemControl, + Blocking, +}; +use hil_test as _; + +cfg_if::cfg_if! { + if #[cfg(any( + feature = "esp32", + ))] { + use esp_hal::dma::Spi2DmaChannel as DmaChannel0; + } else { + use esp_hal::dma::DmaChannel0; + } +} + +struct Context { + spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>, + pcnt_unit: Unit<'static, 0>, + out_pin: Output<'static, GpioPin<5>>, + mosi_mirror: GpioPin<2>, +} + +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use defmt::assert_eq; + + use super::*; + + #[init] + fn init() -> Context { + let peripherals = Peripherals::take(); + let system = SystemControl::new(peripherals.SYSTEM); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio0; + let mosi = io.pins.gpio3; + let miso = io.pins.gpio6; + let cs = io.pins.gpio8; + + let dma = Dma::new(peripherals.DMA); + + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + let dma_channel = dma.spi2channel; + } else { + let dma_channel = dma.channel0; + } + } + + 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, DmaPriority::Priority0)); + + let pcnt = Pcnt::new(peripherals.PCNT); + + let mut out_pin = Output::new(io.pins.gpio5, Level::Low); + out_pin.set_low(); + assert_eq!(out_pin.is_set_low(), true); + let mosi_mirror = io.pins.gpio2; + + Context { + spi, + pcnt_unit: pcnt.unit0, + out_pin, + mosi_mirror, + } + } + + #[test] + #[timeout(3)] + fn test_dma_read_dma_write_pcnt(ctx: Context) { + const DMA_BUFFER_SIZE: usize = 5; + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); + let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); + let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); + + let unit = ctx.pcnt_unit; + let mut spi = ctx.spi; + + unit.channel0.set_edge_signal(PcntSource::from_pin( + ctx.mosi_mirror, + PcntInputConfig { pull: Pull::Down }, + )); + unit.channel0 + .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); + + // Fill the buffer where each byte has 3 pos edges. + dma_tx_buf.as_mut_slice().fill(0b0110_1010); + + assert_eq!(ctx.out_pin.is_set_low(), true); + + for i in 1..4 { + dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); + let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap(); + (spi, dma_rx_buf) = transfer.wait(); + assert_eq!(dma_rx_buf.as_slice(), &[0, 0, 0, 0, 0]); + + let transfer = spi.dma_write(dma_tx_buf).map_err(|e| e.0).unwrap(); + (spi, dma_tx_buf) = transfer.wait(); + assert_eq!(unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); + } + } + + #[test] + #[timeout(3)] + fn test_dma_read_dma_transfer_pcnt(ctx: Context) { + const DMA_BUFFER_SIZE: usize = 5; + let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); + let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); + let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); + + let unit = ctx.pcnt_unit; + let mut spi = ctx.spi; + + unit.channel0.set_edge_signal(PcntSource::from_pin( + ctx.mosi_mirror, + PcntInputConfig { pull: Pull::Down }, + )); + unit.channel0 + .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); + + // Fill the buffer where each byte has 3 pos edges. + dma_tx_buf.as_mut_slice().fill(0b0110_1010); + + assert_eq!(ctx.out_pin.is_set_low(), true); + + for i in 1..4 { + dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); + let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap(); + (spi, dma_rx_buf) = transfer.wait(); + assert_eq!(dma_rx_buf.as_slice(), &[0, 0, 0, 0, 0]); + + let transfer = spi + .dma_transfer(dma_tx_buf, dma_rx_buf) + .map_err(|e| e.0) + .unwrap(); + (spi, (dma_tx_buf, dma_rx_buf)) = transfer.wait(); + assert_eq!(unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _); + } + } +} From 49a3864a6c48998a7be7560678511a1276a6d5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 23 Aug 2024 19:28:04 +0200 Subject: [PATCH 4/5] Re-enable test on S3 --- hil-test/tests/spi_full_duplex_dma.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/hil-test/tests/spi_full_duplex_dma.rs b/hil-test/tests/spi_full_duplex_dma.rs index b7dc9a9e1fd..93099d87818 100644 --- a/hil-test/tests/spi_full_duplex_dma.rs +++ b/hil-test/tests/spi_full_duplex_dma.rs @@ -100,8 +100,6 @@ mod tests { #[test] #[timeout(3)] - // S3 is disabled due to https://github.com/esp-rs/esp-hal/issues/1524#issuecomment-2255306292 - #[cfg(not(feature = "esp32s3"))] fn test_asymmetric_dma_transfer(ctx: Context) { let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4, 2); let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); From fe09462b92419e48de5b53142f84227fe01010f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 23 Aug 2024 19:41:04 +0200 Subject: [PATCH 5/5] Re-enable some S2 tests --- hil-test/tests/spi_full_duplex_dma.rs | 5 +++-- hil-test/tests/spi_full_duplex_dma_async.rs | 3 ++- hil-test/tests/spi_full_duplex_dma_pcnt.rs | 3 ++- hil-test/tests/spi_half_duplex_read.rs | 5 +++-- hil-test/tests/spi_half_duplex_write.rs | 5 +++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/hil-test/tests/spi_full_duplex_dma.rs b/hil-test/tests/spi_full_duplex_dma.rs index 93099d87818..3988d59f249 100644 --- a/hil-test/tests/spi_full_duplex_dma.rs +++ b/hil-test/tests/spi_full_duplex_dma.rs @@ -8,7 +8,7 @@ //! //! Connect MISO (GPIO2) and MOSI (GPIO3) pins. -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s3 +//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 #![no_std] #![no_main] @@ -33,6 +33,7 @@ use hil_test as _; cfg_if::cfg_if! { if #[cfg(any( feature = "esp32", + feature = "esp32s2", ))] { use esp_hal::dma::Spi2DmaChannel as DmaChannel0; } else { @@ -66,7 +67,7 @@ mod tests { let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { - if #[cfg(feature = "esp32")] { + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { let dma_channel = dma.spi2channel; } else { let dma_channel = dma.channel0; diff --git a/hil-test/tests/spi_full_duplex_dma_async.rs b/hil-test/tests/spi_full_duplex_dma_async.rs index 5dad92a461f..cdc2aa02a2d 100644 --- a/hil-test/tests/spi_full_duplex_dma_async.rs +++ b/hil-test/tests/spi_full_duplex_dma_async.rs @@ -43,6 +43,7 @@ use hil_test as _; cfg_if::cfg_if! { if #[cfg(any( feature = "esp32", + feature = "esp32s2", ))] { use esp_hal::dma::Spi2DmaChannel as DmaChannel0; } else { @@ -87,7 +88,7 @@ mod tests { let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { - if #[cfg(feature = "esp32")] { + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { let dma_channel = dma.spi2channel; } else { let dma_channel = dma.channel0; diff --git a/hil-test/tests/spi_full_duplex_dma_pcnt.rs b/hil-test/tests/spi_full_duplex_dma_pcnt.rs index 314f2ccec48..e304784240d 100644 --- a/hil-test/tests/spi_full_duplex_dma_pcnt.rs +++ b/hil-test/tests/spi_full_duplex_dma_pcnt.rs @@ -42,6 +42,7 @@ use hil_test as _; cfg_if::cfg_if! { if #[cfg(any( feature = "esp32", + feature = "esp32s2", ))] { use esp_hal::dma::Spi2DmaChannel as DmaChannel0; } else { @@ -78,7 +79,7 @@ mod tests { let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { - if #[cfg(feature = "esp32")] { + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { let dma_channel = dma.spi2channel; } else { let dma_channel = dma.channel0; diff --git a/hil-test/tests/spi_half_duplex_read.rs b/hil-test/tests/spi_half_duplex_read.rs index 299eceec2b7..ab392a520b3 100644 --- a/hil-test/tests/spi_half_duplex_read.rs +++ b/hil-test/tests/spi_half_duplex_read.rs @@ -8,7 +8,7 @@ //! //! Connect MISO (GPIO2) and GPIO (GPIO3) pins. -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s3 +//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 #![no_std] #![no_main] @@ -34,6 +34,7 @@ use hil_test as _; cfg_if::cfg_if! { if #[cfg(any( feature = "esp32", + feature = "esp32s2", ))] { use esp_hal::dma::Spi2DmaChannel as DmaChannel0; } else { @@ -68,7 +69,7 @@ mod tests { let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { - if #[cfg(feature = "esp32")] { + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { let dma_channel = dma.spi2channel; } else { let dma_channel = dma.channel0; diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index 33ac182eec5..1acd34b17ce 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -8,7 +8,7 @@ //! //! Connect MOSI (GPIO2) and PCNT (GPIO3) pins. -//% CHIPS: esp32 esp32c6 esp32h2 esp32s3 +//% CHIPS: esp32 esp32c6 esp32h2 esp32s2 esp32s3 #![no_std] #![no_main] @@ -39,6 +39,7 @@ use hil_test as _; cfg_if::cfg_if! { if #[cfg(any( feature = "esp32", + feature = "esp32s2", ))] { use esp_hal::dma::Spi2DmaChannel as DmaChannel0; } else { @@ -74,7 +75,7 @@ mod tests { let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { - if #[cfg(feature = "esp32")] { + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { let dma_channel = dma.spi2channel; } else { let dma_channel = dma.channel0;