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