Skip to content

Commit 8828e91

Browse files
committed
Add async HIL test
1 parent 0826040 commit 8828e91

File tree

2 files changed

+117
-37
lines changed

2 files changed

+117
-37
lines changed

esp-hal/src/spi/master.rs

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ where
840840

841841
pub mod dma {
842842
use core::{
843+
cell::Cell,
843844
cmp::min,
844845
sync::atomic::{fence, Ordering},
845846
};
@@ -1046,6 +1047,9 @@ pub mod dma {
10461047
dma_buf: Buf,
10471048
is_rx: bool,
10481049
is_tx: bool,
1050+
1051+
rx_future_awaited: bool,
1052+
tx_future_awaited: bool,
10491053
}
10501054

10511055
impl<'d, T, C, M, DmaMode, Buf> SpiDmaTransfer<'d, T, C, M, DmaMode, Buf>
@@ -1056,14 +1060,30 @@ pub mod dma {
10561060
M: DuplexMode,
10571061
DmaMode: Mode,
10581062
{
1063+
fn new(
1064+
spi_dma: SpiDma<'d, T, C, M, DmaMode>,
1065+
dma_buf: Buf,
1066+
is_rx: bool,
1067+
is_tx: bool,
1068+
) -> Self {
1069+
Self {
1070+
spi_dma,
1071+
dma_buf,
1072+
is_rx,
1073+
is_tx,
1074+
rx_future_awaited: false,
1075+
tx_future_awaited: false,
1076+
}
1077+
}
1078+
10591079
pub fn is_done(&self) -> bool {
1060-
if self.is_tx && !self.spi_dma.channel.tx.is_done() {
1080+
if self.is_tx && !self.tx_future_awaited && !self.spi_dma.channel.tx.is_done() {
10611081
return false;
10621082
}
10631083
if self.spi_dma.spi.busy() {
10641084
return false;
10651085
}
1066-
if self.is_rx {
1086+
if self.is_rx && !self.rx_future_awaited {
10671087
// If this is an asymmetric transfer and the RX side is smaller, the RX channel
10681088
// will never be "done" as it won't have enough descriptors/buffer to receive
10691089
// the EOF bit from the SPI. So instead the RX channel will hit
@@ -1096,14 +1116,16 @@ pub mod dma {
10961116
M: DuplexMode,
10971117
{
10981118
pub async fn wait_for_done(&mut self) {
1099-
if self.is_tx {
1119+
if self.is_tx && !self.tx_future_awaited {
11001120
let _ = DmaTxFuture::new(&mut self.spi_dma.channel.tx).await;
1121+
self.tx_future_awaited = true;
11011122
}
11021123

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

1105-
if self.is_rx {
1126+
if self.is_rx && !self.rx_future_awaited {
11061127
let _ = DmaRxFuture::new(&mut self.spi_dma.channel.rx).await;
1128+
self.rx_future_awaited = true;
11071129
}
11081130
}
11091131
}
@@ -1141,12 +1163,7 @@ pub mod dma {
11411163
return Err((e, self, buffer));
11421164
}
11431165

1144-
Ok(SpiDmaTransfer {
1145-
spi_dma: self,
1146-
dma_buf: buffer,
1147-
is_tx: true,
1148-
is_rx: false,
1149-
})
1166+
Ok(SpiDmaTransfer::new(self, buffer, true, false))
11501167
}
11511168

11521169
/// Perform a DMA read.
@@ -1161,7 +1178,7 @@ pub mod dma {
11611178
buffer: DmaRxBuf,
11621179
) -> Result<SpiDmaTransfer<'d, T, C, M, DmaMode, DmaRxBuf>, (Error, Self, DmaRxBuf)>
11631180
{
1164-
let bytes_to_read = buffer.capacity();
1181+
let bytes_to_read = buffer.len();
11651182
if bytes_to_read > MAX_DMA_SIZE {
11661183
return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
11671184
}
@@ -1174,12 +1191,7 @@ pub mod dma {
11741191
return Err((e, self, buffer));
11751192
}
11761193

1177-
Ok(SpiDmaTransfer {
1178-
spi_dma: self,
1179-
dma_buf: buffer,
1180-
is_tx: false,
1181-
is_rx: true,
1182-
})
1194+
Ok(SpiDmaTransfer::new(self, buffer, false, true))
11831195
}
11841196

11851197
/// Perform a DMA transfer
@@ -1197,7 +1209,7 @@ pub mod dma {
11971209
(Error, Self, DmaTxBuf, DmaRxBuf),
11981210
> {
11991211
let bytes_to_write = tx_buffer.len();
1200-
let bytes_to_read = rx_buffer.capacity();
1212+
let bytes_to_read = rx_buffer.len();
12011213

12021214
if bytes_to_write > MAX_DMA_SIZE || bytes_to_read > MAX_DMA_SIZE {
12031215
return Err((
@@ -1222,12 +1234,12 @@ pub mod dma {
12221234
return Err((e, self, tx_buffer, rx_buffer));
12231235
}
12241236

1225-
Ok(SpiDmaTransfer {
1226-
spi_dma: self,
1227-
dma_buf: (tx_buffer, rx_buffer),
1228-
is_tx: true,
1229-
is_rx: true,
1230-
})
1237+
Ok(SpiDmaTransfer::new(
1238+
self,
1239+
(tx_buffer, rx_buffer),
1240+
true,
1241+
true,
1242+
))
12311243
}
12321244
}
12331245

@@ -1250,7 +1262,7 @@ pub mod dma {
12501262
buffer: DmaRxBuf,
12511263
) -> Result<SpiDmaTransfer<'d, T, C, M, DmaMode, DmaRxBuf>, (Error, Self, DmaRxBuf)>
12521264
{
1253-
let bytes_to_read = buffer.capacity();
1265+
let bytes_to_read = buffer.len();
12541266
if bytes_to_read > MAX_DMA_SIZE {
12551267
return Err((Error::MaxDmaTransferSizeExceeded, self, buffer));
12561268
}
@@ -1313,12 +1325,7 @@ pub mod dma {
13131325
return Err((e, self, buffer));
13141326
}
13151327

1316-
Ok(SpiDmaTransfer {
1317-
spi_dma: self,
1318-
dma_buf: buffer,
1319-
is_tx: false,
1320-
is_rx: true,
1321-
})
1328+
Ok(SpiDmaTransfer::new(self, buffer, false, true))
13221329
}
13231330

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

1398-
Ok(SpiDmaTransfer {
1399-
spi_dma: self,
1400-
dma_buf: buffer,
1401-
is_tx: true,
1402-
is_rx: false,
1403-
})
1405+
Ok(SpiDmaTransfer::new(self, buffer, true, false))
14041406
}
14051407
}
14061408

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//! SPI Full Duplex Async Test
2+
//!
3+
//! Folowing pins are used:
4+
//! SCLK GPIO0
5+
//! MISO GPIO2
6+
//! MOSI GPIO3
7+
//! CS GPIO8
8+
//!
9+
//! Connect MISO (GPIO2) and MOSI (GPIO3) pins.
10+
11+
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s3
12+
13+
#![no_std]
14+
#![no_main]
15+
16+
use defmt_rtt as _;
17+
use esp_backtrace as _;
18+
19+
#[cfg(test)]
20+
#[embedded_test::tests(executor = esp_hal_embassy::Executor::new())]
21+
mod tests {
22+
use esp_hal::{
23+
clock::ClockControl,
24+
dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf},
25+
dma_buffers,
26+
gpio::Io,
27+
peripherals::Peripherals,
28+
prelude::*,
29+
spi::{
30+
master::{dma::asynch::SpiDmaAsyncBus, prelude::*, Spi},
31+
SpiMode,
32+
},
33+
system::SystemControl,
34+
};
35+
36+
#[init]
37+
async fn init() {}
38+
39+
#[test]
40+
#[timeout(3)]
41+
async fn test_transfer() {
42+
let peripherals = Peripherals::take();
43+
let system = SystemControl::new(peripherals.SYSTEM);
44+
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
45+
46+
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
47+
let sclk = io.pins.gpio0;
48+
let miso = io.pins.gpio2;
49+
let mosi = io.pins.gpio3;
50+
let cs = io.pins.gpio8;
51+
52+
let dma = Dma::new(peripherals.DMA);
53+
54+
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
55+
let dma_channel = dma.spi2channel;
56+
#[cfg(not(any(feature = "esp32", feature = "esp32s2")))]
57+
let dma_channel = dma.channel0;
58+
59+
let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(4);
60+
let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
61+
let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
62+
63+
let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks)
64+
.with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs))
65+
.with_dma(dma_channel.configure_for_async(false, DmaPriority::Priority0));
66+
67+
let mut spi_bus = SpiDmaAsyncBus::new(spi, dma_tx_buf, dma_rx_buf);
68+
69+
let send_buffer = [0, 1, 2, 3, 4, 5, 6, 7];
70+
let mut buffer = [0; 8];
71+
72+
embedded_hal_async::spi::SpiBus::transfer(&mut spi_bus, &mut buffer, &send_buffer)
73+
.await
74+
.unwrap();
75+
76+
assert_eq!(send_buffer, buffer);
77+
}
78+
}

0 commit comments

Comments
 (0)