aboutsummaryrefslogtreecommitdiff
path: root/embassy-mcxa
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-12-05 15:22:38 +0100
committerJames Munns <[email protected]>2025-12-05 15:22:38 +0100
commitfa54dd5849a083b286b2a3f1928428c8704d3d70 (patch)
tree56f6e4f4ad5233d357a7ef5fefb38083f32d0562 /embassy-mcxa
parent1ce2083f9a0fcf1cfbb10de0fb3ed44b460a5cc7 (diff)
Create separate ring buffered RX receiver to encapsulate unsafe
Diffstat (limited to 'embassy-mcxa')
-rw-r--r--embassy-mcxa/src/dma.rs15
-rw-r--r--embassy-mcxa/src/lpuart/mod.rs40
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
2197impl<'a, W: Word> Drop for RingBuffer<'a, W> {
2198 fn drop(&mut self) {
2199 self.teardown();
2200 }
2201}
2202
2190impl<C: Channel> DmaChannel<C> { 2203impl<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 @@
1use core::future::Future;
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2 3
3use embassy_hal_internal::{Peri, PeripheralType}; 4use embassy_hal_internal::{Peri, PeripheralType};
4use paste::paste; 5use paste::paste;
5 6
6use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig}; 7use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig};
7use crate::clocks::{ClockError, Gate, PoweredClock, enable_and_reset}; 8use crate::clocks::{enable_and_reset, ClockError, Gate, PoweredClock};
8use crate::gpio::SealedPin; 9use crate::gpio::SealedPin;
9use crate::pac::lpuart0::baud::Sbns as StopBits; 10use crate::pac::lpuart0::baud::Sbns as StopBits;
10use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, M as DataBits, Pt as Parity}; 11use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, Pt as Parity, M as DataBits};
11use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource}; 12use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource};
12use crate::pac::lpuart0::stat::Msbf as MsbFirst; 13use crate::pac::lpuart0::stat::Msbf as MsbFirst;
13use crate::{AnyPin, interrupt, pac}; 14use crate::{interrupt, pac, AnyPin};
14 15
15pub mod buffered; 16pub 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.
725pub 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
1483impl<'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
1468impl<'a, T: Instance, TxC: DmaChannelTrait, RxC: DmaChannelTrait> LpuartDma<'a, T, TxC, RxC> { 1498impl<'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(