1use core::marker::PhantomData;
2
3use arbitrary_int::{u5, u6, u18};
4
5cfg_if::cfg_if! {
6 if #[cfg(feature = "vor1x")] {
7 pub const BASE_ADDR_0: usize = 0x4004_0000;
9 pub const BASE_ADDR_1: usize = 0x4004_1000;
11 } else if #[cfg(feature = "vor4x")] {
12 pub const BASE_ADDR_0: usize = 0x4002_4000;
14 pub const BASE_ADDR_1: usize = 0x4002_5000;
16 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 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 #[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 #[bit(0, rw)]
181 rx: bool,
182 #[bit(1, rw)]
184 rx_status: bool,
185 #[bit(2, rw)]
187 rx_timeout: bool,
188
189 #[bit(4, rw)]
191 tx: bool,
192 #[bit(5, rw)]
194 tx_status: bool,
195 #[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 #[bit(0, r)]
206 rx: bool,
207 #[bit(1, r)]
209 rx_status: bool,
210 #[bit(2, r)]
212 rx_timeout: bool,
213
214 #[bit(4, r)]
216 tx: bool,
217 #[bit(5, r)]
219 tx_status: bool,
220 #[bit(6, r)]
222 tx_empty: bool,
223 #[bit(7, r)]
224 tx_cts: bool,
225}
226
227#[bitbybit::bitfield(u32, default = 0x0)]
229#[derive(Debug)]
230pub struct InterruptClear {
231 #[bit(1, w)]
232 rx_overrun: bool,
233 #[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 #[bits(8..=12, r)]
251 rx_fifo: u5,
252 #[bits(16..=23, r)]
253 tx_state: u8,
254 #[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 #[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}