1#![no_std]
6#![deny(missing_docs)]
7
8use bitflags::bitflags;
9use safe_mmio::{
10 UniqueMmioPointer, field,
11 fields::{ReadPure, ReadWrite},
12};
13use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
14
15pub enum Parity {
17 None,
19 Odd,
21 Even,
23}
24
25pub struct Uart<'a> {
27 regs: UniqueMmioPointer<'a, UartRegisters>,
28}
29
30impl<'a> Uart<'a> {
31 pub const fn new(regs: UniqueMmioPointer<'a, UartRegisters>) -> Uart<'a> {
33 Uart { regs }
34 }
35
36 pub fn configure(&mut self, enabled: bool, baud: u32, parity: Parity) {
38 let p = match parity {
39 Parity::None => Control::empty(),
40 Parity::Odd => Control::PARITY_ENABLE,
41 Parity::Even => Control::PARITY_ENABLE | Control::PARITY_EVEN,
42 };
43 let en = if enabled {
44 Control::ENABLE
45 } else {
46 Control::empty()
47 };
48 let baud = Control::from_bits((baud << 1) & Control::BAUD_RATE.bits()).unwrap();
49 field!(self.regs, control).write(p | en | baud);
50 }
51
52 pub fn transmit(&mut self, byte: u8) {
56 while !field!(self.regs, status).read().contains(Status::TX_READY) {
57 core::hint::spin_loop();
58 }
59 field!(self.regs, fifo).write(byte as u32);
60 }
61}
62
63#[derive(Clone, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
65#[repr(C, align(4))]
66pub struct UartRegisters {
67 pub fifo: ReadWrite<u32>,
72 pub control: ReadWrite<Control>,
76 pub status: ReadPure<Status>,
80}
81
82#[repr(transparent)]
84#[derive(Copy, Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
85pub struct Control(u32);
86
87#[repr(transparent)]
89#[derive(Copy, Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
90pub struct Status(u32);
91
92bitflags! {
93 impl Control: u32 {
94 const ENABLE = 1 << 0;
96 const BAUD_RATE = 0x7F_FFFF << 1;
98 const PARITY_ENABLE = 0b01 << 24;
100 const PARITY_EVEN = 0b10 << 24;
102 }
103
104 impl Status: u32 {
105 const RX_READY = 0b10;
107 const TX_READY = 0b01;
109 }
110}