py32_hal/usart/
ringbuffered.rs

1//! Ring-buffered UART
2
3// The following code is modified from embassy-stm32
4// https://github.com/embassy-rs/embassy/tree/main/embassy-stm32
5// Special thanks to the Embassy Project and its contributors for their work!
6
7use core::future::poll_fn;
8use core::mem;
9use core::sync::atomic::{compiler_fence, Ordering};
10use core::task::Poll;
11
12use embassy_embedded_hal::SetConfig;
13use embassy_hal_internal::PeripheralRef;
14use embedded_io_async::ReadReady;
15use futures_util::future::{select, Either};
16
17use super::{
18    clear_interrupt_flags, rdr, reconfigure, sr, Config, ConfigError, Error, Info, State, UartRx,
19};
20#[cfg(dma)]
21use crate::dma::ReadableRingBuffer;
22use crate::gpio::{AnyPin, SealedPin as _};
23use crate::mode::Async;
24use crate::time::Hertz;
25use crate::usart::{Regs, Sr};
26
27/// Rx-only Ring-buffered UART Driver
28///
29/// Created with [UartRx::into_ring_buffered]
30pub struct RingBufferedUartRx<'d> {
31    info: &'static Info,
32    state: &'static State,
33    kernel_clock: Hertz,
34    rx: Option<PeripheralRef<'d, AnyPin>>,
35    rts: Option<PeripheralRef<'d, AnyPin>>,
36    ring_buf: ReadableRingBuffer<'d, u8>,
37}
38
39impl<'d> SetConfig for RingBufferedUartRx<'d> {
40    type Config = Config;
41    type ConfigError = ConfigError;
42
43    fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
44        self.set_config(config)
45    }
46}
47
48impl<'d> UartRx<'d, Async> {
49    /// Turn the `UartRx` into a buffered uart which can continously receive in the background
50    /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
51    /// DMA controller, and must be large enough to prevent overflows.
52    pub fn into_ring_buffered(mut self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d> {
53        assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
54
55        let opts = Default::default();
56
57        // Safety: we forget the struct before this function returns.
58        let rx_dma = self.rx_dma.as_mut().unwrap();
59        let request = rx_dma.request;
60        let rx_dma = unsafe { rx_dma.channel.clone_unchecked() };
61
62        let info = self.info;
63        let state = self.state;
64        let kernel_clock = self.kernel_clock;
65        let ring_buf =
66            unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) };
67        let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) };
68        let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) };
69
70        // Don't disable the clock
71        mem::forget(self);
72
73        RingBufferedUartRx {
74            info,
75            state,
76            kernel_clock,
77            rx,
78            rts,
79            ring_buf,
80        }
81    }
82}
83
84impl<'d> RingBufferedUartRx<'d> {
85    /// Reconfigure the driver
86    pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
87        reconfigure(self.info, self.kernel_clock, config)
88    }
89
90    /// Configure and start the DMA backed UART receiver
91    ///
92    /// Note: This is also done automatically by [`read()`] if required.
93    pub fn start_uart(&mut self) {
94        // Clear the buffer so that it is ready to receive data
95        compiler_fence(Ordering::SeqCst);
96        self.ring_buf.start();
97
98        let r = self.info.regs;
99        // clear all interrupts and DMA Rx Request
100        r.cr1().modify(|w| {
101            // disable RXNE interrupt
102            w.set_rxneie(false);
103            // enable parity interrupt if not ParityNone
104            w.set_peie(w.pce());
105            // enable idle line interrupt
106            w.set_idleie(true);
107        });
108        r.cr3().modify(|w| {
109            // enable Error Interrupt: (Frame error, Noise error, Overrun error)
110            w.set_eie(true);
111            // enable DMA Rx Request
112            w.set_dmar(true);
113        });
114    }
115
116    /// Stop DMA backed UART receiver
117    fn stop_uart(&mut self) {
118        self.ring_buf.request_pause();
119
120        let r = self.info.regs;
121        // clear all interrupts and DMA Rx Request
122        r.cr1().modify(|w| {
123            // disable RXNE interrupt
124            w.set_rxneie(false);
125            // disable parity interrupt
126            w.set_peie(false);
127            // disable idle line interrupt
128            w.set_idleie(false);
129        });
130        r.cr3().modify(|w| {
131            // disable Error Interrupt: (Frame error, Noise error, Overrun error)
132            w.set_eie(false);
133            // disable DMA Rx Request
134            w.set_dmar(false);
135        });
136
137        compiler_fence(Ordering::SeqCst);
138    }
139
140    /// Read bytes that are readily available in the ring buffer.
141    /// If no bytes are currently available in the buffer the call waits until the some
142    /// bytes are available (at least one byte and at most half the buffer size)
143    ///
144    /// Background receive is started if `start()` has not been previously called.
145    ///
146    /// Receive in the background is terminated if an error is returned.
147    /// It must then manually be started again by calling `start()` or by re-calling `read()`.
148    pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
149        let r = self.info.regs;
150
151        // Start DMA and Uart if it was not already started,
152        // otherwise check for errors in status register.
153        let sr = clear_idle_flag(r);
154        if !r.cr3().read().dmar() {
155            self.start_uart();
156        } else {
157            check_for_errors(sr)?;
158        }
159
160        loop {
161            match self.ring_buf.read(buf) {
162                Ok((0, _)) => {}
163                Ok((len, _)) => {
164                    return Ok(len);
165                }
166                Err(_) => {
167                    self.stop_uart();
168                    return Err(Error::Overrun);
169                }
170            }
171
172            match self.wait_for_data_or_idle().await {
173                Ok(_) => {}
174                Err(err) => {
175                    self.stop_uart();
176                    return Err(err);
177                }
178            }
179        }
180    }
181
182    /// Wait for uart idle or dma half-full or full
183    async fn wait_for_data_or_idle(&mut self) -> Result<(), Error> {
184        compiler_fence(Ordering::SeqCst);
185
186        // Future which completes when idle line is detected
187        let s = self.state;
188        let uart = poll_fn(|cx| {
189            s.rx_waker.register(cx.waker());
190
191            compiler_fence(Ordering::SeqCst);
192
193            // Critical section is needed so that IDLE isn't set after
194            // our read but before we clear it.
195            let sr = critical_section::with(|_| clear_idle_flag(self.info.regs));
196
197            check_for_errors(sr)?;
198
199            if sr.idle() {
200                // Idle line is detected
201                Poll::Ready(Ok(()))
202            } else {
203                Poll::Pending
204            }
205        });
206
207        let mut dma_init = false;
208        // Future which completes when there is dma is half full or full
209        let dma = poll_fn(|cx| {
210            self.ring_buf.set_waker(cx.waker());
211
212            let status = match dma_init {
213                false => Poll::Pending,
214                true => Poll::Ready(()),
215            };
216
217            dma_init = true;
218            status
219        });
220
221        match select(uart, dma).await {
222            Either::Left((result, _)) => result,
223            Either::Right(((), _)) => Ok(()),
224        }
225    }
226}
227
228impl Drop for RingBufferedUartRx<'_> {
229    fn drop(&mut self) {
230        self.stop_uart();
231        self.rx.as_ref().map(|x| x.set_as_disconnected());
232        self.rts.as_ref().map(|x| x.set_as_disconnected());
233        super::drop_tx_rx(self.info, self.state);
234    }
235}
236
237/// Return an error result if the Sr register has errors
238fn check_for_errors(s: Sr) -> Result<(), Error> {
239    if s.pe() {
240        Err(Error::Parity)
241    } else if s.fe() {
242        Err(Error::Framing)
243    } else if s.ne() {
244        Err(Error::Noise)
245    } else if s.ore() {
246        Err(Error::Overrun)
247    } else {
248        Ok(())
249    }
250}
251
252/// Clear IDLE and return the Sr register
253fn clear_idle_flag(r: Regs) -> Sr {
254    // SAFETY: read only and we only use Rx related flags
255
256    let sr = sr(r).read();
257
258    // This read also clears the error and idle interrupt flags on v1.
259    unsafe { rdr(r).read_volatile() };
260    clear_interrupt_flags(r, sr);
261
262    r.cr1().modify(|w| w.set_idleie(true));
263
264    sr
265}
266
267impl embedded_io_async::ErrorType for RingBufferedUartRx<'_> {
268    type Error = Error;
269}
270
271impl embedded_io_async::Read for RingBufferedUartRx<'_> {
272    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
273        self.read(buf).await
274    }
275}
276
277impl ReadReady for RingBufferedUartRx<'_> {
278    fn read_ready(&mut self) -> Result<bool, Self::Error> {
279        let len = self.ring_buf.len().map_err(|e| match e {
280            crate::dma::ringbuffer::Error::Overrun => Self::Error::Overrun,
281            crate::dma::ringbuffer::Error::DmaUnsynced => {
282                error!(
283                    "Ringbuffer error: DmaUNsynced, driver implementation is 
284                    probably bugged please open an issue"
285                );
286                // we report this as overrun since its recoverable in the same way
287                Self::Error::Overrun
288            }
289        })?;
290        Ok(len > 0)
291    }
292}