Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Add qspi_write_read test
  • Loading branch information
bjoernQ committed Aug 28, 2024
commit 61d6b0f3900e09c45bac0017cdd4b5758cb16ebe
4 changes: 4 additions & 0 deletions hil-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ harness = false
name = "qspi_write"
harness = false

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

[[test]]
name = "spi_full_duplex"
harness = false
Expand Down
202 changes: 202 additions & 0 deletions hil-test/tests/qspi_write_read.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
//! QSPI Write + Read Test
//!
//! Make sure issue #1860 doesn't affect us
//!
//! Following pins are used:
//! MOSI/MISO GPIO2
//!
//! GPIO GPIO3
//!
//! Connect MOSI/MISO (GPIO2) and GPIO (GPIO3) pins.

//% CHIPS: esp32 esp32c6 esp32h2 esp32s2 esp32s3

#![no_std]
#![no_main]

use esp_hal::{
clock::{ClockControl, Clocks},
dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{GpioPin, Io, Level, Output},
peripherals::Peripherals,
prelude::*,
spi::{
master::{Address, Command, Spi, SpiDma},
HalfDuplexMode,
SpiDataMode,
SpiMode,
},
system::SystemControl,
Blocking,
};
use hil_test as _;

cfg_if::cfg_if! {
if #[cfg(any(
feature = "esp32",
feature = "esp32s2",
))] {
use esp_hal::dma::Spi2DmaChannel as DmaChannel0;
} else {
use esp_hal::dma::DmaChannel0;
}
}

struct Context {
spi: esp_hal::peripherals::SPI2,
dma_channel: Channel<'static, DmaChannel0, Blocking>,
mosi: esp_hal::gpio::GpioPin<2>,
mosi_mirror: Output<'static, GpioPin<3>>,
clocks: Clocks<'static>,
}

fn execute(
mut spi: SpiDma<'static, esp_hal::peripherals::SPI2, DmaChannel0, HalfDuplexMode, Blocking>,
mut mosi_mirror: Output<'static, GpioPin<3>>,
wanted: u8,
) {
const DMA_BUFFER_SIZE: usize = 4;

let (buffer, descriptors, rx_buffer, rx_descriptors) =
dma_buffers!(DMA_BUFFER_SIZE, DMA_BUFFER_SIZE);
let mut dma_tx_buf = DmaTxBuf::new(descriptors, buffer).unwrap();
let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();

dma_tx_buf.fill(&[0xff; DMA_BUFFER_SIZE]);

let transfer = spi
.write(
SpiDataMode::Quad,
Command::Command8(wanted as u16, SpiDataMode::Quad),
Address::Address24(
wanted as u32 | (wanted as u32) << 8 | (wanted as u32) << 16,
SpiDataMode::Quad,
),
0,
dma_tx_buf,
)
.map_err(|e| e.0)
.unwrap();
(spi, _) = transfer.wait();

mosi_mirror.set_low();

let transfer = spi
.read(
SpiDataMode::Quad,
Command::None,
Address::None,
0,
dma_rx_buf,
)
.map_err(|e| e.0)
.unwrap();
(_, dma_rx_buf) = transfer.wait();
assert_eq!(dma_rx_buf.as_slice(), &[wanted; DMA_BUFFER_SIZE]);
}

#[cfg(test)]
#[embedded_test::tests]
mod tests {
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 mosi = io.pins.gpio2;
let mosi_mirror = Output::new(io.pins.gpio3, Level::High);

let dma = Dma::new(peripherals.DMA);

cfg_if::cfg_if! {
if #[cfg(any(feature = "esp32", feature = "esp32s2"))] {
let dma_channel = dma.spi2channel;
} else {
let dma_channel = dma.channel0;
}
}

let dma_channel = dma_channel.configure(false, DmaPriority::Priority0);

Context {
spi: peripherals.SPI2,
dma_channel,
mosi,
mosi_mirror,
clocks,
}
}

#[test]
#[timeout(3)]
fn test_spi_writes_correctly_to_pin_0(ctx: Context) {
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
.with_pins(
esp_hal::gpio::NO_PIN,
Some(ctx.mosi),
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
)
.with_dma(ctx.dma_channel);

super::execute(spi, ctx.mosi_mirror, !0b0001_0001);
}

#[test]
#[timeout(3)]
fn test_spi_writes_correctly_to_pin_1(ctx: Context) {
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
.with_pins(
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
Some(ctx.mosi),
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
)
.with_dma(ctx.dma_channel);

super::execute(spi, ctx.mosi_mirror, !0b0010_0010);
}

#[test]
#[timeout(3)]
fn test_spi_writes_correctly_to_pin_2(ctx: Context) {
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
.with_pins(
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
Some(ctx.mosi),
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
)
.with_dma(ctx.dma_channel);

super::execute(spi, ctx.mosi_mirror, !0b0100_0100);
}

#[test]
#[timeout(3)]
fn test_spi_writes_correctly_to_pin_3(ctx: Context) {
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
.with_pins(
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
esp_hal::gpio::NO_PIN,
Some(ctx.mosi),
esp_hal::gpio::NO_PIN,
)
.with_dma(ctx.dma_channel);

super::execute(spi, ctx.mosi_mirror, !0b1000_1000);
}
}