From 8baf4df20b858bee34e152be4d6a6510938e8f45 Mon Sep 17 00:00:00 2001 From: Bryan Kadzban Date: Thu, 25 May 2023 04:48:21 +0000 Subject: [PATCH 1/2] Add an is_done() poll method to DMA transfers Implement it by forwarding to the DMA channel's existing is_done mehod. Add the implementation to both SPI and I2S DMA transfer structs. --- esp-hal-common/src/dma/mod.rs | 4 ++++ esp-hal-common/src/i2s.rs | 10 ++++++++++ esp-hal-common/src/spi.rs | 12 ++++++++++++ 3 files changed, 26 insertions(+) diff --git a/esp-hal-common/src/dma/mod.rs b/esp-hal-common/src/dma/mod.rs index 6574c2ae0..f4e1fbde4 100644 --- a/esp-hal-common/src/dma/mod.rs +++ b/esp-hal-common/src/dma/mod.rs @@ -846,6 +846,8 @@ where pub trait DmaTransfer: Drop { /// Wait for the transfer to finish. fn wait(self) -> (B, T); + /// Check if the transfer is finished. + fn is_done(&self) -> bool; } /// Trait to be implemented for an in progress dma transfer. @@ -853,6 +855,8 @@ pub trait DmaTransfer: Drop { pub trait DmaTransferRxTx: Drop { /// Wait for the transfer to finish. fn wait(self) -> (BR, BT, T); + /// Check if the transfer is finished. + fn is_done(&self) -> bool; } #[cfg(feature = "async")] diff --git a/esp-hal-common/src/i2s.rs b/esp-hal-common/src/i2s.rs index fca4f4a2e..5889ad5fc 100644 --- a/esp-hal-common/src/i2s.rs +++ b/esp-hal-common/src/i2s.rs @@ -326,6 +326,11 @@ where (buffer, payload) } } + + /// Check if the DMA transfer is complete + fn is_done(&self) -> bool { + self.i2s_tx.tx_channel.is_done() + } } impl<'d, T, P, TX, BUFFER> Drop for I2sWriteDmaTransfer @@ -451,6 +456,11 @@ where (buffer, payload) } } + + /// Check if the DMA transfer is complete + fn is_done(&self) -> bool { + self.i2s_rx.rx_channel.is_done() + } } impl Drop for I2sReadDmaTransfer diff --git a/esp-hal-common/src/spi.rs b/esp-hal-common/src/spi.rs index 4593fde6e..4c2727e42 100644 --- a/esp-hal-common/src/spi.rs +++ b/esp-hal-common/src/spi.rs @@ -861,6 +861,12 @@ pub mod dma { (rbuffer, tbuffer, payload) } } + + /// Check if the DMA transfer is complete + fn is_done(&self) -> bool { + let ch = &self.spi_dma.channel; + ch.tx.is_done() && ch.rx.is_done() + } } impl<'d, T, TX, RX, P, RXBUF, TXBUF, M> Drop @@ -918,6 +924,12 @@ pub mod dma { (buffer, payload) } } + + /// Check if the DMA transfer is complete + fn is_done(&self) -> bool { + let ch = &self.spi_dma.channel; + ch.tx.is_done() && ch.rx.is_done() + } } impl<'d, T, TX, RX, P, BUFFER, M> Drop for SpiDmaTransfer<'d, T, TX, RX, P, BUFFER, M> From a6835d9cecf0be3f8a9c92e67a7c97cfa808f0e2 Mon Sep 17 00:00:00 2001 From: Bryan Kadzban Date: Thu, 25 May 2023 06:08:54 +0000 Subject: [PATCH 2/2] Add examples for polling DMA transfers. Only in the SPI case, but the I2S case has the same API so this should be fine. --- CHANGELOG.md | 1 + esp32-hal/examples/spi_loopback_dma.rs | 7 +++++++ esp32c2-hal/examples/spi_loopback_dma.rs | 7 +++++++ esp32c3-hal/examples/spi_loopback_dma.rs | 7 +++++++ esp32c6-hal/examples/spi_loopback_dma.rs | 7 +++++++ esp32s2-hal/examples/spi_loopback_dma.rs | 7 +++++++ esp32s3-hal/examples/spi_loopback_dma.rs | 7 +++++++ 7 files changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71d1a91a9..05ea4dcf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add some miscellaneous examples for the ESP32-H2 (#548) - Add initial support for PCNT in ESP32-H2 (#551) - Add initial support for RMT in ESP32-H2 (#556) +- Add a fn to poll DMA transfers ### Fixed diff --git a/esp32-hal/examples/spi_loopback_dma.rs b/esp32-hal/examples/spi_loopback_dma.rs index 283cd147c..548716094 100644 --- a/esp32-hal/examples/spi_loopback_dma.rs +++ b/esp32-hal/examples/spi_loopback_dma.rs @@ -98,6 +98,13 @@ fn main() -> ! { let transfer = spi.dma_transfer(send, receive).unwrap(); // here we could do something else while DMA transfer is in progress + let mut i = 0; + // Check is_done until the transfer is almost done (32000 bytes at 100kHz is + // 2.56 seconds), then move to wait(). + while !transfer.is_done() && i < 10 { + delay.delay_ms(250u32); + i += 1; + } // the buffers and spi is moved into the transfer and we can get it back via // `wait` (receive, send, spi) = transfer.wait(); diff --git a/esp32c2-hal/examples/spi_loopback_dma.rs b/esp32c2-hal/examples/spi_loopback_dma.rs index 79743740d..529ec1b0c 100644 --- a/esp32c2-hal/examples/spi_loopback_dma.rs +++ b/esp32c2-hal/examples/spi_loopback_dma.rs @@ -99,6 +99,13 @@ fn main() -> ! { let transfer = spi.dma_transfer(send, receive).unwrap(); // here we could do something else while DMA transfer is in progress + let mut i = 0; + // Check is_done until the transfer is almost done (32000 bytes at 100kHz is + // 2.56 seconds), then move to wait(). + while !transfer.is_done() && i < 10 { + delay.delay_ms(250u32); + i += 1; + } // the buffers and spi is moved into the transfer and we can get it back via // `wait` (receive, send, spi) = transfer.wait(); diff --git a/esp32c3-hal/examples/spi_loopback_dma.rs b/esp32c3-hal/examples/spi_loopback_dma.rs index 8bc8910fb..f612b8601 100644 --- a/esp32c3-hal/examples/spi_loopback_dma.rs +++ b/esp32c3-hal/examples/spi_loopback_dma.rs @@ -106,6 +106,13 @@ fn main() -> ! { let transfer = spi.dma_transfer(send, receive).unwrap(); // here we could do something else while DMA transfer is in progress + let mut i = 0; + // Check is_done until the transfer is almost done (32000 bytes at 100kHz is + // 2.56 seconds), then move to wait(). + while !transfer.is_done() && i < 10 { + delay.delay_ms(250u32); + i += 1; + } // the buffers and spi is moved into the transfer and we can get it back via // `wait` (receive, send, spi) = transfer.wait(); diff --git a/esp32c6-hal/examples/spi_loopback_dma.rs b/esp32c6-hal/examples/spi_loopback_dma.rs index 945a62bcf..7f72e664d 100644 --- a/esp32c6-hal/examples/spi_loopback_dma.rs +++ b/esp32c6-hal/examples/spi_loopback_dma.rs @@ -107,6 +107,13 @@ fn main() -> ! { let transfer = spi.dma_transfer(send, receive).unwrap(); // here we could do something else while DMA transfer is in progress + let mut i = 0; + // Check is_done until the transfer is almost done (32000 bytes at 100kHz is + // 2.56 seconds), then move to wait(). + while !transfer.is_done() && i < 10 { + delay.delay_ms(250u32); + i += 1; + } // the buffers and spi is moved into the transfer and we can get it back via // `wait` (receive, send, spi) = transfer.wait(); diff --git a/esp32s2-hal/examples/spi_loopback_dma.rs b/esp32s2-hal/examples/spi_loopback_dma.rs index 0f64b55b8..15df558e9 100644 --- a/esp32s2-hal/examples/spi_loopback_dma.rs +++ b/esp32s2-hal/examples/spi_loopback_dma.rs @@ -98,6 +98,13 @@ fn main() -> ! { let transfer = spi.dma_transfer(send, receive).unwrap(); // here we could do something else while DMA transfer is in progress + let mut i = 0; + // Check is_done until the transfer is almost done (32000 bytes at 100kHz is + // 2.56 seconds), then move to wait(). + while !transfer.is_done() && i < 10 { + delay.delay_ms(250u32); + i += 1; + } // the buffers and spi is moved into the transfer and we can get it back via // `wait` (receive, send, spi) = transfer.wait(); diff --git a/esp32s3-hal/examples/spi_loopback_dma.rs b/esp32s3-hal/examples/spi_loopback_dma.rs index 0e2b6d9c6..f71b5e21c 100644 --- a/esp32s3-hal/examples/spi_loopback_dma.rs +++ b/esp32s3-hal/examples/spi_loopback_dma.rs @@ -106,6 +106,13 @@ fn main() -> ! { let transfer = spi.dma_transfer(send, receive).unwrap(); // here we could do something else while DMA transfer is in progress + let mut i = 0; + // Check is_done until the transfer is almost done (32000 bytes at 100kHz is + // 2.56 seconds), then move to wait(). + while !transfer.is_done() && i < 10 { + delay.delay_ms(250u32); + i += 1; + } // the buffers and spi is moved into the transfer and we can get it back via // `wait` (receive, send, spi) = transfer.wait();