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}