1use core::convert::Infallible;
3
4use crate::{
5 RxErrors, handle_status_reg_errors,
6 registers::{self, Control, TxFifo},
7};
8
9pub struct Tx {
14 pub(crate) regs: registers::MmioRegisters<'static>,
15 pub(crate) errors: Option<RxErrors>,
16}
17
18impl Tx {
19 pub unsafe fn steal(base_addr: usize) -> Self {
33 let regs = unsafe { registers::Registers::new_mmio_at(base_addr) };
34 Self { regs, errors: None }
35 }
36
37 #[inline]
41 pub fn write_fifo(&mut self, data: u8) -> nb::Result<(), Infallible> {
42 let status_reg = self.regs.read_stat_reg();
43 if status_reg.tx_fifo_full() {
44 return Err(nb::Error::WouldBlock);
45 }
46 self.write_fifo_unchecked(data);
47 if let Some(errors) = handle_status_reg_errors(&status_reg) {
48 self.errors = Some(errors);
49 }
50 Ok(())
51 }
52
53 #[inline]
55 pub fn reset_fifo(&mut self) {
56 let status = self.regs.read_stat_reg();
57 self.regs.write_ctrl_reg(
58 Control::builder()
59 .with_enable_interrupt(status.intr_enabled())
60 .with_reset_rx_fifo(false)
61 .with_reset_tx_fifo(true)
62 .build(),
63 );
64 }
65
66 #[inline(always)]
70 pub fn write_fifo_unchecked(&mut self, data: u8) {
71 self.regs
72 .write_tx_fifo(TxFifo::new_with_raw_value(data as u32));
73 }
74
75 #[inline(always)]
77 pub fn fifo_empty(&self) -> bool {
78 self.regs.read_stat_reg().tx_fifo_empty()
79 }
80
81 #[inline(always)]
83 pub fn fifo_full(&self) -> bool {
84 self.regs.read_stat_reg().tx_fifo_full()
85 }
86
87 pub fn fill_fifo(&mut self, buf: &[u8]) -> usize {
92 let mut written = 0;
93 while written < buf.len() {
94 match self.write_fifo(buf[written]) {
95 Ok(_) => written += 1,
96 Err(nb::Error::WouldBlock) => break,
97 }
98 }
99 written
100 }
101
102 pub fn read_and_clear_last_error(&mut self) -> Option<RxErrors> {
104 let errors = self.errors?;
105 self.errors = None;
106 Some(errors)
107 }
108}
109
110impl embedded_hal_nb::serial::ErrorType for Tx {
111 type Error = Infallible;
112}
113
114impl embedded_hal_nb::serial::Write for Tx {
115 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
116 self.write_fifo(word)
117 }
118
119 fn flush(&mut self) -> nb::Result<(), Self::Error> {
120 while !self.fifo_empty() {}
121 Ok(())
122 }
123}
124
125impl embedded_io::ErrorType for Tx {
126 type Error = Infallible;
127}
128
129impl embedded_io::Write for Tx {
130 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
131 if buf.is_empty() {
132 return Ok(0);
133 }
134 while self.fifo_full() {}
135 let mut written = 0;
136 for &byte in buf.iter() {
137 match self.write_fifo(byte) {
138 Ok(_) => written += 1,
139 Err(nb::Error::WouldBlock) => break,
140 }
141 }
142 Ok(written)
143 }
144
145 fn flush(&mut self) -> Result<(), Self::Error> {
146 while !self.fifo_empty() {}
147 Ok(())
148 }
149}