Skip to content

Commit

Permalink
Add async HIL test
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominic Fischer committed Jul 27, 2024
1 parent 0826040 commit 8828e91
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 37 deletions.
76 changes: 39 additions & 37 deletions esp-hal/src/spi/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,7 @@ where

pub mod dma {
use core::{
cell::Cell,
cmp::min,
sync::atomic::{fence, Ordering},
};
Expand Down Expand Up @@ -1046,6 +1047,9 @@ pub mod dma {
dma_buf: Buf,
is_rx: bool,
is_tx: bool,

rx_future_awaited: bool,
tx_future_awaited: bool,
}

impl<'d, T, C, M, DmaMode, Buf> SpiDmaTransfer<'d, T, C, M, DmaMode, Buf>
Expand All @@ -1056,14 +1060,30 @@ pub mod dma {
M: DuplexMode,
DmaMode: Mode,
{
fn new(
spi_dma: SpiDma<'d, T, C, M, DmaMode>,
dma_buf: Buf,
is_rx: bool,
is_tx: bool,
) -> Self {
Self {
spi_dma,
dma_buf,
is_rx,
is_tx,
rx_future_awaited: false,
tx_future_awaited: false,
}
}

pub fn is_done(&self) -> bool {
if self.is_tx && !self.spi_dma.channel.tx.is_done() {
if self.is_tx && !self.tx_future_awaited && !self.spi_dma.channel.tx.is_done() {
return false;
}
if self.spi_dma.spi.busy() {
return false;
}
if self.is_rx {
if self.is_rx && !self.rx_future_awaited {
// If this is an asymmetric transfer and the RX side is smaller, the RX channel
// will never be "done" as it won't have enough descriptors/buffer to receive
// the EOF bit from the SPI. So instead the RX channel will hit
Expand Down Expand Up @@ -1096,14 +1116,16 @@ pub mod dma {
M: DuplexMode,
{
pub async fn wait_for_done(&mut self) {
if self.is_tx {
if self.is_tx && !self.tx_future_awaited {
let _ = DmaTxFuture::new(&mut self.spi_dma.channel.tx).await;
self.tx_future_awaited = true;
}

// As a future enhancement, setup Spi Future in here as well.

if self.is_rx {
if self.is_rx && !self.rx_future_awaited {
let _ = DmaRxFuture::new(&mut self.spi_dma.channel.rx).await;
self.rx_future_awaited = true;
}
}
}
Expand Down Expand Up @@ -1141,12 +1163,7 @@ pub mod dma {
return Err((e, self, buffer));
}

Ok(SpiDmaTransfer {
spi_dma: self,
dma_buf: buffer,
is_tx: true,
is_rx: false,
})
Ok(SpiDmaTransfer::new(self, buffer, true, false))
}

/// Perform a DMA read.
Expand All @@ -1161,7 +1178,7 @@ pub mod dma {
buffer: DmaRxBuf,
) -> Result<SpiDmaTransfer<'d, T, C, M, DmaMode, DmaRxBuf>, (Error, Self, DmaRxBuf)>
{
let bytes_to_read = buffer.capacity();
let bytes_to_read = buffer.len();
if bytes_to_read > MAX_DMA_SIZE {
return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
}
Expand All @@ -1174,12 +1191,7 @@ pub mod dma {
return Err((e, self, buffer));
}

Ok(SpiDmaTransfer {
spi_dma: self,
dma_buf: buffer,
is_tx: false,
is_rx: true,
})
Ok(SpiDmaTransfer::new(self, buffer, false, true))
}

/// Perform a DMA transfer
Expand All @@ -1197,7 +1209,7 @@ pub mod dma {
(Error, Self, DmaTxBuf, DmaRxBuf),
> {
let bytes_to_write = tx_buffer.len();
let bytes_to_read = rx_buffer.capacity();
let bytes_to_read = rx_buffer.len();

if bytes_to_write > MAX_DMA_SIZE || bytes_to_read > MAX_DMA_SIZE {
return Err((
Expand All @@ -1222,12 +1234,12 @@ pub mod dma {
return Err((e, self, tx_buffer, rx_buffer));
}

Ok(SpiDmaTransfer {
spi_dma: self,
dma_buf: (tx_buffer, rx_buffer),
is_tx: true,
is_rx: true,
})
Ok(SpiDmaTransfer::new(
self,
(tx_buffer, rx_buffer),
true,
true,
))
}
}

Expand All @@ -1250,7 +1262,7 @@ pub mod dma {
buffer: DmaRxBuf,
) -> Result<SpiDmaTransfer<'d, T, C, M, DmaMode, DmaRxBuf>, (Error, Self, DmaRxBuf)>
{
let bytes_to_read = buffer.capacity();
let bytes_to_read = buffer.len();
if bytes_to_read > MAX_DMA_SIZE {
return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
}
Expand Down Expand Up @@ -1313,12 +1325,7 @@ pub mod dma {
return Err((e, self, buffer));
}

Ok(SpiDmaTransfer {
spi_dma: self,
dma_buf: buffer,
is_tx: false,
is_rx: true,
})
Ok(SpiDmaTransfer::new(self, buffer, false, true))
}

#[allow(clippy::type_complexity)]
Expand Down Expand Up @@ -1395,12 +1402,7 @@ pub mod dma {
return Err((e, self, buffer));
}

Ok(SpiDmaTransfer {
spi_dma: self,
dma_buf: buffer,
is_tx: true,
is_rx: false,
})
Ok(SpiDmaTransfer::new(self, buffer, true, false))
}
}

Expand Down
78 changes: 78 additions & 0 deletions hil-test/tests/spi_full_duplex_async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//! SPI Full Duplex Async Test
//!
//! Folowing pins are used:
//! SCLK GPIO0
//! MISO GPIO2
//! MOSI GPIO3
//! CS GPIO8
//!
//! Connect MISO (GPIO2) and MOSI (GPIO3) pins.

//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s3

#![no_std]
#![no_main]

use defmt_rtt as _;
use esp_backtrace as _;

#[cfg(test)]
#[embedded_test::tests(executor = esp_hal_embassy::Executor::new())]
mod tests {
use esp_hal::{
clock::ClockControl,
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::Io,
peripherals::Peripherals,
prelude::*,
spi::{
master::{dma::asynch::SpiDmaAsyncBus, prelude::*, Spi},
SpiMode,
},
system::SystemControl,
};

#[init]
async fn init() {}

#[test]
#[timeout(3)]
async fn test_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;

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 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));

let mut spi_bus = SpiDmaAsyncBus::new(spi, dma_tx_buf, dma_rx_buf);

let send_buffer = [0, 1, 2, 3, 4, 5, 6, 7];
let mut buffer = [0; 8];

embedded_hal_async::spi::SpiBus::transfer(&mut spi_bus, &mut buffer, &send_buffer)
.await
.unwrap();

assert_eq!(send_buffer, buffer);
}
}

0 comments on commit 8828e91

Please sign in to comment.