diff options
| author | James Munns <[email protected]> | 2025-12-05 15:22:38 +0100 |
|---|---|---|
| committer | James Munns <[email protected]> | 2025-12-05 15:22:38 +0100 |
| commit | fa54dd5849a083b286b2a3f1928428c8704d3d70 (patch) | |
| tree | 56f6e4f4ad5233d357a7ef5fefb38083f32d0562 /embassy-mcxa | |
| parent | 1ce2083f9a0fcf1cfbb10de0fb3ed44b460a5cc7 (diff) | |
Create separate ring buffered RX receiver to encapsulate unsafe
Diffstat (limited to 'embassy-mcxa')
| -rw-r--r-- | embassy-mcxa/src/dma.rs | 15 | ||||
| -rw-r--r-- | embassy-mcxa/src/lpuart/mod.rs | 40 |
2 files changed, 49 insertions, 6 deletions
diff --git a/embassy-mcxa/src/dma.rs b/embassy-mcxa/src/dma.rs index 7d1588516..d563c2e29 100644 --- a/embassy-mcxa/src/dma.rs +++ b/embassy-mcxa/src/dma.rs | |||
| @@ -2170,7 +2170,14 @@ impl<'a, W: Word> RingBuffer<'a, W> { | |||
| 2170 | /// Stop the DMA transfer and consume the ring buffer. | 2170 | /// Stop the DMA transfer and consume the ring buffer. |
| 2171 | /// | 2171 | /// |
| 2172 | /// Returns any remaining unread data count. | 2172 | /// Returns any remaining unread data count. |
| 2173 | pub fn stop(self) -> usize { | 2173 | pub fn stop(mut self) -> usize { |
| 2174 | let res = self.teardown(); | ||
| 2175 | drop(self); | ||
| 2176 | res | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | /// Stop the DMA transfer. Intended to be called by `stop()` or `Drop`. | ||
| 2180 | fn teardown(&mut self) -> usize { | ||
| 2174 | let available = self.available(); | 2181 | let available = self.available(); |
| 2175 | 2182 | ||
| 2176 | // Disable the channel | 2183 | // Disable the channel |
| @@ -2187,6 +2194,12 @@ impl<'a, W: Word> RingBuffer<'a, W> { | |||
| 2187 | } | 2194 | } |
| 2188 | } | 2195 | } |
| 2189 | 2196 | ||
| 2197 | impl<'a, W: Word> Drop for RingBuffer<'a, W> { | ||
| 2198 | fn drop(&mut self) { | ||
| 2199 | self.teardown(); | ||
| 2200 | } | ||
| 2201 | } | ||
| 2202 | |||
| 2190 | impl<C: Channel> DmaChannel<C> { | 2203 | impl<C: Channel> DmaChannel<C> { |
| 2191 | /// Set up a circular DMA transfer for continuous peripheral-to-memory reception. | 2204 | /// Set up a circular DMA transfer for continuous peripheral-to-memory reception. |
| 2192 | /// | 2205 | /// |
diff --git a/embassy-mcxa/src/lpuart/mod.rs b/embassy-mcxa/src/lpuart/mod.rs index 39fecb413..a176c7032 100644 --- a/embassy-mcxa/src/lpuart/mod.rs +++ b/embassy-mcxa/src/lpuart/mod.rs | |||
| @@ -1,16 +1,17 @@ | |||
| 1 | use core::future::Future; | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | 3 | ||
| 3 | use embassy_hal_internal::{Peri, PeripheralType}; | 4 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 4 | use paste::paste; | 5 | use paste::paste; |
| 5 | 6 | ||
| 6 | use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig}; | 7 | use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig}; |
| 7 | use crate::clocks::{ClockError, Gate, PoweredClock, enable_and_reset}; | 8 | use crate::clocks::{enable_and_reset, ClockError, Gate, PoweredClock}; |
| 8 | use crate::gpio::SealedPin; | 9 | use crate::gpio::SealedPin; |
| 9 | use crate::pac::lpuart0::baud::Sbns as StopBits; | 10 | use crate::pac::lpuart0::baud::Sbns as StopBits; |
| 10 | use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, M as DataBits, Pt as Parity}; | 11 | use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, Pt as Parity, M as DataBits}; |
| 11 | use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource}; | 12 | use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource}; |
| 12 | use crate::pac::lpuart0::stat::Msbf as MsbFirst; | 13 | use crate::pac::lpuart0::stat::Msbf as MsbFirst; |
| 13 | use crate::{AnyPin, interrupt, pac}; | 14 | use crate::{interrupt, pac, AnyPin}; |
| 14 | 15 | ||
| 15 | pub mod buffered; | 16 | pub mod buffered; |
| 16 | 17 | ||
| @@ -720,6 +721,12 @@ pub struct LpuartDma<'a, T: Instance, TxC: DmaChannelTrait, RxC: DmaChannelTrait | |||
| 720 | rx: LpuartRxDma<'a, T, RxC>, | 721 | rx: LpuartRxDma<'a, T, RxC>, |
| 721 | } | 722 | } |
| 722 | 723 | ||
| 724 | /// Lpuart RX driver with ring-buffered DMA support. | ||
| 725 | pub struct LpuartRxRingDma<'peri, 'ring, T: Instance, C: DmaChannelTrait> { | ||
| 726 | _inner: LpuartRxDma<'peri, T, C>, | ||
| 727 | ring: RingBuffer<'ring, u8>, | ||
| 728 | } | ||
| 729 | |||
| 723 | // ============================================================================ | 730 | // ============================================================================ |
| 724 | // LPUART CORE IMPLEMENTATION | 731 | // LPUART CORE IMPLEMENTATION |
| 725 | // ============================================================================ | 732 | // ============================================================================ |
| @@ -1402,6 +1409,14 @@ impl<'a, T: Instance, C: DmaChannelTrait> LpuartRxDma<'a, T, C> { | |||
| 1402 | Ok(()) | 1409 | Ok(()) |
| 1403 | } | 1410 | } |
| 1404 | 1411 | ||
| 1412 | pub fn into_ring_dma_rx<'buf>(self, buf: &'buf mut [u8]) -> LpuartRxRingDma<'a, 'buf, T, C> { | ||
| 1413 | unsafe { | ||
| 1414 | let ring = self.setup_ring_buffer(buf); | ||
| 1415 | self.enable_dma_request(); | ||
| 1416 | LpuartRxRingDma { _inner: self, ring } | ||
| 1417 | } | ||
| 1418 | } | ||
| 1419 | |||
| 1405 | /// Set up a ring buffer for continuous DMA reception. | 1420 | /// Set up a ring buffer for continuous DMA reception. |
| 1406 | /// | 1421 | /// |
| 1407 | /// This configures the DMA channel for circular operation, enabling continuous | 1422 | /// This configures the DMA channel for circular operation, enabling continuous |
| @@ -1441,7 +1456,7 @@ impl<'a, T: Instance, C: DmaChannelTrait> LpuartRxDma<'a, T, C> { | |||
| 1441 | /// - Only one RingBuffer should exist per LPUART RX channel at a time. | 1456 | /// - Only one RingBuffer should exist per LPUART RX channel at a time. |
| 1442 | /// - The caller must ensure the static buffer is not accessed elsewhere while | 1457 | /// - The caller must ensure the static buffer is not accessed elsewhere while |
| 1443 | /// the ring buffer is active. | 1458 | /// the ring buffer is active. |
| 1444 | pub unsafe fn setup_ring_buffer<'b>(&self, buf: &'b mut [u8]) -> RingBuffer<'b, u8> { | 1459 | unsafe fn setup_ring_buffer<'b>(&self, buf: &'b mut [u8]) -> RingBuffer<'b, u8> { |
| 1445 | // Get the peripheral data register address | 1460 | // Get the peripheral data register address |
| 1446 | let peri_addr = self.info.regs.data().as_ptr() as *const u8; | 1461 | let peri_addr = self.info.regs.data().as_ptr() as *const u8; |
| 1447 | 1462 | ||
| @@ -1460,11 +1475,26 @@ impl<'a, T: Instance, C: DmaChannelTrait> LpuartRxDma<'a, T, C> { | |||
| 1460 | /// Call this after `setup_ring_buffer()` to start continuous reception. | 1475 | /// Call this after `setup_ring_buffer()` to start continuous reception. |
| 1461 | /// This is separated from setup to allow for any additional configuration | 1476 | /// This is separated from setup to allow for any additional configuration |
| 1462 | /// before starting the transfer. | 1477 | /// before starting the transfer. |
| 1463 | pub unsafe fn enable_dma_request(&self) { | 1478 | unsafe fn enable_dma_request(&self) { |
| 1464 | self.rx_dma.enable_request(); | 1479 | self.rx_dma.enable_request(); |
| 1465 | } | 1480 | } |
| 1466 | } | 1481 | } |
| 1467 | 1482 | ||
| 1483 | impl<'peri, 'buf, T: Instance, C: DmaChannelTrait> LpuartRxRingDma<'peri, 'buf, T, C> { | ||
| 1484 | /// Read from the ring buffer | ||
| 1485 | pub fn read<'d>( | ||
| 1486 | &mut self, | ||
| 1487 | dst: &'d mut [u8], | ||
| 1488 | ) -> impl Future<Output = core::result::Result<usize, crate::dma::Error>> + use<'_, 'buf, 'd, T, C> { | ||
| 1489 | self.ring.read(dst) | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | /// Clear the current contents of the ring buffer | ||
| 1493 | pub fn clear(&mut self) { | ||
| 1494 | self.ring.clear(); | ||
| 1495 | } | ||
| 1496 | } | ||
| 1497 | |||
| 1468 | impl<'a, T: Instance, TxC: DmaChannelTrait, RxC: DmaChannelTrait> LpuartDma<'a, T, TxC, RxC> { | 1498 | impl<'a, T: Instance, TxC: DmaChannelTrait, RxC: DmaChannelTrait> LpuartDma<'a, T, TxC, RxC> { |
| 1469 | /// Create a new LPUART driver with DMA support for both TX and RX. | 1499 | /// Create a new LPUART driver with DMA support for both TX and RX. |
| 1470 | pub fn new( | 1500 | pub fn new( |
