arm_pl011_uart/
embedded_io.rs

1// SPDX-FileCopyrightText: Copyright The arm-pl011-uart Contributors.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use crate::{Error, Uart};
5use embedded_io::{ErrorKind, ErrorType, Read, ReadReady, Write, WriteReady};
6
7impl ErrorType for Uart<'_> {
8    type Error = Error;
9}
10
11impl embedded_io::Error for Error {
12    fn kind(&self) -> ErrorKind {
13        match self {
14            Self::Break | Self::Overrun => ErrorKind::Other,
15            Self::Framing | Self::Parity => ErrorKind::InvalidData,
16            Self::InvalidParameter => ErrorKind::InvalidInput,
17        }
18    }
19}
20
21impl Write for Uart<'_> {
22    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
23        let mut bytes_written = 0;
24        if !buf.is_empty() {
25            // Wait until there is room in the TX buffer.
26            while self.is_tx_fifo_full() {}
27
28            // Write until the TX buffer is full or we run out of bytes to write. The caller will
29            // take care of retrying until the full buffer is written.
30            for byte in buf {
31                self.write_word(*byte);
32                bytes_written += 1;
33                if self.is_tx_fifo_full() {
34                    break;
35                }
36            }
37        }
38        Ok(bytes_written)
39    }
40
41    fn flush(&mut self) -> Result<(), Self::Error> {
42        while self.is_busy() {}
43        Ok(())
44    }
45}
46
47impl WriteReady for Uart<'_> {
48    fn write_ready(&mut self) -> Result<bool, Self::Error> {
49        Ok(!self.is_tx_fifo_full())
50    }
51}
52
53impl Read for Uart<'_> {
54    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
55        if buf.is_empty() {
56            Ok(0)
57        } else {
58            // Wait until a byte is available to read.
59            loop {
60                // Read a single byte. No need to wait for more, the caller will retry until it has
61                // as many as it wants.
62                if let Some(byte) = self.read_word()? {
63                    buf[0] = byte;
64                    return Ok(1);
65                }
66            }
67        }
68    }
69}
70
71impl ReadReady for Uart<'_> {
72    fn read_ready(&mut self) -> Result<bool, Self::Error> {
73        Ok(!self.is_rx_fifo_empty())
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use crate::tests::FakePL011Registers;
81
82    #[test]
83    fn error_kind() {
84        assert_eq!(ErrorKind::Other, embedded_io::Error::kind(&Error::Break));
85
86        assert_eq!(
87            ErrorKind::InvalidData,
88            embedded_io::Error::kind(&Error::Framing)
89        );
90
91        assert_eq!(
92            ErrorKind::InvalidInput,
93            embedded_io::Error::kind(&Error::InvalidParameter)
94        );
95    }
96
97    #[test]
98    fn embeddedio_write_empty() {
99        let mut regs = FakePL011Registers::new();
100        let mut uart = regs.uart_for_test();
101        assert_eq!(Ok(0), Write::write(&mut uart, &[]));
102        assert_eq!(Ok(()), Write::flush(&mut uart));
103    }
104
105    #[test]
106    fn embeddedio_write() {
107        let mut regs = FakePL011Registers::new();
108        let mut uart = regs.uart_for_test();
109        assert_eq!(Ok(2), Write::write(&mut uart, &[1, 2]));
110        assert_eq!(Ok(()), Write::write_all(&mut uart, &[1, 2]));
111        assert_eq!(Ok(()), Write::flush(&mut uart));
112    }
113
114    #[test]
115    fn embeddedio_write_fifo_full() {
116        let mut regs = FakePL011Registers::new();
117        {
118            let mut uart = regs.uart_for_test();
119            assert_eq!(Ok(true), uart.write_ready());
120        }
121
122        {
123            regs.reg_write(0x018, 1 << 5);
124            let mut uart = regs.uart_for_test();
125            assert_eq!(Ok(false), uart.write_ready());
126        }
127    }
128
129    #[test]
130    fn embeddedio_read_empty() {
131        let mut regs = FakePL011Registers::new();
132        let mut uart = regs.uart_for_test();
133        let mut data = [];
134        assert_eq!(Ok(0), Read::read(&mut uart, &mut data));
135    }
136
137    #[test]
138    fn embeddedio_read() {
139        let mut regs = FakePL011Registers::new();
140        let mut uart = regs.uart_for_test();
141        let mut data = [0u8; 2];
142        assert_eq!(Ok(1), Read::read(&mut uart, &mut data));
143        assert_eq!(data, [0, 0]);
144        assert_eq!(Ok(()), Read::read_exact(&mut uart, &mut data));
145        assert_eq!(data, [0, 0]);
146    }
147
148    #[test]
149    fn embeddedio_read_fifo_empty() {
150        let mut regs = FakePL011Registers::new();
151        {
152            let mut uart = regs.uart_for_test();
153            assert_eq!(Ok(true), uart.read_ready());
154        }
155
156        {
157            regs.reg_write(0x018, 1 << 4);
158            let mut uart = regs.uart_for_test();
159            assert_eq!(Ok(false), uart.read_ready());
160        }
161    }
162}