safe_mmio_example/
lib.rs

1//! # safe-mmio-example
2//!
3//! A very basic peripheral example using safe-mmio
4
5#![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
15/// UART parity
16pub enum Parity {
17    /// No Parity
18    None,
19    /// Odd Parity
20    Odd,
21    /// Even Parity
22    Even,
23}
24
25/// Represents a UART
26pub struct Uart<'a> {
27    regs: UniqueMmioPointer<'a, UartRegisters>,
28}
29
30impl<'a> Uart<'a> {
31    /// Create a UART driver, with the UART at the given address
32    pub const fn new(regs: UniqueMmioPointer<'a, UartRegisters>) -> Uart<'a> {
33        Uart { regs }
34    }
35
36    /// Configure the UART
37    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    /// Transmit a byte
53    ///
54    /// Blocks until space available
55    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/// Describes the UART's registers
64#[derive(Clone, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
65#[repr(C, align(4))]
66pub struct UartRegisters {
67    /// Data FIFO
68    ///
69    /// * Read here to get a byte from the FIFO
70    /// * Write here to put a byte into the FIFO
71    pub fifo: ReadWrite<u32>,
72    /// Control Register
73    ///
74    /// Adjust various UART settings
75    pub control: ReadWrite<Control>,
76    /// Status Register
77    ///
78    /// Read-only UART status
79    pub status: ReadPure<Status>,
80}
81
82/// Control Register
83#[repr(transparent)]
84#[derive(Copy, Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
85pub struct Control(u32);
86
87/// Status Register
88#[repr(transparent)]
89#[derive(Copy, Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)]
90pub struct Status(u32);
91
92bitflags! {
93    impl Control: u32 {
94        /// Is this peripheral enabled
95        const ENABLE = 1 << 0;
96        /// Baud Rate
97        const BAUD_RATE = 0x7F_FFFF << 1;
98        /// Parity Enabled
99        const PARITY_ENABLE = 0b01 << 24;
100        /// Even Parity
101        const PARITY_EVEN = 0b10 << 24;
102    }
103
104    impl Status: u32 {
105        /// Does the RX FIFO have data?
106        const RX_READY = 0b10;
107        /// Does the TX FIFO have data?
108        const TX_READY = 0b01;
109    }
110}