Skip to main content

rp2040_hal/uart/
reader.rs

1//! Universal Asynchronous Receiver Transmitter - Receiver Code
2//!
3//! This module is for receiving data with a UART.
4
5use super::{FifoWatermark, UartDevice, ValidUartPinout};
6use crate::dma::{EndlessReadTarget, ReadTarget};
7use crate::pac::uart0::RegisterBlock;
8use embedded_hal_0_2::serial::Read as Read02;
9use nb::Error::*;
10
11use embedded_hal_nb::serial::{Error, ErrorKind, ErrorType, Read};
12
13/// When there's a read error.
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15#[derive(Debug)]
16pub struct ReadError<'err> {
17    /// The type of error
18    pub err_type: ReadErrorType,
19
20    /// Reference to the data that was read but eventually discarded because of the error.
21    pub discarded: &'err [u8],
22}
23
24/// Possible types of read errors. See Chapter 4, Section 2 ยง8 - Table 436: "UARTDR Register"
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum ReadErrorType {
28    /// Triggered when the FIFO (or shift-register) is overflowed.
29    Overrun,
30
31    /// Triggered when a break is received
32    Break,
33
34    /// Triggered when there is a parity mismatch between what's received and our settings.
35    Parity,
36
37    /// Triggered when the received character didn't have a valid stop bit.
38    Framing,
39}
40
41impl Error for ReadErrorType {
42    fn kind(&self) -> ErrorKind {
43        match self {
44            ReadErrorType::Overrun => ErrorKind::Overrun,
45            ReadErrorType::Break => ErrorKind::Other,
46            ReadErrorType::Parity => ErrorKind::Parity,
47            ReadErrorType::Framing => ErrorKind::FrameFormat,
48        }
49    }
50}
51
52pub(crate) fn is_readable<D: UartDevice>(device: &D) -> bool {
53    device.uartfr().read().rxfe().bit_is_clear()
54}
55
56/// Enable/disable the rx/tx FIFO
57///
58/// Unfortunately, it's not possible to enable/disable rx/tx
59/// independently on this chip
60/// Default is false
61pub fn set_fifos(rb: &RegisterBlock, enable: bool) {
62    if enable {
63        rb.uartlcr_h().modify(|_r, w| w.fen().set_bit())
64    } else {
65        rb.uartlcr_h().modify(|_r, w| w.fen().clear_bit())
66    }
67}
68
69/// Set rx FIFO watermark
70///
71/// See DS: Table 423
72pub fn set_rx_watermark(rb: &RegisterBlock, watermark: FifoWatermark) {
73    let wm = match watermark {
74        FifoWatermark::Bytes4 => 0,
75        FifoWatermark::Bytes8 => 1,
76        FifoWatermark::Bytes16 => 2,
77        FifoWatermark::Bytes24 => 3,
78        FifoWatermark::Bytes28 => 4,
79    };
80    rb.uartifls()
81        .modify(|_r, w| unsafe { w.rxiflsel().bits(wm) });
82}
83
84/// Enables the Receive Interrupt.
85///
86/// The relevant UARTx IRQ will fire when there is data in the receive register.
87pub(crate) fn enable_rx_interrupt(rb: &RegisterBlock) {
88    // Access the UART Interrupt Mask Set/Clear register. Setting a bit
89    // high enables the interrupt.
90
91    // We set the RX interrupt, and the RX Timeout interrupt. This means
92    // we will get an interrupt when the RX FIFO level is triggered, or
93    // when the RX FIFO is non-empty, but 32-bit periods have passed with
94    // no further data. This means we don't have to interrupt on every
95    // single byte, but can make use of the hardware FIFO.
96    rb.uartimsc().modify(|_r, w| {
97        w.rxim().set_bit();
98        w.rtim().set_bit();
99        w
100    });
101}
102
103/// Disables the Receive Interrupt.
104pub(crate) fn disable_rx_interrupt(rb: &RegisterBlock) {
105    // Access the UART Interrupt Mask Set/Clear register. Setting a bit
106    // low disables the interrupt.
107
108    rb.uartimsc().modify(|_r, w| {
109        w.rxim().clear_bit();
110        w.rtim().clear_bit();
111        w
112    });
113}
114
115pub(crate) fn read_raw<'b, D: UartDevice>(
116    device: &D,
117    buffer: &'b mut [u8],
118) -> nb::Result<usize, ReadError<'b>> {
119    let mut bytes_read = 0;
120
121    Ok(loop {
122        if !is_readable(device) {
123            if bytes_read == 0 {
124                // The overrun error (OE) bit is checked separately as it
125                // doesn't really correspond to a specific byte we've read. If
126                // we don't do this here, the overrun error is hidden until the
127                // next byte turns up - which may never happen.
128                if device.uartrsr().read().oe().bit_is_set() {
129                    // We observed a FIFO overrun on an empty FIFO. Clear the
130                    // error otherwise it sticks.
131                    unsafe {
132                        device.uartrsr().write_with_zero(|w| w);
133                    }
134                    // Now report the error.
135                    //
136                    // Note that you will also get an overrun error on the first
137                    // byte that turns up after this error - we can't stop that
138                    // as we have no mutable state to indicate that it's already
139                    // been handled. But two overrun errors is better that none.
140                    return Err(Other(ReadError {
141                        err_type: ReadErrorType::Overrun,
142                        discarded: &buffer[..bytes_read],
143                    }));
144                } else {
145                    return Err(WouldBlock);
146                }
147            } else {
148                break bytes_read;
149            }
150        }
151
152        if bytes_read < buffer.len() {
153            let mut error: Option<ReadErrorType> = None;
154
155            let read = device.uartdr().read();
156
157            // If multiple status bits are set, report
158            // the most serious or most specific condition,
159            // in the following order of precedence:
160            // break > parity > framing
161            //
162            // overrun is last because the byte associated with it is still good.
163            if read.be().bit_is_set() {
164                error = Some(ReadErrorType::Break);
165            } else if read.pe().bit_is_set() {
166                error = Some(ReadErrorType::Parity);
167            } else if read.fe().bit_is_set() {
168                error = Some(ReadErrorType::Framing);
169            } else if read.oe().bit_is_set() {
170                error = Some(ReadErrorType::Overrun);
171                // if we get an overrun - there's still data there
172                buffer[bytes_read] = read.data().bits();
173                bytes_read += 1;
174            }
175
176            if let Some(err_type) = error {
177                return Err(Other(ReadError {
178                    err_type,
179                    discarded: &buffer[..bytes_read],
180                }));
181            }
182
183            buffer[bytes_read] = read.data().bits();
184            bytes_read += 1;
185        } else {
186            break bytes_read;
187        }
188    })
189}
190
191pub(crate) fn read_full_blocking<D: UartDevice>(
192    device: &D,
193    buffer: &mut [u8],
194) -> Result<(), ReadErrorType> {
195    let mut offset = 0;
196
197    while offset != buffer.len() {
198        offset += match read_raw(device, &mut buffer[offset..]) {
199            Ok(bytes_read) => bytes_read,
200            Err(e) => match e {
201                Other(inner) => return Err(inner.err_type),
202                WouldBlock => continue,
203            },
204        }
205    }
206
207    Ok(())
208}
209
210/// Half of an [`UartPeripheral`] that is only capable of reading. Obtained by calling [`UartPeripheral::split()`]
211///
212/// [`UartPeripheral`]: struct.UartPeripheral.html
213/// [`UartPeripheral::split()`]: struct.UartPeripheral.html#method.split
214pub struct Reader<D: UartDevice, P: ValidUartPinout<D>> {
215    pub(super) device: D,
216    pub(super) pins: P,
217    pub(super) read_error: Option<ReadErrorType>,
218}
219
220impl<D: UartDevice, P: ValidUartPinout<D>> Reader<D, P> {
221    /// Reads bytes from the UART.
222    /// This function reads as long as it can. As soon that the FIFO is empty, if :
223    /// - 0 bytes were read, a WouldBlock Error is returned
224    /// - some bytes were read, it is deemed to be a success
225    ///
226    /// Upon success, it will return how many bytes were read.
227    pub fn read_raw<'b>(&self, buffer: &'b mut [u8]) -> nb::Result<usize, ReadError<'b>> {
228        read_raw(&self.device, buffer)
229    }
230
231    /// Reads bytes from the UART.
232    /// This function blocks until the full buffer has been received.
233    pub fn read_full_blocking(&self, buffer: &mut [u8]) -> Result<(), ReadErrorType> {
234        read_full_blocking(&self.device, buffer)
235    }
236
237    /// Enables the Receive Interrupt.
238    ///
239    /// The relevant UARTx IRQ will fire when there is data in the receive register.
240    pub fn enable_rx_interrupt(&mut self) {
241        enable_rx_interrupt(&self.device)
242    }
243
244    /// Disables the Receive Interrupt.
245    pub fn disable_rx_interrupt(&mut self) {
246        disable_rx_interrupt(&self.device)
247    }
248}
249
250impl<D: UartDevice, P: ValidUartPinout<D>> embedded_io::ErrorType for Reader<D, P> {
251    type Error = ReadErrorType;
252}
253
254impl<D: UartDevice, P: ValidUartPinout<D>> embedded_io::Read for Reader<D, P> {
255    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
256        // If the last read stored an error, report it now
257        if let Some(err) = self.read_error.take() {
258            return Err(err);
259        }
260        match nb::block!(self.read_raw(buf)) {
261            Ok(bytes_read) => Ok(bytes_read),
262            Err(err) if !err.discarded.is_empty() => {
263                // If an error was reported but some bytes were already read,
264                // return the data now and store the error for the next
265                // invocation.
266                self.read_error = Some(err.err_type);
267                Ok(err.discarded.len())
268            }
269            Err(err) => Err(err.err_type),
270        }
271    }
272}
273
274impl<D: UartDevice, P: ValidUartPinout<D>> embedded_io::ReadReady for Reader<D, P> {
275    fn read_ready(&mut self) -> Result<bool, Self::Error> {
276        Ok(is_readable(&self.device))
277    }
278}
279
280impl<D: UartDevice, P: ValidUartPinout<D>> Read02<u8> for Reader<D, P> {
281    type Error = ReadErrorType;
282
283    fn read(&mut self) -> nb::Result<u8, Self::Error> {
284        let byte: &mut [u8] = &mut [0; 1];
285
286        match self.read_raw(byte) {
287            Ok(_) => Ok(byte[0]),
288            Err(e) => match e {
289                Other(inner) => Err(Other(inner.err_type)),
290                WouldBlock => Err(WouldBlock),
291            },
292        }
293    }
294}
295
296// Safety: This only reads from the RX fifo, so it doesn't
297// interact with rust-managed memory.
298unsafe impl<D: UartDevice, P: ValidUartPinout<D>> ReadTarget for Reader<D, P> {
299    type ReceivedWord = u8;
300
301    fn rx_treq() -> Option<u8> {
302        Some(D::rx_dreq())
303    }
304
305    fn rx_address_count(&self) -> (u32, u32) {
306        (self.device.uartdr().as_ptr() as u32, u32::MAX)
307    }
308
309    fn rx_increment(&self) -> bool {
310        false
311    }
312}
313
314impl<D: UartDevice, P: ValidUartPinout<D>> EndlessReadTarget for Reader<D, P> {}
315
316impl<D: UartDevice, P: ValidUartPinout<D>> ErrorType for Reader<D, P> {
317    type Error = ReadErrorType;
318}
319
320impl<D: UartDevice, P: ValidUartPinout<D>> Read<u8> for Reader<D, P> {
321    fn read(&mut self) -> nb::Result<u8, Self::Error> {
322        let byte: &mut [u8] = &mut [0; 1];
323
324        match self.read_raw(byte) {
325            Ok(_) => Ok(byte[0]),
326            Err(e) => match e {
327                Other(inner) => Err(Other(inner.err_type)),
328                WouldBlock => Err(WouldBlock),
329            },
330        }
331    }
332}