From 48dae540e8775f2fb13274aa3bd7daac48397a3e Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 22 Aug 2024 16:01:28 +0100 Subject: [PATCH] Limit half duplex transfers to the capacity of the DmaBuf --- esp-hal/src/dma/mod.rs | 20 ----------- esp-hal/src/spi/master.rs | 45 +++++++++++++------------ hil-test/tests/spi_half_duplex_read.rs | 5 +-- hil-test/tests/spi_half_duplex_write.rs | 5 +-- 4 files changed, 30 insertions(+), 45 deletions(-) diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index a26233b2aca..1c174166402 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -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) @@ -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) diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index c30a8c2effb..63be41d968c 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -67,6 +67,7 @@ use fugit::HertzU32; use procmacros::ram; use super::{ + DmaError, DuplexMode, Error, FullDuplexMode, @@ -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); @@ -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); diff --git a/hil-test/tests/spi_half_duplex_read.rs b/hil-test/tests/spi_half_duplex_read.rs index 545e2a67356..63fccb51343 100644 --- a/hil-test/tests/spi_half_duplex_read.rs +++ b/hil-test/tests/spi_half_duplex_read.rs @@ -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(); diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index b56bafea646..d2a7b27b7c9 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -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(