Skip to content

Commit

Permalink
Limit half duplex transfers to the capacity of the DmaBuf
Browse files Browse the repository at this point in the history
  • Loading branch information
MabezDev committed Aug 23, 2024
1 parent 1f47653 commit 48dae54
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 45 deletions.
20 changes: 0 additions & 20 deletions esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1947,16 +1947,6 @@ impl DmaTxBuf {
Ok(buf)
}

/// Create an empty DmaTxBuf.
///
/// This has no ability to transmit data.
pub fn empty() -> Self {
Self {
descriptors: &mut [],
buffer: &mut [],
}
}

/// Consume the buf, returning the descriptors and buffer.
pub fn split(self) -> (&'static mut [DmaDescriptor], &'static mut [u8]) {
(self.descriptors, self.buffer)
Expand Down Expand Up @@ -2092,16 +2082,6 @@ impl DmaRxBuf {
Ok(buf)
}

/// Create an empty DmaRxBuf.
///
/// This has no ability to recieve data.
pub fn empty() -> Self {
Self {
descriptors: &mut [],
buffer: &mut [],
}
}

/// Consume the buf, returning the descriptors and buffer.
pub fn split(self) -> (&'static mut [DmaDescriptor], &'static mut [u8]) {
(self.descriptors, self.buffer)
Expand Down
45 changes: 24 additions & 21 deletions esp-hal/src/spi/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ use fugit::HertzU32;
use procmacros::ram;

use super::{
DmaError,
DuplexMode,
Error,
FullDuplexMode,
Expand Down Expand Up @@ -1754,22 +1755,23 @@ pub mod dma {
buffer: &mut [u8],
) -> Result<(), Self::Error> {
let (mut spi_dma, mut tx_buf, mut rx_buf) = self.wait_for_idle();
if buffer.len() > rx_buf.capacity() {
return Err(super::Error::DmaError(DmaError::Overflow));
}

for chunk in buffer.chunks_mut(rx_buf.capacity()) {
rx_buf.set_length(chunk.len());
rx_buf.set_length(buffer.len());

match spi_dma.read(data_mode, cmd, address, dummy, rx_buf) {
Ok(transfer) => self.state = State::Reading(transfer, tx_buf),
Err((e, spi, rx)) => {
self.state = State::Idle(spi, tx_buf, rx);
return Err(e);
}
match spi_dma.read(data_mode, cmd, address, dummy, rx_buf) {
Ok(transfer) => self.state = State::Reading(transfer, tx_buf),
Err((e, spi, rx)) => {
self.state = State::Idle(spi, tx_buf, rx);
return Err(e);
}
(spi_dma, tx_buf, rx_buf) = self.wait_for_idle();

let bytes_read = rx_buf.read_received_data(chunk);
debug_assert_eq!(bytes_read, chunk.len());
}
(spi_dma, tx_buf, rx_buf) = self.wait_for_idle();

let bytes_read = rx_buf.read_received_data(buffer);
debug_assert_eq!(bytes_read, buffer.len());

self.state = State::Idle(spi_dma, tx_buf, rx_buf);

Expand All @@ -1786,19 +1788,20 @@ pub mod dma {
buffer: &[u8],
) -> Result<(), Self::Error> {
let (mut spi_dma, mut tx_buf, mut rx_buf) = self.wait_for_idle();
if buffer.len() > tx_buf.capacity() {
return Err(super::Error::DmaError(DmaError::Overflow));
}

for chunk in buffer.chunks(tx_buf.capacity()) {
tx_buf.fill(chunk);
tx_buf.fill(buffer);

match spi_dma.write(data_mode, cmd, address, dummy, tx_buf) {
Ok(transfer) => self.state = State::Writing(transfer, rx_buf),
Err((e, spi, tx)) => {
self.state = State::Idle(spi, tx, rx_buf);
return Err(e);
}
match spi_dma.write(data_mode, cmd, address, dummy, tx_buf) {
Ok(transfer) => self.state = State::Writing(transfer, rx_buf),
Err((e, spi, tx)) => {
self.state = State::Idle(spi, tx, rx_buf);
return Err(e);
}
(spi_dma, tx_buf, rx_buf) = self.wait_for_idle();
}
(spi_dma, tx_buf, rx_buf) = self.wait_for_idle();

self.state = State::Idle(spi_dma, tx_buf, rx_buf);

Expand Down
5 changes: 3 additions & 2 deletions hil-test/tests/spi_half_duplex_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,15 @@ mod tests {
#[cfg(not(any(feature = "esp32", feature = "esp32s2")))]
let dma_channel = dma.channel0;

let (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0);
let (buffer, descriptors, tx, txd) = dma_buffers!(DMA_BUFFER_SIZE, 1);
let dma_rx_buf = DmaRxBuf::new(descriptors, buffer).unwrap();
let dma_tx_buf = DmaTxBuf::new(txd, tx).unwrap();

let mut 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))
.with_buffers(DmaTxBuf::empty(), dma_rx_buf);
.with_buffers(dma_tx_buf, dma_rx_buf);

// SPI should read '0's from the MISO pin
miso_mirror.set_low();
Expand Down
5 changes: 3 additions & 2 deletions hil-test/tests/spi_half_duplex_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,15 @@ mod tests {
#[cfg(not(any(feature = "esp32", feature = "esp32s2")))]
let dma_channel = dma.channel0;

let (buffer, descriptors, _, _) = dma_buffers!(DMA_BUFFER_SIZE, 0);
let (buffer, descriptors, rx, rxd) = dma_buffers!(DMA_BUFFER_SIZE, 1);
let dma_tx_buf = DmaTxBuf::new(descriptors, buffer).unwrap();
let dma_rx_buf = DmaRxBuf::new(rxd, rx).unwrap();

let mut 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))
.with_buffers(dma_tx_buf, DmaRxBuf::empty());
.with_buffers(dma_tx_buf, dma_rx_buf);

let unit = pcnt.unit0;
unit.channel0.set_edge_signal(PcntSource::from_pin(
Expand Down

0 comments on commit 48dae54

Please sign in to comment.