pl011_uart/
lib.rs

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#![no_std]
10#![deny(clippy::undocumented_unsafe_blocks)]
11#![deny(unsafe_op_in_unsafe_fn)]
12
13use bitflags::bitflags;
14use core::fmt;
15use core::hint::spin_loop;
16use embedded_io::{ErrorKind, ErrorType, Read, ReadReady, Write, WriteReady};
17
18bitflags! {
19    /// Flags from Data Register
20    #[repr(transparent)]
21    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
22    struct Data: u16 {
23        /// Data character.
24        const DATA = 0b11111111;
25        /// Framing error.
26        const FE = 1 << 8;
27        /// Parity error.
28        const PE = 1 << 9;
29        /// Break error.
30        const BE = 1 << 10;
31        /// Overrun error.
32        const OE = 1 << 11;
33    }
34}
35
36bitflags! {
37    /// Flags from the UART flag register.
38    #[repr(transparent)]
39    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
40    struct Flags: u16 {
41        /// Clear to send.
42        const CTS = 1 << 0;
43        /// Data set ready.
44        const DSR = 1 << 1;
45        /// Data carrier detect.
46        const DCD = 1 << 2;
47        /// UART busy transmitting data.
48        const BUSY = 1 << 3;
49        /// Receive FIFO is empty.
50        const RXFE = 1 << 4;
51        /// Transmit FIFO is full.
52        const TXFF = 1 << 5;
53        /// Receive FIFO is full.
54        const RXFF = 1 << 6;
55        /// Transmit FIFO is empty.
56        const TXFE = 1 << 7;
57        /// Ring indicator.
58        const RI = 1 << 8;
59    }
60}
61
62bitflags! {
63    /// Flags from the UART Receive Status Register / Error Clear Register.
64    #[repr(transparent)]
65    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
66    struct ReceiveStatus: u16 {
67        /// Framing error.
68        const FE = 1 << 0;
69        /// Parity error.
70        const PE = 1 << 1;
71        /// Break error.
72        const BE = 1 << 2;
73        /// Overrun error.
74        const OE = 1 << 3;
75    }
76}
77
78bitflags! {
79    /// Flags from the UART Control Register.
80    #[repr(transparent)]
81    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
82    struct Control: u16 {
83        /// UART Enable.
84        const UARTEN = 1 << 0;
85        /// Serial InfraRed (SIR) Enable.
86        const SIREN = 1 << 1;
87        /// Serial InfraRed (SIR) Low-power.
88        const SIRLP = 1 << 2;
89        /// Bits 6:3 are reserved.
90        /// Loopback Enable.
91        const LBE = 1 << 7;
92        /// Transmit Enable.
93        const TXE = 1 << 8;
94        /// Receive Enable.
95        const RXE = 1 << 9;
96        /// Data Transmit Ready.
97        const DTR = 1 << 10;
98        /// Request To Send.
99        const RTS = 1 << 11;
100        /// Complement of nUARTOut1
101        const OUT1 = 1 << 12;
102        /// Complement of nUARTOut2
103        const OUT2 = 1 << 13;
104        /// Request To Send (RTS) Hardware Flow Control Enable.
105        const RTSEN = 1 << 14;
106        /// Clear To Send (CTS) Hardware Flow Control Enable.
107        const CTSEN = 1 << 15;
108    }
109}
110
111#[repr(C, align(4))]
112struct Registers {
113    /// Data Register.
114    dr: u16,
115    _reserved0: [u8; 2],
116    /// Receive Status Register / Error Clear Register.
117    rsr: ReceiveStatus,
118    _reserved1: [u8; 19],
119    /// Flag Register.
120    fr: Flags,
121    _reserved2: [u8; 6],
122    /// IrDA Low-Power Counter Register.
123    ilpr: u8,
124    _reserved3: [u8; 3],
125    /// Integer Baud Rate Register.
126    ibrd: u16,
127    _reserved4: [u8; 2],
128    /// Fractional Baud Rate Register.
129    fbrd: u8,
130    _reserved5: [u8; 3],
131    /// Line Control Register.
132    lcr_h: u8,
133    _reserved6: [u8; 3],
134    /// Control Register.
135    cr: Control,
136    _reserved7: [u8; 3],
137    /// Interrupt FIFO Level Select Register.
138    ifls: u8,
139    _reserved8: [u8; 3],
140    /// Interrupt Mask Set/Clear Register.
141    imsc: u16,
142    _reserved9: [u8; 2],
143    /// Raw Interrupt Status Register.
144    ris: u16,
145    _reserved10: [u8; 2],
146    /// Masked Interrupt Status Register.
147    mis: u16,
148    _reserved11: [u8; 2],
149    /// Interrupt Clear Register.
150    icr: u16,
151    _reserved12: [u8; 2],
152    /// DMA Control Register.
153    dmacr: u8,
154    _reserved13: [u8; 3],
155}
156
157/// Errors which may occur reading from a PL011 UART.
158#[derive(Copy, Clone, Debug, Eq, PartialEq, thiserror::Error)]
159pub enum Error {
160    /// Break condition detected.
161    #[error("Break condition detected")]
162    Break,
163    /// The received character did not have a valid stop bit.
164    #[error("Framing error, received character didn't have a valid stop bit")]
165    Framing,
166    /// Data was received while the FIFO was already full.
167    #[error("Overrun, data received while the FIFO was already full")]
168    Overrun,
169    /// Parity of the received data character did not match the selected parity.
170    #[error("Parity of the received data character did not match the selected parity")]
171    Parity,
172}
173
174impl embedded_io::Error for Error {
175    fn kind(&self) -> ErrorKind {
176        match self {
177            Self::Break | Self::Overrun => ErrorKind::Other,
178            Self::Framing | Self::Parity => ErrorKind::InvalidData,
179        }
180    }
181}
182
183/// Driver for a PL011 UART.
184#[derive(Debug)]
185pub struct Uart {
186    registers: *mut Registers,
187}
188
189impl Uart {
190    /// Constructs a new instance of the UART driver for a PL011 device at the
191    /// given base address.
192    ///
193    /// # Safety
194    ///
195    /// The given base address must point to the 14 MMIO control registers of a
196    /// PL011 device, which must be mapped into the address space of the process
197    /// as device memory and not have any other aliases.
198    pub unsafe fn new(base_address: *mut u32) -> Self {
199        Self {
200            registers: base_address as *mut Registers,
201        }
202    }
203
204    /// Initializes PL011 UART.
205    ///
206    /// clock: Uart clock in Hz.
207    /// baud_rate: Baud rate.
208    pub fn init(&mut self, clock: u32, baud_rate: u32) {
209        let divisor = (clock << 2) / baud_rate;
210
211        // SAFETY: self.registers points to the control registers of a PL011 device which is
212        // appropriately mapped, as promised by the caller of `Uart::new`.
213        unsafe {
214            // Disable UART before programming.
215            let mut cr: Control = (&raw mut (*self.registers).cr).read_volatile();
216            cr &= !Control::UARTEN;
217            (&raw mut (*self.registers).cr).write_volatile(cr);
218            // Program Integer Baud Rate.
219            (&raw mut (*self.registers).ibrd).write_volatile((divisor >> 6).try_into().unwrap());
220            // Program Fractional Baud Rate.
221            (&raw mut (*self.registers).fbrd).write_volatile((divisor & 0x3F).try_into().unwrap());
222            // Clear any pending errors.
223            (&raw mut (*self.registers).rsr).write_volatile(ReceiveStatus::empty());
224            // Enable UART.
225            (&raw mut (*self.registers).cr)
226                .write_volatile(Control::RXE | Control::TXE | Control::UARTEN);
227        }
228    }
229
230    /// Writes a single byte to the UART.
231    ///
232    /// This blocks until there is space in the transmit FIFO or holding register, but returns as
233    /// soon as the byte has been written to the transmit FIFO or holding register. It doesn't wait
234    /// for the byte to be sent.
235    pub fn write_byte(&mut self, byte: u8) {
236        // Wait until there is room in the TX buffer.
237        while self.flags().contains(Flags::TXFF) {
238            spin_loop();
239        }
240
241        // SAFETY: self.registers points to the control registers of a PL011 device which is
242        // appropriately mapped, as promised by the caller of `Uart::new`.
243        unsafe {
244            // Write to the TX buffer.
245            (&raw mut (*self.registers).dr).write_volatile(u16::from(byte));
246        }
247    }
248
249    /// Returns whether the UART is currently transmitting data.
250    ///
251    /// This will be true immediately after calling [`write_byte`](Self::write_byte).
252    pub fn is_transmitting(&self) -> bool {
253        self.flags().contains(Flags::BUSY)
254    }
255
256    /// Reads and returns a pending byte, or `None` if nothing has been
257    /// received.
258    pub fn read_byte(&mut self) -> Result<Option<u8>, Error> {
259        if self.flags().contains(Flags::RXFE) {
260            Ok(None)
261        } else {
262            // SAFETY: self.registers points to the control registers of a PL011 device which is
263            // appropriately mapped, as promised by the caller of `Uart::new`.
264            let data = unsafe { (&raw const (*self.registers).dr).read_volatile() };
265            let error_status = Data::from_bits_truncate(data);
266            if error_status.contains(Data::FE) {
267                return Err(Error::Framing);
268            }
269            if error_status.contains(Data::PE) {
270                return Err(Error::Parity);
271            }
272            if error_status.contains(Data::BE) {
273                return Err(Error::Break);
274            }
275            if error_status.contains(Data::OE) {
276                return Err(Error::Overrun);
277            }
278            Ok(Some(data as u8))
279        }
280    }
281
282    fn flags(&self) -> Flags {
283        // SAFETY: self.registers points to the control registers of a PL011 device which is
284        // appropriately mapped, as promised by the caller of `Uart::new`.
285        unsafe { (&raw const (*self.registers).fr).read_volatile() }
286    }
287}
288
289impl fmt::Write for Uart {
290    fn write_str(&mut self, s: &str) -> fmt::Result {
291        for c in s.as_bytes() {
292            self.write_byte(*c);
293        }
294        Ok(())
295    }
296}
297
298// SAFETY: `Uart` just contains a pointer to device memory, which can be accessed from any context.
299unsafe impl Send for Uart {}
300
301// SAFETY: Methods on `&Uart` don't allow changing any state so are safe to call concurrently from
302// any context.
303unsafe impl Sync for Uart {}
304
305impl ErrorType for Uart {
306    type Error = Error;
307}
308
309impl Write for Uart {
310    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
311        if buf.is_empty() {
312            Ok(0)
313        } else {
314            self.write_byte(buf[0]);
315            Ok(1)
316        }
317    }
318
319    fn flush(&mut self) -> Result<(), Self::Error> {
320        while self.is_transmitting() {
321            spin_loop();
322        }
323        Ok(())
324    }
325}
326
327impl WriteReady for Uart {
328    fn write_ready(&mut self) -> Result<bool, Self::Error> {
329        Ok(!self.flags().contains(Flags::TXFF))
330    }
331}
332
333impl Read for Uart {
334    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
335        if buf.is_empty() {
336            return Ok(0);
337        }
338
339        loop {
340            if let Some(byte) = self.read_byte()? {
341                buf[0] = byte;
342                return Ok(1);
343            }
344        }
345    }
346}
347
348impl ReadReady for Uart {
349    fn read_ready(&mut self) -> Result<bool, Self::Error> {
350        Ok(!self.flags().contains(Flags::RXFE))
351    }
352}