Skip to content

Commit 2dc285a

Browse files
authored
QSPI tests (#2015)
* Add QSPI tests * Simplify * Add qspi_write_read test
1 parent 8e6411b commit 2dc285a

File tree

4 files changed

+671
-0
lines changed

4 files changed

+671
-0
lines changed

hil-test/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ harness = false
6767
name = "lcd_cam_i8080_async"
6868
harness = false
6969

70+
[[test]]
71+
name = "qspi_read"
72+
harness = false
73+
74+
[[test]]
75+
name = "qspi_write"
76+
harness = false
77+
78+
[[test]]
79+
name = "qspi_write_read"
80+
harness = false
81+
7082
[[test]]
7183
name = "spi_full_duplex"
7284
harness = false

hil-test/tests/qspi_read.rs

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
//! QSPI Read Test
2+
//!
3+
//! Following pins are used:
4+
//! MISO GPIO2
5+
//!
6+
//! GPIO GPIO3
7+
//!
8+
//! Connect MISO (GPIO2) and GPIO (GPIO3) pins.
9+
10+
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
11+
12+
#![no_std]
13+
#![no_main]
14+
15+
use esp_hal::{
16+
clock::{ClockControl, Clocks},
17+
dma::{Channel, Dma, DmaPriority, DmaRxBuf},
18+
dma_buffers,
19+
gpio::{GpioPin, Io, Level, Output},
20+
peripherals::Peripherals,
21+
prelude::*,
22+
spi::{
23+
master::{Address, Command, Spi, SpiDma},
24+
HalfDuplexMode,
25+
SpiDataMode,
26+
SpiMode,
27+
},
28+
system::SystemControl,
29+
Blocking,
30+
};
31+
use hil_test as _;
32+
33+
cfg_if::cfg_if! {
34+
if #[cfg(any(
35+
feature = "esp32",
36+
feature = "esp32s2",
37+
))] {
38+
use esp_hal::dma::Spi2DmaChannel as DmaChannel0;
39+
} else {
40+
use esp_hal::dma::DmaChannel0;
41+
}
42+
}
43+
44+
struct Context {
45+
spi: esp_hal::peripherals::SPI2,
46+
dma_channel: Channel<'static, DmaChannel0, Blocking>,
47+
miso: esp_hal::gpio::GpioPin<2>,
48+
miso_mirror: Output<'static, GpioPin<3>>,
49+
clocks: Clocks<'static>,
50+
}
51+
52+
fn execute(
53+
mut spi: SpiDma<'static, esp_hal::peripherals::SPI2, DmaChannel0, HalfDuplexMode, Blocking>,
54+
mut miso_mirror: Output<'static, GpioPin<3>>,
55+
wanted: u8,
56+
) {
57+
const DMA_BUFFER_SIZE: usize = 4;
58+
59+
let (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0);
60+
let mut dma_rx_buf = DmaRxBuf::new(descriptors, buffer).unwrap();
61+
62+
miso_mirror.set_low();
63+
64+
let transfer = spi
65+
.read(
66+
SpiDataMode::Quad,
67+
Command::None,
68+
Address::None,
69+
0,
70+
dma_rx_buf,
71+
)
72+
.map_err(|e| e.0)
73+
.unwrap();
74+
(spi, dma_rx_buf) = transfer.wait();
75+
76+
assert_eq!(dma_rx_buf.as_slice(), &[wanted; DMA_BUFFER_SIZE]);
77+
78+
// SPI should read all '1's
79+
miso_mirror.set_high();
80+
81+
let transfer = spi
82+
.read(
83+
SpiDataMode::Quad,
84+
Command::None,
85+
Address::None,
86+
0,
87+
dma_rx_buf,
88+
)
89+
.map_err(|e| e.0)
90+
.unwrap();
91+
92+
(_, dma_rx_buf) = transfer.wait();
93+
94+
assert_eq!(dma_rx_buf.as_slice(), &[0xFF; DMA_BUFFER_SIZE]);
95+
}
96+
97+
#[cfg(test)]
98+
#[embedded_test::tests]
99+
mod tests {
100+
use super::*;
101+
102+
#[init]
103+
fn init() -> Context {
104+
let peripherals = Peripherals::take();
105+
let system = SystemControl::new(peripherals.SYSTEM);
106+
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
107+
108+
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
109+
let miso = io.pins.gpio2;
110+
111+
let miso_mirror = Output::new(io.pins.gpio3, Level::High);
112+
113+
let dma = Dma::new(peripherals.DMA);
114+
115+
cfg_if::cfg_if! {
116+
if #[cfg(any(feature = "esp32", feature = "esp32s2"))] {
117+
let dma_channel = dma.spi2channel;
118+
} else {
119+
let dma_channel = dma.channel0;
120+
}
121+
}
122+
123+
let dma_channel = dma_channel.configure(false, DmaPriority::Priority0);
124+
125+
Context {
126+
spi: peripherals.SPI2,
127+
dma_channel,
128+
miso,
129+
miso_mirror,
130+
clocks,
131+
}
132+
}
133+
134+
#[test]
135+
#[timeout(3)]
136+
fn test_spi_reads_correctly_from_gpio_pin_0(ctx: Context) {
137+
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
138+
.with_pins(
139+
esp_hal::gpio::NO_PIN,
140+
Some(ctx.miso),
141+
esp_hal::gpio::NO_PIN,
142+
esp_hal::gpio::NO_PIN,
143+
esp_hal::gpio::NO_PIN,
144+
esp_hal::gpio::NO_PIN,
145+
)
146+
.with_dma(ctx.dma_channel);
147+
148+
// SPI should read '0b11101110'
149+
super::execute(spi, ctx.miso_mirror, 238);
150+
}
151+
152+
#[test]
153+
#[timeout(3)]
154+
fn test_spi_reads_correctly_from_gpio_pin_1(ctx: Context) {
155+
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
156+
.with_pins(
157+
esp_hal::gpio::NO_PIN,
158+
esp_hal::gpio::NO_PIN,
159+
Some(ctx.miso),
160+
esp_hal::gpio::NO_PIN,
161+
esp_hal::gpio::NO_PIN,
162+
esp_hal::gpio::NO_PIN,
163+
)
164+
.with_dma(ctx.dma_channel);
165+
166+
// SPI should read '0b11011101'
167+
super::execute(spi, ctx.miso_mirror, 221);
168+
}
169+
170+
#[test]
171+
#[timeout(3)]
172+
fn test_spi_reads_correctly_from_gpio_pin_2(ctx: Context) {
173+
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
174+
.with_pins(
175+
esp_hal::gpio::NO_PIN,
176+
esp_hal::gpio::NO_PIN,
177+
esp_hal::gpio::NO_PIN,
178+
Some(ctx.miso),
179+
esp_hal::gpio::NO_PIN,
180+
esp_hal::gpio::NO_PIN,
181+
)
182+
.with_dma(ctx.dma_channel);
183+
184+
// SPI should read '0b10111011'
185+
super::execute(spi, ctx.miso_mirror, 187);
186+
}
187+
188+
#[test]
189+
#[timeout(3)]
190+
fn test_spi_reads_correctly_from_gpio_pin_3(ctx: Context) {
191+
let spi = Spi::new_half_duplex(ctx.spi, 100.kHz(), SpiMode::Mode0, &ctx.clocks)
192+
.with_pins(
193+
esp_hal::gpio::NO_PIN,
194+
esp_hal::gpio::NO_PIN,
195+
esp_hal::gpio::NO_PIN,
196+
esp_hal::gpio::NO_PIN,
197+
Some(ctx.miso),
198+
esp_hal::gpio::NO_PIN,
199+
)
200+
.with_dma(ctx.dma_channel);
201+
202+
// SPI should read '0b01110111'
203+
super::execute(spi, ctx.miso_mirror, 119);
204+
}
205+
}

0 commit comments

Comments
 (0)