1#![no_std]
17#![cfg_attr(docsrs, feature(doc_cfg))]
18#![deny(missing_docs)]
19
20use core::convert::Infallible;
21use registers::Control;
22pub mod registers;
23
24pub mod tx;
25pub use tx::*;
26
27pub mod rx;
28pub use rx::*;
29
30pub mod tx_async;
31pub use tx_async::*;
32
33pub const FIFO_DEPTH: usize = 16;
35
36#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
38pub struct RxErrorsCounted {
39 parity: u8,
40 frame: u8,
41 overrun: u8,
42}
43
44impl RxErrorsCounted {
45 pub const fn new() -> Self {
47 Self {
48 parity: 0,
49 frame: 0,
50 overrun: 0,
51 }
52 }
53
54 pub const fn parity(&self) -> u8 {
56 self.parity
57 }
58
59 pub const fn frame(&self) -> u8 {
61 self.frame
62 }
63
64 pub const fn overrun(&self) -> u8 {
66 self.overrun
67 }
68
69 pub fn has_errors(&self) -> bool {
71 self.parity > 0 || self.frame > 0 || self.overrun > 0
72 }
73}
74
75pub struct AxiUartlite {
77 rx: Rx,
78 tx: Tx,
79 errors: RxErrorsCounted,
80}
81
82impl AxiUartlite {
83 pub const unsafe fn new(base_addr: u32) -> Self {
95 let regs = unsafe { registers::Registers::new_mmio_at(base_addr as usize) };
96 Self {
97 rx: Rx {
98 regs: unsafe { regs.clone() },
99 errors: None,
100 },
101 tx: Tx { regs, errors: None },
102 errors: RxErrorsCounted::new(),
103 }
104 }
105
106 #[inline(always)]
108 pub const fn regs(&mut self) -> &mut registers::MmioRegisters<'static> {
109 &mut self.tx.regs
110 }
111
112 #[inline]
116 pub fn write_fifo(&mut self, data: u8) -> nb::Result<(), Infallible> {
117 self.tx.write_fifo(data).unwrap();
118 if let Some(errors) = self.tx.errors {
119 self.handle_status_reg_errors(errors);
120 }
121 Ok(())
122 }
123
124 #[inline(always)]
128 pub fn write_fifo_unchecked(&mut self, data: u8) {
129 self.tx.write_fifo_unchecked(data);
130 }
131
132 #[inline]
136 pub fn read_fifo(&mut self) -> nb::Result<u8, Infallible> {
137 let val = self.rx.read_fifo()?;
138 if let Some(errors) = self.rx.errors {
139 self.handle_status_reg_errors(errors);
140 }
141 Ok(val)
142 }
143
144 #[inline(always)]
146 pub fn read_fifo_unchecked(&mut self) -> u8 {
147 self.rx.read_fifo_unchecked()
148 }
149
150 #[inline(always)]
152 pub fn tx_fifo_empty(&self) -> bool {
153 self.tx.fifo_empty()
154 }
155
156 #[inline(always)]
158 pub fn tx_fifo_full(&self) -> bool {
159 self.tx.fifo_full()
160 }
161
162 #[inline(always)]
164 pub fn rx_has_data(&self) -> bool {
165 self.rx.has_data()
166 }
167
168 pub fn read_and_clear_errors(&mut self) -> RxErrorsCounted {
170 let errors = self.errors;
171 self.errors = RxErrorsCounted::new();
172 errors
173 }
174
175 #[inline(always)]
176 fn handle_status_reg_errors(&mut self, errors: RxErrors) {
177 if errors.frame() {
178 self.errors.frame = self.errors.frame.saturating_add(1);
179 }
180 if errors.parity() {
181 self.errors.parity = self.errors.parity.saturating_add(1);
182 }
183 if errors.overrun() {
184 self.errors.overrun = self.errors.overrun.saturating_add(1);
185 }
186 }
187
188 #[inline]
190 pub fn reset_rx_fifo(&mut self) {
191 self.regs().write_ctrl_reg(
192 Control::builder()
193 .with_enable_interrupt(false)
194 .with_reset_rx_fifo(true)
195 .with_reset_tx_fifo(false)
196 .build(),
197 );
198 }
199
200 #[inline]
202 pub fn reset_tx_fifo(&mut self) {
203 self.regs().write_ctrl_reg(
204 Control::builder()
205 .with_enable_interrupt(false)
206 .with_reset_rx_fifo(false)
207 .with_reset_tx_fifo(true)
208 .build(),
209 );
210 }
211
212 #[inline]
214 pub fn split(self) -> (Tx, Rx) {
215 (self.tx, self.rx)
216 }
217
218 #[inline]
220 pub fn enable_interrupt(&mut self) {
221 self.regs().write_ctrl_reg(
222 Control::builder()
223 .with_enable_interrupt(true)
224 .with_reset_rx_fifo(false)
225 .with_reset_tx_fifo(false)
226 .build(),
227 );
228 }
229
230 #[inline]
232 pub fn disable_interrupt(&mut self) {
233 self.regs().write_ctrl_reg(
234 Control::builder()
235 .with_enable_interrupt(false)
236 .with_reset_rx_fifo(false)
237 .with_reset_tx_fifo(false)
238 .build(),
239 );
240 }
241}
242
243impl embedded_hal_nb::serial::ErrorType for AxiUartlite {
244 type Error = Infallible;
245}
246
247impl embedded_hal_nb::serial::Write for AxiUartlite {
248 #[inline]
249 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
250 self.tx.write(word)
251 }
252
253 #[inline]
254 fn flush(&mut self) -> nb::Result<(), Self::Error> {
255 self.tx.flush()
256 }
257}
258
259impl embedded_hal_nb::serial::Read for AxiUartlite {
260 #[inline]
261 fn read(&mut self) -> nb::Result<u8, Self::Error> {
262 self.rx.read()
263 }
264}
265
266impl embedded_io::ErrorType for AxiUartlite {
267 type Error = Infallible;
268}
269
270impl embedded_io::Read for AxiUartlite {
271 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
272 self.rx.read(buf)
273 }
274}
275
276impl embedded_io::Write for AxiUartlite {
277 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
278 self.tx.write(buf)
279 }
280
281 fn flush(&mut self) -> Result<(), Self::Error> {
282 self.tx.flush()
283 }
284}