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