vorago_shared_hal/uart/
regs.rs

1use core::marker::PhantomData;
2
3use arbitrary_int::{u5, u6, u18};
4
5cfg_if::cfg_if! {
6    if #[cfg(feature = "vor1x")] {
7        /// UART A base address
8        pub const BASE_ADDR_0: usize = 0x4004_0000;
9        /// UART B base address
10        pub const BASE_ADDR_1: usize = 0x4004_1000;
11    } else if #[cfg(feature = "vor4x")] {
12        /// UART 0 base address
13        pub const BASE_ADDR_0: usize = 0x4002_4000;
14        /// UART 1 base address
15        pub const BASE_ADDR_1: usize = 0x4002_5000;
16        /// UART 2 base address
17        pub const BASE_ADDR_2: usize = 0x4001_7000;
18    }
19}
20
21#[derive(Debug, PartialEq, Eq, Clone, Copy)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23pub enum Bank {
24    Uart0 = 0,
25    Uart1 = 1,
26    #[cfg(feature = "vor4x")]
27    Uart2 = 2,
28}
29
30impl Bank {
31    /// Unsafely steal the GPIO peripheral block for the given port.
32    ///
33    /// # Safety
34    ///
35    /// Circumvents ownership and safety guarantees by the HAL.
36    pub unsafe fn steal_regs(&self) -> MmioUart<'static> {
37        Uart::new_mmio(*self)
38    }
39
40    #[cfg(feature = "vor4x")]
41    pub const fn interrupt_id_tx(&self) -> va416xx::Interrupt {
42        match self {
43            Bank::Uart0 => va416xx::Interrupt::UART0_TX,
44            Bank::Uart1 => va416xx::Interrupt::UART1_TX,
45            Bank::Uart2 => va416xx::Interrupt::UART2_TX,
46        }
47    }
48
49    #[cfg(feature = "vor4x")]
50    pub const fn interrupt_id_rx(&self) -> va416xx::Interrupt {
51        match self {
52            Bank::Uart0 => va416xx::Interrupt::UART0_RX,
53            Bank::Uart1 => va416xx::Interrupt::UART1_RX,
54            Bank::Uart2 => va416xx::Interrupt::UART2_RX,
55        }
56    }
57}
58
59#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
60pub struct Data {
61    #[bit(15, rw)]
62    dparity: bool,
63    #[bits(0..=7, rw)]
64    value: u8,
65}
66
67#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_bitfields(feature = "defmt"))]
68pub struct Enable {
69    #[bit(1, rw)]
70    tx: bool,
71    #[bit(0, rw)]
72    rx: bool,
73}
74
75#[bitbybit::bitenum(u1, exhaustive = true)]
76#[derive(Debug, PartialEq, Eq)]
77#[cfg_attr(feature = "defmt", derive(defmt::Format))]
78pub enum Stopbits {
79    One = 0,
80    Two = 1,
81}
82
83#[bitbybit::bitenum(u2, exhaustive = true)]
84#[derive(Debug, PartialEq, Eq)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86pub enum WordSize {
87    Five = 0b00,
88    Six = 0b01,
89    Seven = 0b10,
90    Eight = 0b11,
91}
92
93#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_fields(feature = "defmt"))]
94pub struct Control {
95    #[bit(11, rw)]
96    baud8: bool,
97    #[bit(10, rw)]
98    auto_rts: bool,
99    #[bit(9, rw)]
100    def_rts: bool,
101    #[bit(8, rw)]
102    auto_cts: bool,
103    #[bit(7, rw)]
104    loopback_block: bool,
105    #[bit(6, rw)]
106    loopback: bool,
107    #[bits(4..=5, rw)]
108    wordsize: WordSize,
109    #[bit(3, rw)]
110    stopbits: Stopbits,
111    #[bit(2, rw)]
112    parity_manual: bool,
113    #[bit(1, rw)]
114    parity_even: bool,
115    #[bit(0, rw)]
116    parity_enable: bool,
117}
118
119#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_bitfields(feature = "defmt"))]
120pub struct ClockScale {
121    #[bits(6..=23, rw)]
122    int: u18,
123    #[bits(0..=5, rw)]
124    frac: u6,
125}
126
127#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
128pub struct RxStatus {
129    #[bit(15, r)]
130    rx_rtsn: bool,
131    #[bit(9, r)]
132    rx_addr9: bool,
133    #[bit(8, r)]
134    busy_break: bool,
135    #[bit(7, r)]
136    break_error: bool,
137    #[bit(6, r)]
138    parity_error: bool,
139    #[bit(5, r)]
140    framing_error: bool,
141    #[bit(4, r)]
142    overrun_error: bool,
143    #[bit(3, r)]
144    timeout: bool,
145    #[bit(2, r)]
146    busy: bool,
147    #[bit(1, r)]
148    not_full: bool,
149    #[bit(0, r)]
150    data_available: bool,
151}
152
153#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
154pub struct TxStatus {
155    #[bit(15, r)]
156    tx_ctsn: bool,
157    #[bit(3, r)]
158    wr_lost: bool,
159    #[bit(2, r)]
160    tx_busy: bool,
161    #[bit(1, r)]
162    write_busy: bool,
163    /// There is space in the FIFO to write data.
164    #[bit(0, r)]
165    ready: bool,
166}
167
168#[bitbybit::bitfield(u32, default = 0x0)]
169#[derive(Debug)]
170pub struct FifoClear {
171    #[bit(1, w)]
172    tx: bool,
173    #[bit(0, w)]
174    rx: bool,
175}
176
177#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
178pub struct InterruptControl {
179    /// Generate an interrrupt when the RX FIFO is at least half-full (FIFO count >= trigger level)
180    #[bit(0, rw)]
181    rx: bool,
182    /// Interrupts for status conditions (overrun, framing, parity and break)
183    #[bit(1, rw)]
184    rx_status: bool,
185    /// Interrupt on timeout conditions.
186    #[bit(2, rw)]
187    rx_timeout: bool,
188
189    /// Generates an interrupt when the TX FIFO is at least half-empty (FIFO count < trigger level)
190    #[bit(4, rw)]
191    tx: bool,
192    /// Generates an interrupt on TX FIFO overflow.
193    #[bit(5, rw)]
194    tx_status: bool,
195    /// Generates an interrupt when the transmit FIFO is empty and TXBUSY is 0.
196    #[bit(6, rw)]
197    tx_empty: bool,
198    #[bit(7, rw)]
199    tx_cts: bool,
200}
201
202#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
203pub struct InterruptStatus {
204    /// Generate an interrrupt when the RX FIFO is at least half-full (FIFO count >= trigger level)
205    #[bit(0, r)]
206    rx: bool,
207    /// Interrupts for status conditions (overrun, framing, parity and break)
208    #[bit(1, r)]
209    rx_status: bool,
210    /// Interrupt on timeout conditions.
211    #[bit(2, r)]
212    rx_timeout: bool,
213
214    /// Generates an interrupt when the TX FIFO is at least half-empty (FIFO count < trigger level)
215    #[bit(4, r)]
216    tx: bool,
217    /// Generates an interrupt on TX FIFO overflow.
218    #[bit(5, r)]
219    tx_status: bool,
220    /// Generates an interrupt when the transmit FIFO is empty and TXBUSY is 0.
221    #[bit(6, r)]
222    tx_empty: bool,
223    #[bit(7, r)]
224    tx_cts: bool,
225}
226
227/// As specified in the VA416x0 Programmers Guide, only the RX overflow bit can be cleared.
228#[bitbybit::bitfield(u32, default = 0x0)]
229#[derive(Debug)]
230pub struct InterruptClear {
231    #[bit(1, w)]
232    rx_overrun: bool,
233    /// Not sure if this does anything, the programmer guides are not consistent on this..
234    #[bit(5, w)]
235    tx_overrun: bool,
236}
237
238#[bitbybit::bitfield(u32)]
239#[derive(Debug)]
240pub struct FifoTrigger {
241    #[bits(0..=4, rw)]
242    level: u5,
243}
244
245#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
246pub struct State {
247    #[bits(0..=7, r)]
248    rx_state: u8,
249    /// Data count.
250    #[bits(8..=12, r)]
251    rx_fifo: u5,
252    #[bits(16..=23, r)]
253    tx_state: u8,
254    /// Data count.
255    #[bits(24..=28, r)]
256    tx_fifo: u5,
257}
258
259#[derive(derive_mmio::Mmio)]
260#[mmio(no_ctors)]
261#[repr(C)]
262pub struct Uart {
263    data: Data,
264    enable: Enable,
265    ctrl: Control,
266    clkscale: ClockScale,
267    #[mmio(PureRead)]
268    rx_status: RxStatus,
269    #[mmio(PureRead)]
270    tx_status: TxStatus,
271    #[mmio(Write)]
272    fifo_clr: FifoClear,
273    #[mmio(Write)]
274    txbreak: u32,
275    addr9: u32,
276    addr9mask: u32,
277    irq_enabled: InterruptControl,
278    #[mmio(PureRead)]
279    irq_raw: InterruptStatus,
280    #[mmio(PureRead)]
281    irq_status: InterruptStatus,
282    #[mmio(Write)]
283    irq_clr: InterruptClear,
284    rx_fifo_trigger: FifoTrigger,
285    tx_fifo_trigger: FifoTrigger,
286    rx_fifo_rts_trigger: u32,
287    #[mmio(PureRead)]
288    state: State,
289    _reserved: [u32; 0x3ED],
290    /// Vorago 1x value: 0x0112_07E1. Vorago 4x value: 0x0212_07E9
291    #[mmio(PureRead)]
292    perid: u32,
293}
294
295static_assertions::const_assert_eq!(core::mem::size_of::<Uart>(), 0x1000);
296
297impl Uart {
298    fn new_mmio_at(base: usize) -> MmioUart<'static> {
299        MmioUart {
300            ptr: base as *mut _,
301            phantom: PhantomData,
302        }
303    }
304
305    pub fn new_mmio(bank: Bank) -> MmioUart<'static> {
306        match bank {
307            Bank::Uart0 => Self::new_mmio_at(BASE_ADDR_0),
308            Bank::Uart1 => Self::new_mmio_at(BASE_ADDR_1),
309            #[cfg(feature = "vor4x")]
310            Bank::Uart2 => Self::new_mmio_at(BASE_ADDR_2),
311        }
312    }
313}