Skip to main content

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