1use core::convert::Infallible;
3
4use crate::regs::{self, Registers, fields::Status};
5
6#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub struct RxErrors {
10 parity: bool,
11 frame: bool,
12 overrun: bool,
13}
14
15impl RxErrors {
16 pub const fn new() -> Self {
18 Self {
19 parity: false,
20 frame: false,
21 overrun: false,
22 }
23 }
24
25 pub const fn parity(&self) -> bool {
27 self.parity
28 }
29
30 pub const fn frame(&self) -> bool {
32 self.frame
33 }
34
35 pub const fn overrun(&self) -> bool {
37 self.overrun
38 }
39
40 pub const fn has_errors(&self) -> bool {
42 self.parity || self.frame || self.overrun
43 }
44}
45
46pub struct Rx {
51 pub(crate) regs: regs::MmioRegisters<'static>,
52 pub(crate) errors: Option<RxErrors>,
53}
54
55impl Rx {
56 #[inline]
70 pub const unsafe fn steal(base_addr: usize) -> Self {
71 Self {
72 regs: unsafe { Registers::new_mmio_at(base_addr) },
73 errors: None,
74 }
75 }
76
77 #[inline]
82 pub fn read_fifo(&mut self) -> nb::Result<u8, Infallible> {
83 let status_reg = self.regs.read_stat_reg();
84 if !status_reg.rx_fifo_valid_data() {
85 return Err(nb::Error::WouldBlock);
86 }
87 let val = self.read_fifo_unchecked();
88 if let Some(errors) = handle_status_reg_errors(&status_reg) {
89 self.errors = Some(errors);
90 }
91 Ok(val)
92 }
93
94 #[inline(always)]
96 pub fn read_fifo_unchecked(&mut self) -> u8 {
97 self.regs.read_rx_fifo().data()
98 }
99
100 #[inline(always)]
102 pub fn has_data(&self) -> bool {
103 self.regs.read_stat_reg().rx_fifo_valid_data()
104 }
105
106 #[inline]
110 pub fn read_whole_fifo(&mut self, buf: &mut [u8; 16]) -> usize {
111 let mut read = 0;
112 while read < buf.len() {
113 match self.read_fifo() {
114 Ok(byte) => {
115 buf[read] = byte;
116 read += 1;
117 }
118 Err(nb::Error::WouldBlock) => break,
119 }
120 }
121 read
122 }
123
124 #[inline]
128 pub fn on_interrupt_rx(&mut self, buf: &mut [u8; 16]) -> usize {
129 self.read_whole_fifo(buf)
130 }
131
132 pub fn read_and_clear_last_error(&mut self) -> Option<RxErrors> {
136 let errors = self.errors?;
137 self.errors = None;
138 Some(errors)
139 }
140}
141
142impl embedded_hal_nb::serial::ErrorType for Rx {
143 type Error = Infallible;
144}
145
146impl embedded_hal_nb::serial::Read for Rx {
147 #[inline]
148 fn read(&mut self) -> nb::Result<u8, Self::Error> {
149 self.read_fifo()
150 }
151}
152
153impl embedded_io::ErrorType for Rx {
154 type Error = Infallible;
155}
156
157impl embedded_io::Read for Rx {
158 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
159 if buf.is_empty() {
160 return Ok(0);
161 }
162 while !self.has_data() {}
163 let mut read = 0;
164 for byte in buf.iter_mut() {
165 match self.read_fifo() {
166 Ok(data) => {
167 *byte = data;
168 read += 1;
169 }
170 Err(nb::Error::WouldBlock) => break,
171 }
172 }
173 Ok(read)
174 }
175}
176
177pub const fn handle_status_reg_errors(status_reg: &Status) -> Option<RxErrors> {
179 let mut errors = RxErrors::new();
180 if status_reg.frame_error() {
181 errors.frame = true;
182 }
183 if status_reg.parity_error() {
184 errors.parity = true;
185 }
186 if status_reg.overrun_error() {
187 errors.overrun = true;
188 }
189 if !errors.has_errors() {
190 return None;
191 }
192 Some(errors)
193}