1use crate::pac::LP_UART;
38
39const UART_FIFO_SIZE: u16 = 128;
40
41#[doc(hidden)]
42pub unsafe fn conjure() -> LpUart {
43 unsafe {
44 LpUart {
45 uart: LP_UART::steal(),
46 }
47 }
48}
49
50#[derive(Debug)]
52pub enum Error {}
53
54#[cfg(feature = "embedded-hal")]
55impl embedded_hal_nb::serial::Error for Error {
56 fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
57 embedded_hal_nb::serial::ErrorKind::Other
58 }
59}
60
61#[cfg(feature = "embedded-io")]
62impl embedded_io::Error for Error {
63 fn kind(&self) -> embedded_io::ErrorKind {
64 embedded_io::ErrorKind::Other
65 }
66}
67
68pub mod config {
70 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
72 pub enum DataBits {
73 DataBits5 = 0,
75 DataBits6 = 1,
77 DataBits7 = 2,
79 #[default]
81 DataBits8 = 3,
82 }
83
84 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
86 pub enum Parity {
87 #[default]
89 ParityNone = 0,
90 ParityEven = 1,
92 ParityOdd = 2,
94 }
95
96 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
98 pub enum StopBits {
99 #[default]
101 Stop1 = 1,
102 Stop1p5 = 2,
104 Stop2 = 3,
106 }
107
108 #[derive(Debug, Clone, Copy)]
110 pub struct Config {
111 baudrate: u32,
112 data_bits: DataBits,
113 parity: Parity,
114 stop_bits: StopBits,
115 }
116
117 impl Config {
118 pub fn baudrate(mut self, baudrate: u32) -> Self {
120 self.baudrate = baudrate;
121 self
122 }
123
124 pub fn parity_none(mut self) -> Self {
126 self.parity = Parity::ParityNone;
127 self
128 }
129
130 pub fn parity_even(mut self) -> Self {
132 self.parity = Parity::ParityEven;
133 self
134 }
135
136 pub fn parity_odd(mut self) -> Self {
138 self.parity = Parity::ParityOdd;
139 self
140 }
141
142 pub fn data_bits(mut self, data_bits: DataBits) -> Self {
144 self.data_bits = data_bits;
145 self
146 }
147
148 pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
150 self.stop_bits = stop_bits;
151 self
152 }
153 }
154
155 impl Default for Config {
156 fn default() -> Config {
157 Config {
158 baudrate: 115_200,
159 data_bits: Default::default(),
160 parity: Default::default(),
161 stop_bits: Default::default(),
162 }
163 }
164 }
165}
166
167pub struct LpUart {
169 uart: LP_UART,
170}
171
172impl LpUart {
173 pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
175 if self.rx_fifo_count() > 0 {
176 let byte = self.uart.fifo().read().rxfifo_rd_byte().bits();
177 Ok(byte)
178 } else {
179 Err(nb::Error::WouldBlock)
180 }
181 }
182
183 pub fn write_byte(&mut self, byte: u8) -> nb::Result<(), Error> {
185 if self.tx_fifo_count() < UART_FIFO_SIZE {
186 self.uart
187 .fifo()
188 .write(|w| unsafe { w.rxfifo_rd_byte().bits(byte) });
189 Ok(())
190 } else {
191 Err(nb::Error::WouldBlock)
192 }
193 }
194
195 pub fn write_bytes(&mut self, data: &[u8]) -> Result<usize, Error> {
198 let count = data.len();
199
200 data.iter()
201 .try_for_each(|c| nb::block!(self.write_byte(*c)))?;
202
203 Ok(count)
204 }
205
206 pub fn flush_tx(&mut self) -> nb::Result<(), Error> {
208 if self.is_tx_idle() {
209 Ok(())
210 } else {
211 Err(nb::Error::WouldBlock)
212 }
213 }
214
215 fn rx_fifo_count(&mut self) -> u16 {
216 self.uart.status().read().rxfifo_cnt().bits().into()
217 }
218
219 fn tx_fifo_count(&mut self) -> u16 {
220 self.uart.status().read().txfifo_cnt().bits().into()
221 }
222
223 fn is_tx_idle(&self) -> bool {
224 self.uart.fsm_status().read().st_utx_out().bits() == 0
225 }
226}
227
228impl core::fmt::Write for LpUart {
229 fn write_str(&mut self, s: &str) -> core::fmt::Result {
230 self.write_bytes(s.as_bytes())
231 .map_err(|_| core::fmt::Error)?;
232 Ok(())
233 }
234}
235
236#[cfg(feature = "embedded-hal")]
237impl embedded_hal_nb::serial::ErrorType for LpUart {
238 type Error = Error;
239}
240
241#[cfg(feature = "embedded-hal")]
242impl embedded_hal_nb::serial::Read for LpUart {
243 fn read(&mut self) -> nb::Result<u8, Self::Error> {
244 self.read_byte()
245 }
246}
247
248#[cfg(feature = "embedded-hal")]
249impl embedded_hal_nb::serial::Write for LpUart {
250 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
251 self.write_byte(word)
252 }
253
254 fn flush(&mut self) -> nb::Result<(), Self::Error> {
255 self.flush_tx()
256 }
257}
258
259#[cfg(feature = "embedded-io")]
260impl embedded_io::ErrorType for LpUart {
261 type Error = Error;
262}
263
264#[cfg(feature = "embedded-io")]
265impl embedded_io::Read for LpUart {
266 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
267 if buf.is_empty() {
268 return Ok(0);
269 }
270
271 while self.rx_fifo_count() == 0 {
272 }
274
275 let mut count = 0;
276 while self.rx_fifo_count() > 0 && count < buf.len() {
277 buf[count] = self.uart.fifo().read().rxfifo_rd_byte().bits();
278 count += 1;
279 }
280
281 Ok(count)
282 }
283}
284
285#[cfg(feature = "embedded-io")]
286impl embedded_io::ReadReady for LpUart {
287 fn read_ready(&mut self) -> Result<bool, Self::Error> {
288 Ok(self.rx_fifo_count() > 0)
289 }
290}
291
292#[cfg(feature = "embedded-io")]
293impl embedded_io::Write for LpUart {
294 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
295 self.write_bytes(buf)
296 }
297
298 fn flush(&mut self) -> Result<(), Self::Error> {
299 loop {
300 match self.flush_tx() {
301 Ok(_) => break,
302 Err(nb::Error::WouldBlock) => { }
303 #[allow(unreachable_patterns)]
304 Err(nb::Error::Other(e)) => return Err(e),
305 }
306 }
307
308 Ok(())
309 }
310}