mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-10-02 14:44:42 +00:00
Refactor SPI tests & re-enable S3 and some S2 (#1990)
* Deduplicate spi_full_duplex_dma_async * Refactor SPI tests * Separate out PCNT tests * Re-enable test on S3 * Re-enable some S2 tests
This commit is contained in:
parent
d0f98b6c1f
commit
e1697310f6
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -6,349 +6,145 @@
|
||||
//! 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
|
||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
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,
|
||||
};
|
||||
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: 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(any(feature = "esp32", feature = "esp32s2"))] {
|
||||
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));
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
#[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() {
|
||||
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());
|
||||
}
|
||||
|
||||
#[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 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 = 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);
|
||||
|
||||
// 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);
|
||||
|
||||
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() {
|
||||
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 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 = 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);
|
||||
|
||||
// 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);
|
||||
|
||||
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() {
|
||||
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 +156,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 +173,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];
|
||||
|
@ -23,33 +23,53 @@
|
||||
use embedded_hal_async::spi::SpiBus;
|
||||
use esp_hal::{
|
||||
clock::ClockControl,
|
||||
dma::{Dma, DmaPriority},
|
||||
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
|
||||
dma_buffers,
|
||||
gpio::{Io, Level, Output, Pull},
|
||||
gpio::{GpioPin, Io, Level, Output, Pull},
|
||||
pcnt::{
|
||||
channel::{EdgeMode, PcntInputConfig, PcntSource},
|
||||
unit::Unit,
|
||||
Pcnt,
|
||||
},
|
||||
peripherals::Peripherals,
|
||||
peripherals::{Peripherals, SPI2},
|
||||
prelude::*,
|
||||
spi::{master::Spi, SpiMode},
|
||||
spi::{
|
||||
master::{dma::asynch::SpiDmaAsyncBus, Spi},
|
||||
SpiMode,
|
||||
},
|
||||
system::SystemControl,
|
||||
};
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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::*;
|
||||
|
||||
#[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();
|
||||
@ -68,88 +88,40 @@ 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(any(feature = "esp32", feature = "esp32s2"))] {
|
||||
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,
|
||||
PcntInputConfig { pull: Pull::Down },
|
||||
));
|
||||
unit.channel0
|
||||
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
|
||||
|
||||
let mut receive = [0; DMA_BUFFER_SIZE];
|
||||
|
||||
// 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);
|
||||
|
||||
for i in 1..4 {
|
||||
receive.copy_from_slice(&[5, 5, 5, 5, 5]);
|
||||
SpiBus::read(&mut 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 _);
|
||||
}
|
||||
}
|
||||
|
||||
#[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_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];
|
||||
@ -157,17 +129,45 @@ 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::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(mut ctx: Context) {
|
||||
ctx.pcnt_unit.channel0.set_edge_signal(PcntSource::from_pin(
|
||||
ctx.mosi_mirror,
|
||||
PcntInputConfig { pull: Pull::Down },
|
||||
));
|
||||
ctx.pcnt_unit
|
||||
.channel0
|
||||
.set_input_mode(EdgeMode::Hold, EdgeMode::Increment);
|
||||
|
||||
let mut receive = [0; DMA_BUFFER_SIZE];
|
||||
|
||||
// Fill the buffer where each byte has 3 pos edges.
|
||||
let transmit = [0b0110_1010; DMA_BUFFER_SIZE];
|
||||
|
||||
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 ctx.spi, &mut receive).await.unwrap();
|
||||
assert_eq!(receive, [0, 0, 0, 0, 0]);
|
||||
|
||||
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 _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
180
hil-test/tests/spi_full_duplex_dma_pcnt.rs
Normal file
180
hil-test/tests/spi_full_duplex_dma_pcnt.rs
Normal file
@ -0,0 +1,180 @@
|
||||
//! 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",
|
||||
feature = "esp32s2",
|
||||
))] {
|
||||
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(any(feature = "esp32", feature = "esp32s2"))] {
|
||||
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 _);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,39 +8,54 @@
|
||||
//!
|
||||
//! 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]
|
||||
|
||||
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",
|
||||
feature = "esp32s2",
|
||||
))] {
|
||||
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,
|
||||
};
|
||||
use defmt::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[init]
|
||||
fn init() {}
|
||||
|
||||
#[test]
|
||||
#[timeout(3)]
|
||||
fn test_spi_reads_correctly_from_gpio_pin() {
|
||||
const DMA_BUFFER_SIZE: usize = 4;
|
||||
|
||||
fn init() -> Context {
|
||||
let peripherals = Peripherals::take();
|
||||
let system = SystemControl::new(peripherals.SYSTEM);
|
||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||
@ -49,25 +64,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;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(feature = "esp32", feature = "esp32s2"))] {
|
||||
let dma_channel = dma.spi2channel;
|
||||
} else {
|
||||
let dma_channel = dma.channel0;
|
||||
}
|
||||
}
|
||||
|
||||
let (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0);
|
||||
let mut dma_rx_buf = DmaRxBuf::new(descriptors, buffer).unwrap();
|
||||
|
||||
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 +112,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(
|
||||
|
@ -8,71 +8,105 @@
|
||||
//!
|
||||
//! Connect MOSI (GPIO2) and PCNT (GPIO3) pins.
|
||||
|
||||
//% CHIPS: esp32 esp32c6 esp32h2 esp32s3
|
||||
//% CHIPS: esp32 esp32c6 esp32h2 esp32s2 esp32s3
|
||||
|
||||
#![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",
|
||||
feature = "esp32s2",
|
||||
))] {
|
||||
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;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[init]
|
||||
fn init() {}
|
||||
|
||||
#[test]
|
||||
#[timeout(3)]
|
||||
fn test_spi_writes_are_correctly_by_pcnt() {
|
||||
const DMA_BUFFER_SIZE: usize = 4;
|
||||
|
||||
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(any(feature = "esp32", feature = "esp32s2"))] {
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user