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