Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more SPI DMA (full-duplex) HIL tests (blocking and async) #1952

Merged
merged 3 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions hil-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ harness = false
name = "spi_full_duplex_dma"
harness = false

[[test]]
name = "spi_full_duplex_dma_async"
harness = false

[[test]]
name = "spi_half_duplex_read"
harness = false
Expand Down
172 changes: 167 additions & 5 deletions hil-test/tests/spi_full_duplex_dma.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
//! SPI Full Duplex DMA Test
//! SPI Full Duplex DMA ASYNC Test
//!
//! Folowing pins are used:
//! SCLK GPIO0
//! MISO GPIO2
//! 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
Expand Down Expand Up @@ -68,7 +76,6 @@ mod tests {
rx_descriptors,
);

// DMA buffer require a static life-time
let mut send = tx_buffer;
let mut receive = rx_buffer;

Expand Down Expand Up @@ -111,7 +118,6 @@ mod tests {
rx_descriptors,
);

// DMA buffer require a static life-time
let mut send = tx_buffer;
let mut receive = rx_buffer;

Expand Down Expand Up @@ -154,7 +160,6 @@ mod tests {
rx_descriptors,
);

// DMA buffer require a static life-time
let mut send = tx_buffer;
let mut receive = rx_buffer;

Expand Down Expand Up @@ -305,7 +310,6 @@ mod tests {
rx_descriptors,
);

// DMA buffer require a static life-time
let send = tx_buffer;
let receive = rx_buffer;

Expand All @@ -318,4 +322,162 @@ mod tests {
let (_, send, receive) = transfer.wait().unwrap();
assert_eq!(send, receive);
}

#[test]
#[timeout(3)]
#[cfg(any(
feature = "esp32",
feature = "esp32c6",
feature = "esp32h2",
feature = "esp32s3"
))]
fn test_dma_read_dma_write_pcnt() {
use esp_hal::{
gpio::{Level, Output, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
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 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),
tx_descriptors,
rx_descriptors,
);

let unit = pcnt.unit0;
unit.channel0.set_edge_signal(PcntSource::from_pin(
mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);

let mut receive = rx_buffer;

// Fill the buffer where each byte has 3 pos edges.
tx_buffer.fill(0b0110_1010);

assert_eq!(out_pin.is_set_low(), true);

for i in 1..4 {
receive.copy_from_slice(&[5, 5, 5, 5, 5]);
let transfer = spi.dma_read(&mut receive).unwrap();
transfer.wait().unwrap();
assert_eq!(receive, &[0, 0, 0, 0, 0]);

let transfer = spi.dma_write(&tx_buffer).unwrap();
transfer.wait().unwrap();
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() {
use esp_hal::{
gpio::{Level, Output, Pull},
pcnt::{
channel::{EdgeMode, PcntInputConfig, PcntSource},
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 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),
tx_descriptors,
rx_descriptors,
);

let unit = pcnt.unit0;
JurajSadel marked this conversation as resolved.
Show resolved Hide resolved
unit.channel0.set_edge_signal(PcntSource::from_pin(
mosi_mirror,
PcntInputConfig { pull: Pull::Down },
));
unit.channel0
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);

let mut receive = rx_buffer;

// Fill the buffer where each byte has 3 pos edges.
tx_buffer.fill(0b0110_1010);

assert_eq!(out_pin.is_set_low(), true);

for i in 1..4 {
receive.copy_from_slice(&[5, 5, 5, 5, 5]);
let transfer = spi.dma_read(&mut receive).unwrap();
transfer.wait().unwrap();
assert_eq!(receive, &[0, 0, 0, 0, 0]);

let transfer = spi.dma_transfer(&tx_buffer, &mut receive).unwrap();
transfer.wait().unwrap();
assert_eq!(unit.get_value(), (i * 3 * DMA_BUFFER_SIZE) as _);
}
}
}
Loading