aboutsummaryrefslogtreecommitdiff
path: root/embassy-mspm0/src/uart
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-mspm0/src/uart')
-rw-r--r--embassy-mspm0/src/uart/buffered.rs1060
-rw-r--r--embassy-mspm0/src/uart/mod.rs1174
2 files changed, 2234 insertions, 0 deletions
diff --git a/embassy-mspm0/src/uart/buffered.rs b/embassy-mspm0/src/uart/buffered.rs
new file mode 100644
index 000000000..cbc0b6c80
--- /dev/null
+++ b/embassy-mspm0/src/uart/buffered.rs
@@ -0,0 +1,1060 @@
1use core::future::{poll_fn, Future};
2use core::marker::PhantomData;
3use core::slice;
4use core::sync::atomic::{AtomicU8, Ordering};
5use core::task::Poll;
6
7use embassy_embedded_hal::SetConfig;
8use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
9use embassy_hal_internal::interrupt::InterruptExt;
10use embassy_sync::waitqueue::AtomicWaker;
11use embedded_hal_nb::nb;
12
13use crate::gpio::{AnyPin, SealedPin};
14use crate::interrupt::typelevel::Binding;
15use crate::pac::uart::Uart as Regs;
16use crate::uart::{Config, ConfigError, CtsPin, Error, Info, Instance, RtsPin, RxPin, State, TxPin};
17use crate::{interrupt, Peri};
18
19/// Interrupt handler.
20pub struct BufferedInterruptHandler<T: Instance> {
21 _uart: PhantomData<T>,
22}
23
24impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for BufferedInterruptHandler<T> {
25 unsafe fn on_interrupt() {
26 on_interrupt(T::info().regs, T::buffered_state())
27 }
28}
29
30/// Bidirectional buffered UART which acts as a combination of [`BufferedUartTx`] and [`BufferedUartRx`].
31pub struct BufferedUart<'d> {
32 rx: BufferedUartRx<'d>,
33 tx: BufferedUartTx<'d>,
34}
35
36impl SetConfig for BufferedUart<'_> {
37 type Config = Config;
38 type ConfigError = ConfigError;
39
40 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
41 self.set_config(config)
42 }
43}
44
45impl<'d> BufferedUart<'d> {
46 /// Create a new bidirectional buffered UART.
47 pub fn new<T: Instance>(
48 uart: Peri<'d, T>,
49 tx: Peri<'d, impl TxPin<T>>,
50 rx: Peri<'d, impl RxPin<T>>,
51 _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
52 tx_buffer: &'d mut [u8],
53 rx_buffer: &'d mut [u8],
54 config: Config,
55 ) -> Result<Self, ConfigError> {
56 Self::new_inner(
57 uart,
58 new_pin!(rx, config.rx_pf()),
59 new_pin!(tx, config.tx_pf()),
60 None,
61 None,
62 tx_buffer,
63 rx_buffer,
64 config,
65 )
66 }
67
68 /// Create a new bidirectional buffered UART with request-to-send and clear-to-send pins
69 pub fn new_with_rtscts<T: Instance>(
70 uart: Peri<'d, T>,
71 tx: Peri<'d, impl TxPin<T>>,
72 rx: Peri<'d, impl RxPin<T>>,
73 rts: Peri<'d, impl RtsPin<T>>,
74 cts: Peri<'d, impl CtsPin<T>>,
75 _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
76 tx_buffer: &'d mut [u8],
77 rx_buffer: &'d mut [u8],
78 config: Config,
79 ) -> Result<Self, ConfigError> {
80 Self::new_inner(
81 uart,
82 new_pin!(rx, config.rx_pf()),
83 new_pin!(tx, config.tx_pf()),
84 new_pin!(rts, config.rts_pf()),
85 new_pin!(cts, config.cts_pf()),
86 tx_buffer,
87 rx_buffer,
88 config,
89 )
90 }
91
92 /// Reconfigure the driver
93 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
94 self.tx.set_config(config)?;
95 self.rx.set_config(config)
96 }
97
98 /// Set baudrate
99 pub fn set_baudrate(&mut self, baudrate: u32) -> Result<(), ConfigError> {
100 self.rx.set_baudrate(baudrate)
101 }
102
103 /// Write to UART TX buffer, blocking execution until done.
104 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<usize, Error> {
105 self.tx.blocking_write(buffer)
106 }
107
108 /// Flush UART TX buffer, blocking execution until done.
109 pub fn blocking_flush(&mut self) -> Result<(), Error> {
110 self.tx.blocking_flush()
111 }
112
113 /// Check if UART is busy.
114 pub fn busy(&self) -> bool {
115 self.tx.busy()
116 }
117
118 /// Read from UART RX buffer, blocking execution until done.
119 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
120 self.rx.blocking_read(buffer)
121 }
122
123 /// Send break character.
124 pub fn send_break(&mut self) {
125 self.tx.send_break()
126 }
127
128 /// Split into separate RX and TX handles.
129 pub fn split(self) -> (BufferedUartTx<'d>, BufferedUartRx<'d>) {
130 (self.tx, self.rx)
131 }
132
133 /// Split into separate RX and TX handles.
134 pub fn split_ref(&mut self) -> (BufferedUartTx<'_>, BufferedUartRx<'_>) {
135 (
136 BufferedUartTx {
137 info: self.tx.info,
138 state: self.tx.state,
139 tx: self.tx.tx.as_mut().map(Peri::reborrow),
140 cts: self.tx.cts.as_mut().map(Peri::reborrow),
141 reborrowed: true,
142 },
143 BufferedUartRx {
144 info: self.rx.info,
145 state: self.rx.state,
146 rx: self.rx.rx.as_mut().map(Peri::reborrow),
147 rts: self.rx.rts.as_mut().map(Peri::reborrow),
148 reborrowed: true,
149 },
150 )
151 }
152}
153
154/// Rx-only buffered UART.
155///
156/// Can be obtained from [`BufferedUart::split`], or can be constructed independently,
157/// if you do not need the transmitting half of the driver.
158pub struct BufferedUartRx<'d> {
159 info: &'static Info,
160 state: &'static BufferedState,
161 rx: Option<Peri<'d, AnyPin>>,
162 rts: Option<Peri<'d, AnyPin>>,
163 reborrowed: bool,
164}
165
166impl SetConfig for BufferedUartRx<'_> {
167 type Config = Config;
168 type ConfigError = ConfigError;
169
170 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
171 self.set_config(config)
172 }
173}
174
175impl<'d> BufferedUartRx<'d> {
176 /// Create a new rx-only buffered UART with no hardware flow control.
177 ///
178 /// Useful if you only want Uart Rx. It saves 1 pin.
179 pub fn new<T: Instance>(
180 uart: Peri<'d, T>,
181 rx: Peri<'d, impl RxPin<T>>,
182 _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
183 rx_buffer: &'d mut [u8],
184 config: Config,
185 ) -> Result<Self, ConfigError> {
186 Self::new_inner(uart, new_pin!(rx, config.rx_pf()), None, rx_buffer, config)
187 }
188
189 /// Create a new rx-only buffered UART with a request-to-send pin
190 pub fn new_with_rts<T: Instance>(
191 uart: Peri<'d, T>,
192 rx: Peri<'d, impl RxPin<T>>,
193 rts: Peri<'d, impl RtsPin<T>>,
194 _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
195 rx_buffer: &'d mut [u8],
196 config: Config,
197 ) -> Result<Self, ConfigError> {
198 Self::new_inner(
199 uart,
200 new_pin!(rx, config.rx_pf()),
201 new_pin!(rts, config.rts_pf()),
202 rx_buffer,
203 config,
204 )
205 }
206
207 /// Reconfigure the driver
208 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
209 if let Some(ref rx) = self.rx {
210 rx.update_pf(config.rx_pf());
211 }
212
213 if let Some(ref rts) = self.rts {
214 rts.update_pf(config.rts_pf());
215 }
216
217 super::reconfigure(&self.info, &self.state.state, config)
218 }
219
220 /// Set baudrate
221 pub fn set_baudrate(&mut self, baudrate: u32) -> Result<(), ConfigError> {
222 super::set_baudrate(&self.info, self.state.state.clock.load(Ordering::Relaxed), baudrate)
223 }
224
225 /// Read from UART RX buffer, blocking execution until done.
226 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
227 self.blocking_read_inner(buffer)
228 }
229}
230
231impl Drop for BufferedUartRx<'_> {
232 fn drop(&mut self) {
233 if !self.reborrowed {
234 let state = self.state;
235
236 // SAFETY: RX is being dropped (and is not reborrowed), so the ring buffer must be deinitialized
237 // in order to meet the requirements of init.
238 unsafe {
239 state.rx_buf.deinit();
240 }
241
242 // TX is inactive if the buffer is not available. If this is true, then disable the
243 // interrupt handler since we are running in RX only mode.
244 if state.tx_buf.len() == 0 {
245 self.info.interrupt.disable();
246 }
247
248 self.rx.as_ref().map(|x| x.set_as_disconnected());
249 self.rts.as_ref().map(|x| x.set_as_disconnected());
250 }
251 }
252}
253
254/// Tx-only buffered UART.
255///
256/// Can be obtained from [`BufferedUart::split`], or can be constructed independently,
257/// if you do not need the receiving half of the driver.
258pub struct BufferedUartTx<'d> {
259 info: &'static Info,
260 state: &'static BufferedState,
261 tx: Option<Peri<'d, AnyPin>>,
262 cts: Option<Peri<'d, AnyPin>>,
263 reborrowed: bool,
264}
265
266impl SetConfig for BufferedUartTx<'_> {
267 type Config = Config;
268 type ConfigError = ConfigError;
269
270 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
271 self.set_config(config)
272 }
273}
274
275impl<'d> BufferedUartTx<'d> {
276 /// Create a new tx-only buffered UART with no hardware flow control.
277 ///
278 /// Useful if you only want Uart Tx. It saves 1 pin.
279 pub fn new<T: Instance>(
280 uart: Peri<'d, T>,
281 tx: Peri<'d, impl TxPin<T>>,
282 _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
283 tx_buffer: &'d mut [u8],
284 config: Config,
285 ) -> Result<Self, ConfigError> {
286 Self::new_inner(uart, new_pin!(tx, config.tx_pf()), None, tx_buffer, config)
287 }
288
289 /// Create a new tx-only buffered UART with a clear-to-send pin
290 pub fn new_with_rts<T: Instance>(
291 uart: Peri<'d, T>,
292 tx: Peri<'d, impl TxPin<T>>,
293 cts: Peri<'d, impl CtsPin<T>>,
294 _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
295 tx_buffer: &'d mut [u8],
296 config: Config,
297 ) -> Result<Self, ConfigError> {
298 Self::new_inner(
299 uart,
300 new_pin!(tx, config.tx_pf()),
301 new_pin!(cts, config.cts_pf()),
302 tx_buffer,
303 config,
304 )
305 }
306
307 /// Reconfigure the driver
308 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
309 if let Some(ref tx) = self.tx {
310 tx.update_pf(config.tx_pf());
311 }
312
313 if let Some(ref cts) = self.cts {
314 cts.update_pf(config.cts_pf());
315 }
316
317 super::reconfigure(self.info, &self.state.state, config)
318 }
319
320 /// Set baudrate
321 pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> {
322 super::set_baudrate(&self.info, self.state.state.clock.load(Ordering::Relaxed), baudrate)
323 }
324
325 /// Write to UART TX buffer, blocking execution until done.
326 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<usize, Error> {
327 self.blocking_write_inner(buffer)
328 }
329
330 /// Flush UART TX buffer, blocking execution until done.
331 pub fn blocking_flush(&mut self) -> Result<(), Error> {
332 let state = self.state;
333
334 loop {
335 if state.tx_buf.is_empty() {
336 return Ok(());
337 }
338 }
339 }
340
341 /// Check if UART is busy.
342 pub fn busy(&self) -> bool {
343 super::busy(self.info.regs)
344 }
345
346 /// Send break character
347 pub fn send_break(&mut self) {
348 let r = self.info.regs;
349
350 r.lcrh().modify(|w| {
351 w.set_brk(true);
352 });
353 }
354}
355
356impl Drop for BufferedUartTx<'_> {
357 fn drop(&mut self) {
358 if !self.reborrowed {
359 let state = self.state;
360
361 // SAFETY: TX is being dropped (and is not reborrowed), so the ring buffer must be deinitialized
362 // in order to meet the requirements of init.
363 unsafe {
364 state.tx_buf.deinit();
365 }
366
367 // RX is inactive if the buffer is not available. If this is true, then disable the
368 // interrupt handler since we are running in TX only mode.
369 if state.rx_buf.len() == 0 {
370 self.info.interrupt.disable();
371 }
372
373 self.tx.as_ref().map(|x| x.set_as_disconnected());
374 self.cts.as_ref().map(|x| x.set_as_disconnected());
375 }
376 }
377}
378
379impl embedded_io_async::ErrorType for BufferedUart<'_> {
380 type Error = Error;
381}
382
383impl embedded_io_async::ErrorType for BufferedUartRx<'_> {
384 type Error = Error;
385}
386
387impl embedded_io_async::ErrorType for BufferedUartTx<'_> {
388 type Error = Error;
389}
390
391impl embedded_io_async::Read for BufferedUart<'_> {
392 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
393 self.rx.read(buf).await
394 }
395}
396
397impl embedded_io_async::Read for BufferedUartRx<'_> {
398 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
399 self.read_inner(buf).await
400 }
401}
402
403impl embedded_io_async::ReadReady for BufferedUart<'_> {
404 fn read_ready(&mut self) -> Result<bool, Self::Error> {
405 self.rx.read_ready()
406 }
407}
408
409impl embedded_io_async::ReadReady for BufferedUartRx<'_> {
410 fn read_ready(&mut self) -> Result<bool, Self::Error> {
411 self.read_ready_inner()
412 }
413}
414
415impl embedded_io_async::BufRead for BufferedUart<'_> {
416 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
417 self.rx.fill_buf().await
418 }
419
420 fn consume(&mut self, amt: usize) {
421 self.rx.consume(amt);
422 }
423}
424
425impl embedded_io_async::BufRead for BufferedUartRx<'_> {
426 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
427 self.fill_buf_inner().await
428 }
429
430 fn consume(&mut self, amt: usize) {
431 self.consume_inner(amt);
432 }
433}
434
435impl embedded_io_async::Write for BufferedUart<'_> {
436 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
437 self.tx.write_inner(buf).await
438 }
439}
440
441impl embedded_io_async::Write for BufferedUartTx<'_> {
442 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
443 self.write_inner(buf).await
444 }
445
446 async fn flush(&mut self) -> Result<(), Self::Error> {
447 self.flush_inner().await
448 }
449}
450
451impl embedded_io::Read for BufferedUart<'_> {
452 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
453 self.rx.read(buf)
454 }
455}
456
457impl embedded_io::Read for BufferedUartRx<'_> {
458 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
459 self.blocking_read_inner(buf)
460 }
461}
462
463impl embedded_io::Write for BufferedUart<'_> {
464 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
465 self.tx.write(buf)
466 }
467
468 fn flush(&mut self) -> Result<(), Self::Error> {
469 self.tx.flush()
470 }
471}
472
473impl embedded_io::Write for BufferedUartTx<'_> {
474 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
475 self.blocking_write_inner(buf)
476 }
477
478 fn flush(&mut self) -> Result<(), Self::Error> {
479 self.blocking_flush()
480 }
481}
482
483impl embedded_hal_nb::serial::Error for Error {
484 fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
485 match self {
486 Error::Framing => embedded_hal_nb::serial::ErrorKind::FrameFormat,
487 Error::Noise => embedded_hal_nb::serial::ErrorKind::Noise,
488 Error::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun,
489 Error::Parity => embedded_hal_nb::serial::ErrorKind::Parity,
490 Error::Break => embedded_hal_nb::serial::ErrorKind::Other,
491 }
492 }
493}
494
495impl embedded_hal_nb::serial::ErrorType for BufferedUart<'_> {
496 type Error = Error;
497}
498
499impl embedded_hal_nb::serial::ErrorType for BufferedUartRx<'_> {
500 type Error = Error;
501}
502
503impl embedded_hal_nb::serial::ErrorType for BufferedUartTx<'_> {
504 type Error = Error;
505}
506
507impl embedded_hal_nb::serial::Read for BufferedUart<'_> {
508 fn read(&mut self) -> nb::Result<u8, Self::Error> {
509 self.rx.read()
510 }
511}
512
513impl embedded_hal_nb::serial::Read for BufferedUartRx<'_> {
514 fn read(&mut self) -> nb::Result<u8, Self::Error> {
515 if self.info.regs.stat().read().rxfe() {
516 return Err(nb::Error::WouldBlock);
517 }
518
519 super::read_with_error(self.info.regs).map_err(nb::Error::Other)
520 }
521}
522
523impl embedded_hal_nb::serial::Write for BufferedUart<'_> {
524 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
525 self.tx.write(word)
526 }
527
528 fn flush(&mut self) -> nb::Result<(), Self::Error> {
529 self.tx.flush()
530 }
531}
532
533impl embedded_hal_nb::serial::Write for BufferedUartTx<'_> {
534 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
535 self.blocking_write(&[word]).map(drop).map_err(nb::Error::Other)
536 }
537
538 fn flush(&mut self) -> nb::Result<(), Self::Error> {
539 self.blocking_flush().map_err(nb::Error::Other)
540 }
541}
542
543// Impl details
544
545/// Buffered UART state.
546pub(crate) struct BufferedState {
547 /// non-buffered UART state. This is inline in order to avoid [`BufferedUartRx`]/Tx
548 /// needing to carry around a 2nd static reference and waste another 4 bytes.
549 state: State,
550 rx_waker: AtomicWaker,
551 rx_buf: RingBuffer,
552 tx_waker: AtomicWaker,
553 tx_buf: RingBuffer,
554 rx_error: AtomicU8,
555}
556
557// these must match bits 8..12 in RXDATA, but shifted by 8 to the right
558const RXE_NOISE: u8 = 16;
559const RXE_OVERRUN: u8 = 8;
560const RXE_BREAK: u8 = 4;
561const RXE_PARITY: u8 = 2;
562const RXE_FRAMING: u8 = 1;
563
564impl BufferedState {
565 pub const fn new() -> Self {
566 Self {
567 state: State::new(),
568 rx_waker: AtomicWaker::new(),
569 rx_buf: RingBuffer::new(),
570 tx_waker: AtomicWaker::new(),
571 tx_buf: RingBuffer::new(),
572 rx_error: AtomicU8::new(0),
573 }
574 }
575}
576
577impl<'d> BufferedUart<'d> {
578 fn new_inner<T: Instance>(
579 _peri: Peri<'d, T>,
580 rx: Option<Peri<'d, AnyPin>>,
581 tx: Option<Peri<'d, AnyPin>>,
582 rts: Option<Peri<'d, AnyPin>>,
583 cts: Option<Peri<'d, AnyPin>>,
584 tx_buffer: &'d mut [u8],
585 rx_buffer: &'d mut [u8],
586 config: Config,
587 ) -> Result<Self, ConfigError> {
588 let info = T::info();
589 let state = T::buffered_state();
590
591 let mut this = Self {
592 tx: BufferedUartTx {
593 info,
594 state,
595 tx,
596 cts,
597 reborrowed: false,
598 },
599 rx: BufferedUartRx {
600 info,
601 state,
602 rx,
603 rts,
604 reborrowed: false,
605 },
606 };
607 this.enable_and_configure(tx_buffer, rx_buffer, &config)?;
608
609 Ok(this)
610 }
611
612 fn enable_and_configure(
613 &mut self,
614 tx_buffer: &'d mut [u8],
615 rx_buffer: &'d mut [u8],
616 config: &Config,
617 ) -> Result<(), ConfigError> {
618 let info = self.rx.info;
619 let state = self.rx.state;
620
621 assert!(!tx_buffer.is_empty());
622 assert!(!rx_buffer.is_empty());
623
624 init_buffers(info, state, Some(tx_buffer), Some(rx_buffer));
625 super::enable(info.regs);
626 super::configure(
627 info,
628 &state.state,
629 config,
630 true,
631 self.rx.rts.is_some(),
632 true,
633 self.tx.cts.is_some(),
634 )?;
635
636 info.interrupt.unpend();
637 unsafe { info.interrupt.enable() };
638
639 Ok(())
640 }
641}
642
643impl<'d> BufferedUartRx<'d> {
644 fn new_inner<T: Instance>(
645 _peri: Peri<'d, T>,
646 rx: Option<Peri<'d, AnyPin>>,
647 rts: Option<Peri<'d, AnyPin>>,
648 rx_buffer: &'d mut [u8],
649 config: Config,
650 ) -> Result<Self, ConfigError> {
651 let mut this = Self {
652 info: T::info(),
653 state: T::buffered_state(),
654 rx,
655 rts,
656 reborrowed: false,
657 };
658 this.enable_and_configure(rx_buffer, &config)?;
659
660 Ok(this)
661 }
662
663 fn enable_and_configure(&mut self, rx_buffer: &'d mut [u8], config: &Config) -> Result<(), ConfigError> {
664 let info = self.info;
665 let state = self.state;
666
667 init_buffers(info, state, None, Some(rx_buffer));
668 super::enable(info.regs);
669 super::configure(info, &self.state.state, config, true, self.rts.is_some(), false, false)?;
670
671 info.interrupt.unpend();
672 unsafe { info.interrupt.enable() };
673
674 Ok(())
675 }
676
677 async fn read_inner(&self, buf: &mut [u8]) -> Result<usize, Error> {
678 poll_fn(move |cx| {
679 let state = self.state;
680
681 if let Poll::Ready(r) = self.try_read(buf) {
682 return Poll::Ready(r);
683 }
684
685 state.rx_waker.register(cx.waker());
686 Poll::Pending
687 })
688 .await
689 }
690
691 fn blocking_read_inner(&self, buffer: &mut [u8]) -> Result<usize, Error> {
692 loop {
693 match self.try_read(buffer) {
694 Poll::Ready(res) => return res,
695 Poll::Pending => continue,
696 }
697 }
698 }
699
700 fn fill_buf_inner(&self) -> impl Future<Output = Result<&'_ [u8], Error>> {
701 poll_fn(move |cx| {
702 let mut rx_reader = unsafe { self.state.rx_buf.reader() };
703 let (p, n) = rx_reader.pop_buf();
704 let result = if n == 0 {
705 match Self::get_rx_error(self.state) {
706 None => {
707 self.state.rx_waker.register(cx.waker());
708 return Poll::Pending;
709 }
710 Some(e) => Err(e),
711 }
712 } else {
713 let buf = unsafe { slice::from_raw_parts(p, n) };
714 Ok(buf)
715 };
716
717 Poll::Ready(result)
718 })
719 }
720
721 fn consume_inner(&self, amt: usize) {
722 let mut rx_reader = unsafe { self.state.rx_buf.reader() };
723 rx_reader.pop_done(amt);
724
725 // (Re-)Enable the interrupt to receive more data in case it was
726 // disabled because the buffer was full or errors were detected.
727 self.info.regs.cpu_int(0).imask().modify(|w| {
728 w.set_rxint(true);
729 w.set_rtout(true);
730 });
731 }
732
733 /// we are ready to read if there is data in the buffer
734 fn read_ready_inner(&self) -> Result<bool, Error> {
735 Ok(!self.state.rx_buf.is_empty())
736 }
737
738 fn try_read(&self, buf: &mut [u8]) -> Poll<Result<usize, Error>> {
739 let state = self.state;
740
741 if buf.is_empty() {
742 return Poll::Ready(Ok(0));
743 }
744
745 let mut rx_reader = unsafe { state.rx_buf.reader() };
746 let n = rx_reader.pop(|data| {
747 let n = data.len().min(buf.len());
748 buf[..n].copy_from_slice(&data[..n]);
749 n
750 });
751
752 let result = if n == 0 {
753 match Self::get_rx_error(state) {
754 None => return Poll::Pending,
755 Some(e) => Err(e),
756 }
757 } else {
758 Ok(n)
759 };
760
761 // (Re-)Enable the interrupt to receive more data in case it was
762 // disabled because the buffer was full or errors were detected.
763 self.info.regs.cpu_int(0).imask().modify(|w| {
764 w.set_rxint(true);
765 w.set_rtout(true);
766 });
767
768 Poll::Ready(result)
769 }
770
771 fn get_rx_error(state: &BufferedState) -> Option<Error> {
772 // Cortex-M0 has does not support atomic swap, so we must do two operations.
773 let errs = critical_section::with(|_cs| {
774 let errs = state.rx_error.load(Ordering::Relaxed);
775 state.rx_error.store(0, Ordering::Relaxed);
776
777 errs
778 });
779
780 if errs & RXE_NOISE != 0 {
781 Some(Error::Noise)
782 } else if errs & RXE_OVERRUN != 0 {
783 Some(Error::Overrun)
784 } else if errs & RXE_BREAK != 0 {
785 Some(Error::Break)
786 } else if errs & RXE_PARITY != 0 {
787 Some(Error::Parity)
788 } else if errs & RXE_FRAMING != 0 {
789 Some(Error::Framing)
790 } else {
791 None
792 }
793 }
794}
795
796impl<'d> BufferedUartTx<'d> {
797 fn new_inner<T: Instance>(
798 _peri: Peri<'d, T>,
799 tx: Option<Peri<'d, AnyPin>>,
800 cts: Option<Peri<'d, AnyPin>>,
801 tx_buffer: &'d mut [u8],
802 config: Config,
803 ) -> Result<Self, ConfigError> {
804 let mut this = Self {
805 info: T::info(),
806 state: T::buffered_state(),
807 tx,
808 cts,
809 reborrowed: false,
810 };
811
812 this.enable_and_configure(tx_buffer, &config)?;
813
814 Ok(this)
815 }
816
817 async fn write_inner(&self, buf: &[u8]) -> Result<usize, Error> {
818 poll_fn(move |cx| {
819 let state = self.state;
820
821 if buf.is_empty() {
822 return Poll::Ready(Ok(0));
823 }
824
825 let mut tx_writer = unsafe { state.tx_buf.writer() };
826 let n = tx_writer.push(|data| {
827 let n = data.len().min(buf.len());
828 data[..n].copy_from_slice(&buf[..n]);
829 n
830 });
831
832 if n == 0 {
833 state.tx_waker.register(cx.waker());
834 return Poll::Pending;
835 }
836
837 // The TX interrupt only triggers when the there was data in the
838 // FIFO and the number of bytes drops below a threshold. When the
839 // FIFO was empty we have to manually pend the interrupt to shovel
840 // TX data from the buffer into the FIFO.
841 self.info.interrupt.pend();
842 Poll::Ready(Ok(n))
843 })
844 .await
845 }
846
847 fn blocking_write_inner(&self, buffer: &[u8]) -> Result<usize, Error> {
848 let state = self.state;
849
850 loop {
851 let empty = state.tx_buf.is_empty();
852
853 // SAFETY: tx buf must be initialized if BufferedUartTx exists.
854 let mut tx_writer = unsafe { state.tx_buf.writer() };
855 let data = tx_writer.push_slice();
856
857 if !data.is_empty() {
858 let n = data.len().min(buffer.len());
859 data[..n].copy_from_slice(&buffer[..n]);
860 tx_writer.push_done(n);
861
862 if empty {
863 self.info.interrupt.pend();
864 }
865
866 return Ok(n);
867 }
868 }
869 }
870
871 async fn flush_inner(&self) -> Result<(), Error> {
872 poll_fn(move |cx| {
873 let state = self.state;
874
875 if !state.tx_buf.is_empty() {
876 state.tx_waker.register(cx.waker());
877 return Poll::Pending;
878 }
879
880 Poll::Ready(Ok(()))
881 })
882 .await
883 }
884
885 fn enable_and_configure(&mut self, tx_buffer: &'d mut [u8], config: &Config) -> Result<(), ConfigError> {
886 let info = self.info;
887 let state = self.state;
888
889 init_buffers(info, state, Some(tx_buffer), None);
890 super::enable(info.regs);
891 super::configure(info, &state.state, config, false, false, true, self.cts.is_some())?;
892
893 info.interrupt.unpend();
894 unsafe { info.interrupt.enable() };
895
896 Ok(())
897 }
898}
899
900fn init_buffers<'d>(
901 info: &Info,
902 state: &BufferedState,
903 tx_buffer: Option<&'d mut [u8]>,
904 rx_buffer: Option<&'d mut [u8]>,
905) {
906 if let Some(tx_buffer) = tx_buffer {
907 let len = tx_buffer.len();
908 unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
909 }
910
911 if let Some(rx_buffer) = rx_buffer {
912 let len = rx_buffer.len();
913 unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
914 }
915
916 info.regs.cpu_int(0).imask().modify(|w| {
917 w.set_nerr(true);
918 w.set_frmerr(true);
919 w.set_parerr(true);
920 w.set_brkerr(true);
921 w.set_ovrerr(true);
922 });
923}
924
925fn on_interrupt(r: Regs, state: &'static BufferedState) {
926 let int = r.cpu_int(0).mis().read();
927
928 // Per https://github.com/embassy-rs/embassy/pull/1458, both buffered and unbuffered handlers may be bound.
929 if super::dma_enabled(r) {
930 return;
931 }
932
933 // RX
934 if state.rx_buf.is_available() {
935 // SAFETY: RX must have been initialized if RXE is set.
936 let mut rx_writer = unsafe { state.rx_buf.writer() };
937 let rx_buf = rx_writer.push_slice();
938 let mut n_read = 0;
939 let mut error = false;
940
941 for rx_byte in rx_buf {
942 let stat = r.stat().read();
943
944 if stat.rxfe() {
945 break;
946 }
947
948 let data = r.rxdata().read();
949
950 if (data.0 >> 8) != 0 {
951 // Cortex-M0 does not support atomic fetch_or, must do 2 operations.
952 critical_section::with(|_cs| {
953 let mut value = state.rx_error.load(Ordering::Relaxed);
954 value |= (data.0 >> 8) as u8;
955 state.rx_error.store(value, Ordering::Relaxed);
956 });
957 error = true;
958
959 // only fill the buffer with valid characters. the current character is fine
960 // if the error is an overrun, but if we add it to the buffer we'll report
961 // the overrun one character too late. drop it instead and pretend we were
962 // a bit slower at draining the rx fifo than we actually were.
963 // this is consistent with blocking uart error reporting.
964 break;
965 }
966
967 *rx_byte = data.data();
968 n_read += 1;
969 }
970
971 if n_read > 0 {
972 rx_writer.push_done(n_read);
973 state.rx_waker.wake();
974 } else if error {
975 state.rx_waker.wake();
976 }
977
978 // Disable any further RX interrupts when the buffer becomes full or
979 // errors have occurred. This lets us buffer additional errors in the
980 // fifo without needing more error storage locations, and most applications
981 // will want to do a full reset of their uart state anyway once an error
982 // has happened.
983 if state.rx_buf.is_full() || error {
984 r.cpu_int(0).imask().modify(|w| {
985 w.set_rxint(false);
986 w.set_rtout(false);
987 });
988 }
989 }
990
991 if int.eot() {
992 r.cpu_int(0).imask().modify(|w| {
993 w.set_eot(false);
994 });
995
996 r.cpu_int(0).iclr().write(|w| {
997 w.set_eot(true);
998 });
999
1000 state.tx_waker.wake();
1001 }
1002
1003 // TX
1004 if state.tx_buf.is_available() {
1005 // SAFETY: TX must have been initialized if TXE is set.
1006 let mut tx_reader = unsafe { state.tx_buf.reader() };
1007 let buf = tx_reader.pop_slice();
1008 let mut n_written = 0;
1009
1010 for tx_byte in buf.iter_mut() {
1011 let stat = r.stat().read();
1012
1013 if stat.txff() {
1014 break;
1015 }
1016
1017 r.txdata().write(|w| {
1018 w.set_data(*tx_byte);
1019 });
1020 n_written += 1;
1021 }
1022
1023 if n_written > 0 {
1024 // EOT will wake.
1025 r.cpu_int(0).imask().modify(|w| {
1026 w.set_eot(true);
1027 });
1028
1029 tx_reader.pop_done(n_written);
1030 }
1031 }
1032
1033 // Clear TX and error interrupt flags
1034 // RX interrupt flags are cleared by writing to ICLR.
1035 let mis = r.cpu_int(0).mis().read();
1036 r.cpu_int(0).iclr().write(|w| {
1037 w.set_nerr(mis.nerr());
1038 w.set_frmerr(mis.frmerr());
1039 w.set_parerr(mis.parerr());
1040 w.set_brkerr(mis.brkerr());
1041 w.set_ovrerr(mis.ovrerr());
1042 });
1043
1044 // Errors
1045 if mis.nerr() {
1046 warn!("Noise error");
1047 }
1048 if mis.frmerr() {
1049 warn!("Framing error");
1050 }
1051 if mis.parerr() {
1052 warn!("Parity error");
1053 }
1054 if mis.brkerr() {
1055 warn!("Break error");
1056 }
1057 if mis.ovrerr() {
1058 warn!("Overrun error");
1059 }
1060}
diff --git a/embassy-mspm0/src/uart/mod.rs b/embassy-mspm0/src/uart/mod.rs
new file mode 100644
index 000000000..6599cea06
--- /dev/null
+++ b/embassy-mspm0/src/uart/mod.rs
@@ -0,0 +1,1174 @@
1#![macro_use]
2
3mod buffered;
4
5use core::marker::PhantomData;
6use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
7
8pub use buffered::*;
9use embassy_embedded_hal::SetConfig;
10use embassy_hal_internal::PeripheralType;
11
12use crate::gpio::{AnyPin, PfType, Pull, SealedPin};
13use crate::interrupt::{Interrupt, InterruptExt};
14use crate::mode::{Blocking, Mode};
15use crate::pac::uart::{vals, Uart as Regs};
16use crate::Peri;
17
18/// The clock source for the UART.
19#[derive(Clone, Copy, PartialEq, Eq, Debug)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum ClockSel {
22 /// Use the low frequency clock.
23 ///
24 /// The LFCLK runs at 32.768 kHz.
25 LfClk,
26
27 /// Use the middle frequency clock.
28 ///
29 /// The MCLK runs at 4 MHz.
30 MfClk,
31 // BusClk,
32 // BusClk depends on the timer's power domain.
33 // This will be implemented later.
34}
35
36#[non_exhaustive]
37#[derive(Clone, Copy, PartialEq, Eq, Debug)]
38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
39/// The order of bits in byte.
40pub enum BitOrder {
41 /// The most significant bit is first.
42 MsbFirst,
43
44 /// The least significant bit is first.
45 LsbFirst,
46}
47
48#[derive(Clone, Copy, PartialEq, Eq, Debug)]
49#[cfg_attr(feature = "defmt", derive(defmt::Format))]
50/// Number of data bits
51pub enum DataBits {
52 /// 5 Data Bits
53 DataBits5,
54
55 /// 6 Data Bits
56 DataBits6,
57
58 /// 7 Data Bits
59 DataBits7,
60
61 /// 8 Data Bits
62 DataBits8,
63}
64
65#[derive(Clone, Copy, PartialEq, Eq, Debug)]
66#[cfg_attr(feature = "defmt", derive(defmt::Format))]
67/// Parity
68pub enum Parity {
69 /// No parity
70 ParityNone,
71
72 /// Even Parity
73 ParityEven,
74
75 /// Odd Parity
76 ParityOdd,
77}
78
79#[derive(Clone, Copy, PartialEq, Eq, Debug)]
80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81/// Number of stop bits
82pub enum StopBits {
83 /// One stop bit
84 Stop1,
85
86 /// Two stop bits
87 Stop2,
88}
89
90#[non_exhaustive]
91#[derive(Clone, Copy, PartialEq, Eq, Debug)]
92#[cfg_attr(feature = "defmt", derive(defmt::Format))]
93/// Config Error
94pub enum ConfigError {
95 /// Rx or Tx not enabled
96 RxOrTxNotEnabled,
97
98 /// The baud rate could not be configured with the given clocks.
99 InvalidBaudRate,
100}
101
102#[non_exhaustive]
103#[derive(Clone, Copy, PartialEq, Eq, Debug)]
104/// Config
105pub struct Config {
106 /// UART clock source.
107 pub clock_source: ClockSel,
108
109 /// Baud rate
110 pub baudrate: u32,
111
112 /// Number of data bits.
113 pub data_bits: DataBits,
114
115 /// Number of stop bits.
116 pub stop_bits: StopBits,
117
118 /// Parity type.
119 pub parity: Parity,
120
121 /// The order of bits in a transmitted/received byte.
122 pub msb_order: BitOrder,
123
124 /// If true: the `TX` is internally connected to `RX`.
125 pub loop_back_enable: bool,
126
127 // TODO: Pending way to check if uart is extended
128 // /// If true: [manchester coding] is used.
129 // ///
130 // /// [manchester coding]: https://en.wikipedia.org/wiki/Manchester_code
131 // pub manchester: bool,
132
133 // TODO: majority voting
134 /// If true: the built-in FIFO is enabled.
135 pub fifo_enable: bool,
136
137 // TODO: glitch suppression
138 /// If true: invert TX pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle).
139 pub invert_tx: bool,
140
141 /// If true: invert RX pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle).
142 pub invert_rx: bool,
143
144 /// If true: invert RTS pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle).
145 pub invert_rts: bool,
146
147 /// If true: invert CTS pin signal values (V<sub>DD</sub> = 0/mark, Gnd = 1/idle).
148 pub invert_cts: bool,
149
150 /// Set the pull configuration for the TX pin.
151 pub tx_pull: Pull,
152
153 /// Set the pull configuration for the RX pin.
154 pub rx_pull: Pull,
155
156 /// Set the pull configuration for the RTS pin.
157 pub rts_pull: Pull,
158
159 /// Set the pull configuration for the CTS pin.
160 pub cts_pull: Pull,
161}
162
163impl Default for Config {
164 fn default() -> Self {
165 Self {
166 clock_source: ClockSel::MfClk,
167 baudrate: 115200,
168 data_bits: DataBits::DataBits8,
169 stop_bits: StopBits::Stop1,
170 parity: Parity::ParityNone,
171 // hardware default
172 msb_order: BitOrder::LsbFirst,
173 loop_back_enable: false,
174 // manchester: false,
175 fifo_enable: false,
176 invert_tx: false,
177 invert_rx: false,
178 invert_rts: false,
179 invert_cts: false,
180 tx_pull: Pull::None,
181 rx_pull: Pull::None,
182 rts_pull: Pull::None,
183 cts_pull: Pull::None,
184 }
185 }
186}
187
188/// Bidirectional UART Driver, which acts as a combination of [`UartTx`] and [`UartRx`].
189///
190/// ### Notes on [`embedded_io::Read`]
191///
192/// [`embedded_io::Read`] requires guarantees that the base [`UartRx`] cannot provide.
193///
194/// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`]
195/// as alternatives that do provide the necessary guarantees for `embedded_io::Read`.
196pub struct Uart<'d, M: Mode> {
197 tx: UartTx<'d, M>,
198 rx: UartRx<'d, M>,
199}
200
201impl<'d, M: Mode> SetConfig for Uart<'d, M> {
202 type Config = Config;
203 type ConfigError = ConfigError;
204
205 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
206 self.set_config(config)
207 }
208}
209
210/// Serial error
211#[derive(Debug, Eq, PartialEq, Copy, Clone)]
212#[cfg_attr(feature = "defmt", derive(defmt::Format))]
213#[non_exhaustive]
214pub enum Error {
215 Framing,
216
217 Noise,
218
219 Overrun,
220
221 Parity,
222
223 Break,
224}
225
226impl core::fmt::Display for Error {
227 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
228 let message = match self {
229 Self::Framing => "Framing Error",
230 Self::Noise => "Noise Error",
231 Self::Overrun => "RX Buffer Overrun",
232 Self::Parity => "Parity Check Error",
233 Self::Break => "Break Error",
234 };
235
236 write!(f, "{}", message)
237 }
238}
239
240impl core::error::Error for Error {}
241
242impl embedded_io::Error for Error {
243 fn kind(&self) -> embedded_io::ErrorKind {
244 embedded_io::ErrorKind::Other
245 }
246}
247
248/// Rx-only UART Driver.
249///
250/// Can be obtained from [`Uart::split`], or can be constructed independently,
251/// if you do not need the transmitting half of the driver.
252pub struct UartRx<'d, M: Mode> {
253 info: &'static Info,
254 state: &'static State,
255 rx: Option<Peri<'d, AnyPin>>,
256 rts: Option<Peri<'d, AnyPin>>,
257 _phantom: PhantomData<M>,
258}
259
260impl<'d, M: Mode> SetConfig for UartRx<'d, M> {
261 type Config = Config;
262 type ConfigError = ConfigError;
263
264 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
265 self.set_config(config)
266 }
267}
268
269impl<'d> UartRx<'d, Blocking> {
270 /// Create a new rx-only UART with no hardware flow control.
271 ///
272 /// Useful if you only want Uart Rx. It saves 1 pin.
273 pub fn new_blocking<T: Instance>(
274 peri: Peri<'d, T>,
275 rx: Peri<'d, impl RxPin<T>>,
276 config: Config,
277 ) -> Result<Self, ConfigError> {
278 Self::new_inner(peri, new_pin!(rx, config.rx_pf()), None, config)
279 }
280
281 /// Create a new rx-only UART with a request-to-send pin
282 pub fn new_blocking_with_rts<T: Instance>(
283 peri: Peri<'d, T>,
284 rx: Peri<'d, impl RxPin<T>>,
285 rts: Peri<'d, impl RtsPin<T>>,
286 config: Config,
287 ) -> Result<Self, ConfigError> {
288 Self::new_inner(
289 peri,
290 new_pin!(rx, config.rx_pf()),
291 new_pin!(rts, config.rts_pf()),
292 config,
293 )
294 }
295}
296
297impl<'d, M: Mode> UartRx<'d, M> {
298 /// Perform a blocking read into `buffer`
299 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
300 let r = self.info.regs;
301
302 for b in buffer {
303 // Wait if nothing has arrived yet.
304 while r.stat().read().rxfe() {}
305
306 // Prevent the compiler from reading from buffer too early
307 compiler_fence(Ordering::Acquire);
308 *b = read_with_error(r)?;
309 }
310
311 Ok(())
312 }
313
314 /// Reconfigure the driver
315 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
316 if let Some(ref rx) = self.rx {
317 rx.update_pf(config.rx_pf());
318 }
319
320 if let Some(ref rts) = self.rts {
321 rts.update_pf(config.rts_pf());
322 }
323
324 reconfigure(self.info, self.state, config)
325 }
326
327 /// Set baudrate
328 pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> {
329 set_baudrate(&self.info, self.state.clock.load(Ordering::Relaxed), baudrate)
330 }
331}
332
333impl<'d, M: Mode> Drop for UartRx<'d, M> {
334 fn drop(&mut self) {
335 self.rx.as_ref().map(|x| x.set_as_disconnected());
336 self.rts.as_ref().map(|x| x.set_as_disconnected());
337 }
338}
339
340/// Tx-only UART Driver.
341///
342/// Can be obtained from [`Uart::split`], or can be constructed independently,
343/// if you do not need the receiving half of the driver.
344pub struct UartTx<'d, M: Mode> {
345 info: &'static Info,
346 state: &'static State,
347 tx: Option<Peri<'d, AnyPin>>,
348 cts: Option<Peri<'d, AnyPin>>,
349 _phantom: PhantomData<M>,
350}
351
352impl<'d, M: Mode> SetConfig for UartTx<'d, M> {
353 type Config = Config;
354 type ConfigError = ConfigError;
355
356 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
357 reconfigure(self.info, self.state, config)
358 }
359}
360
361impl<'d> UartTx<'d, Blocking> {
362 /// Create a new blocking tx-only UART with no hardware flow control.
363 ///
364 /// Useful if you only want Uart Tx. It saves 1 pin.
365 pub fn new_blocking<T: Instance>(
366 peri: Peri<'d, T>,
367 tx: Peri<'d, impl TxPin<T>>,
368 config: Config,
369 ) -> Result<Self, ConfigError> {
370 Self::new_inner(peri, new_pin!(tx, config.tx_pf()), None, config)
371 }
372
373 /// Create a new blocking tx-only UART with a clear-to-send pin
374 pub fn new_blocking_with_cts<T: Instance>(
375 peri: Peri<'d, T>,
376 tx: Peri<'d, impl TxPin<T>>,
377 cts: Peri<'d, impl CtsPin<T>>,
378 config: Config,
379 ) -> Result<Self, ConfigError> {
380 Self::new_inner(
381 peri,
382 new_pin!(tx, config.tx_pf()),
383 new_pin!(cts, config.cts_pf()),
384 config,
385 )
386 }
387}
388
389impl<'d, M: Mode> UartTx<'d, M> {
390 /// Perform a blocking UART write
391 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
392 let r = self.info.regs;
393
394 for &b in buffer {
395 // Wait if there is no space
396 while !r.stat().read().txfe() {}
397
398 // Prevent the compiler from writing to buffer too early
399 compiler_fence(Ordering::Release);
400 r.txdata().write(|w| {
401 w.set_data(b);
402 });
403 }
404
405 Ok(())
406 }
407
408 /// Block until transmission complete
409 pub fn blocking_flush(&mut self) -> Result<(), Error> {
410 let r = self.info.regs;
411
412 // Wait until TX fifo/buffer is empty
413 while r.stat().read().txfe() {}
414 Ok(())
415 }
416
417 /// Send break character
418 pub fn send_break(&self) {
419 let r = self.info.regs;
420
421 r.lcrh().modify(|w| {
422 w.set_brk(true);
423 });
424 }
425
426 /// Check if UART is busy.
427 pub fn busy(&self) -> bool {
428 busy(self.info.regs)
429 }
430
431 /// Reconfigure the driver
432 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
433 if let Some(ref tx) = self.tx {
434 tx.update_pf(config.tx_pf());
435 }
436
437 if let Some(ref cts) = self.cts {
438 cts.update_pf(config.cts_pf());
439 }
440
441 reconfigure(self.info, self.state, config)
442 }
443
444 /// Set baudrate
445 pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> {
446 set_baudrate(&self.info, self.state.clock.load(Ordering::Relaxed), baudrate)
447 }
448}
449
450impl<'d, M: Mode> Drop for UartTx<'d, M> {
451 fn drop(&mut self) {
452 self.tx.as_ref().map(|x| x.set_as_disconnected());
453 self.cts.as_ref().map(|x| x.set_as_disconnected());
454 }
455}
456
457impl<'d> Uart<'d, Blocking> {
458 /// Create a new blocking bidirectional UART.
459 pub fn new_blocking<T: Instance>(
460 peri: Peri<'d, T>,
461 rx: Peri<'d, impl RxPin<T>>,
462 tx: Peri<'d, impl TxPin<T>>,
463 config: Config,
464 ) -> Result<Self, ConfigError> {
465 Self::new_inner(
466 peri,
467 new_pin!(rx, config.rx_pf()),
468 new_pin!(tx, config.tx_pf()),
469 None,
470 None,
471 config,
472 )
473 }
474
475 /// Create a new bidirectional UART with request-to-send and clear-to-send pins
476 pub fn new_blocking_with_rtscts<T: Instance>(
477 peri: Peri<'d, T>,
478 rx: Peri<'d, impl RxPin<T>>,
479 tx: Peri<'d, impl TxPin<T>>,
480 rts: Peri<'d, impl RtsPin<T>>,
481 cts: Peri<'d, impl CtsPin<T>>,
482 config: Config,
483 ) -> Result<Self, ConfigError> {
484 Self::new_inner(
485 peri,
486 new_pin!(rx, config.rx_pf()),
487 new_pin!(tx, config.tx_pf()),
488 new_pin!(rts, config.rts_pf()),
489 new_pin!(cts, config.cts_pf()),
490 config,
491 )
492 }
493}
494
495impl<'d, M: Mode> Uart<'d, M> {
496 /// Perform a blocking write
497 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
498 self.tx.blocking_write(buffer)
499 }
500
501 /// Block until transmission complete
502 pub fn blocking_flush(&mut self) -> Result<(), Error> {
503 self.tx.blocking_flush()
504 }
505
506 /// Check if UART is busy.
507 pub fn busy(&self) -> bool {
508 self.tx.busy()
509 }
510
511 /// Perform a blocking read into `buffer`
512 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
513 self.rx.blocking_read(buffer)
514 }
515
516 /// Split the Uart into a transmitter and receiver, which is
517 /// particularly useful when having two tasks correlating to
518 /// transmitting and receiving.
519 pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) {
520 (self.tx, self.rx)
521 }
522
523 /// Split the Uart into a transmitter and receiver by mutable reference,
524 /// which is particularly useful when having two tasks correlating to
525 /// transmitting and receiving.
526 pub fn split_ref(&mut self) -> (&mut UartTx<'d, M>, &mut UartRx<'d, M>) {
527 (&mut self.tx, &mut self.rx)
528 }
529
530 /// Reconfigure the driver
531 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
532 self.tx.set_config(config)?;
533 self.rx.set_config(config)
534 }
535
536 /// Send break character
537 pub fn send_break(&self) {
538 self.tx.send_break();
539 }
540
541 /// Set baudrate
542 pub fn set_baudrate(&self, baudrate: u32) -> Result<(), ConfigError> {
543 set_baudrate(&self.tx.info, self.tx.state.clock.load(Ordering::Relaxed), baudrate)
544 }
545}
546
547/// Peripheral instance trait.
548#[allow(private_bounds)]
549pub trait Instance: SealedInstance + PeripheralType {
550 type Interrupt: crate::interrupt::typelevel::Interrupt;
551}
552
553/// UART `TX` pin trait
554pub trait TxPin<T: Instance>: crate::gpio::Pin {
555 /// Get the PF number needed to use this pin as `TX`.
556 fn pf_num(&self) -> u8;
557}
558
559/// UART `RX` pin trait
560pub trait RxPin<T: Instance>: crate::gpio::Pin {
561 /// Get the PF number needed to use this pin as `RX`.
562 fn pf_num(&self) -> u8;
563}
564
565/// UART `CTS` pin trait
566pub trait CtsPin<T: Instance>: crate::gpio::Pin {
567 /// Get the PF number needed to use this pin as `CTS`.
568 fn pf_num(&self) -> u8;
569}
570
571/// UART `RTS` pin trait
572pub trait RtsPin<T: Instance>: crate::gpio::Pin {
573 /// Get the PF number needed to use this pin as `RTS`.
574 fn pf_num(&self) -> u8;
575}
576
577// ==== IMPL types ====
578
579pub(crate) struct Info {
580 pub(crate) regs: Regs,
581 pub(crate) interrupt: Interrupt,
582}
583
584pub(crate) struct State {
585 /// The clock rate of the UART in Hz.
586 clock: AtomicU32,
587}
588
589impl State {
590 pub const fn new() -> Self {
591 Self {
592 clock: AtomicU32::new(0),
593 }
594 }
595}
596
597impl<'d, M: Mode> UartRx<'d, M> {
598 fn new_inner<T: Instance>(
599 _peri: Peri<'d, T>,
600 rx: Option<Peri<'d, AnyPin>>,
601 rts: Option<Peri<'d, AnyPin>>,
602 config: Config,
603 ) -> Result<Self, ConfigError> {
604 let mut this = Self {
605 info: T::info(),
606 state: T::state(),
607 rx,
608 rts,
609 _phantom: PhantomData,
610 };
611 this.enable_and_configure(&config)?;
612
613 Ok(this)
614 }
615
616 fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
617 let info = self.info;
618
619 enable(info.regs);
620 configure(info, self.state, config, true, self.rts.is_some(), false, false)?;
621
622 Ok(())
623 }
624}
625
626impl<'d, M: Mode> UartTx<'d, M> {
627 fn new_inner<T: Instance>(
628 _peri: Peri<'d, T>,
629 tx: Option<Peri<'d, AnyPin>>,
630 cts: Option<Peri<'d, AnyPin>>,
631 config: Config,
632 ) -> Result<Self, ConfigError> {
633 let mut this = Self {
634 info: T::info(),
635 state: T::state(),
636 tx,
637 cts,
638 _phantom: PhantomData,
639 };
640 this.enable_and_configure(&config)?;
641
642 Ok(this)
643 }
644
645 fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
646 let info = self.info;
647 let state = self.state;
648
649 enable(info.regs);
650 configure(info, state, config, false, false, true, self.cts.is_some())?;
651
652 Ok(())
653 }
654}
655
656impl<'d, M: Mode> Uart<'d, M> {
657 fn new_inner<T: Instance>(
658 _peri: Peri<'d, T>,
659 rx: Option<Peri<'d, AnyPin>>,
660 tx: Option<Peri<'d, AnyPin>>,
661 rts: Option<Peri<'d, AnyPin>>,
662 cts: Option<Peri<'d, AnyPin>>,
663 config: Config,
664 ) -> Result<Self, ConfigError> {
665 let info = T::info();
666 let state = T::state();
667
668 let mut this = Self {
669 tx: UartTx {
670 info,
671 state,
672 tx,
673 cts,
674 _phantom: PhantomData,
675 },
676 rx: UartRx {
677 info,
678 state,
679 rx,
680 rts,
681 _phantom: PhantomData,
682 },
683 };
684 this.enable_and_configure(&config)?;
685
686 Ok(this)
687 }
688
689 fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
690 let info = self.rx.info;
691 let state = self.rx.state;
692
693 enable(info.regs);
694 configure(
695 info,
696 state,
697 config,
698 true,
699 self.rx.rts.is_some(),
700 true,
701 self.tx.cts.is_some(),
702 )?;
703
704 info.interrupt.unpend();
705 unsafe { info.interrupt.enable() };
706
707 Ok(())
708 }
709}
710
711impl Config {
712 fn tx_pf(&self) -> PfType {
713 PfType::output(self.tx_pull, self.invert_tx)
714 }
715
716 fn rx_pf(&self) -> PfType {
717 PfType::input(self.rx_pull, self.invert_rx)
718 }
719
720 fn rts_pf(&self) -> PfType {
721 PfType::output(self.rts_pull, self.invert_rts)
722 }
723
724 fn cts_pf(&self) -> PfType {
725 PfType::input(self.rts_pull, self.invert_rts)
726 }
727}
728
729fn enable(regs: Regs) {
730 let gprcm = regs.gprcm(0);
731
732 gprcm.rstctl().write(|w| {
733 w.set_resetstkyclr(true);
734 w.set_resetassert(true);
735 w.set_key(vals::ResetKey::KEY);
736 });
737
738 gprcm.pwren().write(|w| {
739 w.set_enable(true);
740 w.set_key(vals::PwrenKey::KEY);
741 });
742}
743
744fn configure(
745 info: &Info,
746 state: &State,
747 config: &Config,
748 enable_rx: bool,
749 enable_rts: bool,
750 enable_tx: bool,
751 enable_cts: bool,
752) -> Result<(), ConfigError> {
753 let r = info.regs;
754
755 if !enable_rx && !enable_tx {
756 return Err(ConfigError::RxOrTxNotEnabled);
757 }
758
759 // SLAU846B says that clocks should be enabled before disabling the uart.
760 r.clksel().write(|w| match config.clock_source {
761 ClockSel::LfClk => {
762 w.set_lfclk_sel(true);
763 w.set_mfclk_sel(false);
764 w.set_busclk_sel(false);
765 }
766 ClockSel::MfClk => {
767 w.set_mfclk_sel(true);
768 w.set_lfclk_sel(false);
769 w.set_busclk_sel(false);
770 }
771 });
772
773 let clock = match config.clock_source {
774 ClockSel::LfClk => 32768,
775 ClockSel::MfClk => 4_000_000,
776 };
777
778 state.clock.store(clock, Ordering::Relaxed);
779
780 info.regs.ctl0().modify(|w| {
781 w.set_lbe(config.loop_back_enable);
782 // Errata UART_ERR_02, must set RXE to allow use of EOT.
783 w.set_rxe(enable_rx | enable_tx);
784 w.set_txe(enable_tx);
785 // RXD_OUT_EN and TXD_OUT_EN?
786 w.set_menc(false);
787 w.set_mode(vals::Mode::UART);
788 w.set_rtsen(enable_rts);
789 w.set_ctsen(enable_cts);
790 // oversampling is set later
791 w.set_fen(config.fifo_enable);
792 // TODO: config
793 w.set_majvote(false);
794 w.set_msbfirst(matches!(config.msb_order, BitOrder::MsbFirst));
795 });
796
797 info.regs.ifls().modify(|w| {
798 // TODO: Need power domain info for other options.
799 w.set_txiflsel(vals::Iflssel::AT_LEAST_ONE);
800 w.set_rxiflsel(vals::Iflssel::AT_LEAST_ONE);
801 });
802
803 info.regs.lcrh().modify(|w| {
804 let eps = if matches!(config.parity, Parity::ParityEven) {
805 vals::Eps::EVEN
806 } else {
807 vals::Eps::ODD
808 };
809
810 let wlen = match config.data_bits {
811 DataBits::DataBits5 => vals::Wlen::DATABIT5,
812 DataBits::DataBits6 => vals::Wlen::DATABIT6,
813 DataBits::DataBits7 => vals::Wlen::DATABIT7,
814 DataBits::DataBits8 => vals::Wlen::DATABIT8,
815 };
816
817 // Used in LIN mode only
818 w.set_brk(false);
819 w.set_pen(config.parity != Parity::ParityNone);
820 w.set_eps(eps);
821 w.set_stp2(matches!(config.stop_bits, StopBits::Stop2));
822 w.set_wlen(wlen);
823 // appears to only be used in RS-485 mode.
824 w.set_sps(false);
825 // IDLE pattern?
826 w.set_sendidle(false);
827 // ignore extdir_setup and extdir_hold, only used in RS-485 mode.
828 });
829
830 set_baudrate_inner(info.regs, clock, config.baudrate)?;
831
832 r.ctl0().modify(|w| {
833 w.set_enable(true);
834 });
835
836 Ok(())
837}
838
839fn reconfigure(info: &Info, state: &State, config: &Config) -> Result<(), ConfigError> {
840 info.interrupt.disable();
841 let r = info.regs;
842 let ctl0 = r.ctl0().read();
843 configure(info, state, config, ctl0.rxe(), ctl0.rtsen(), ctl0.txe(), ctl0.ctsen())?;
844
845 info.interrupt.unpend();
846 unsafe { info.interrupt.enable() };
847
848 Ok(())
849}
850
851/// Set the baud rate and clock settings.
852///
853/// This should be done relatively late during configuration since some clock settings are invalid depending on mode.
854fn set_baudrate(info: &Info, clock: u32, baudrate: u32) -> Result<(), ConfigError> {
855 let r = info.regs;
856
857 info.interrupt.disable();
858
859 // Programming baud rate requires that the peripheral is disabled
860 critical_section::with(|_cs| {
861 r.ctl0().modify(|w| {
862 w.set_enable(false);
863 });
864 });
865
866 // Wait for end of transmission per suggestion in SLAU 845 section 18.3.28
867 while !r.stat().read().txfe() {}
868
869 set_baudrate_inner(r, clock, baudrate)?;
870
871 critical_section::with(|_cs| {
872 r.ctl0().modify(|w| {
873 w.set_enable(true);
874 });
875 });
876
877 info.interrupt.unpend();
878 unsafe { info.interrupt.enable() };
879
880 Ok(())
881}
882
883fn set_baudrate_inner(regs: Regs, clock: u32, baudrate: u32) -> Result<(), ConfigError> {
884 // Quoting SLAU846 section 18.2.3.4:
885 // "When IBRD = 0, FBRD is ignored and no data gets transferred by the UART."
886 const MIN_IBRD: u16 = 1;
887
888 // FBRD can be 0
889 // FBRD is at most a 6-bit number.
890 const MAX_FBRD: u8 = 2_u8.pow(6);
891
892 const DIVS: [(u8, vals::Clkdiv); 8] = [
893 (1, vals::Clkdiv::DIV_BY_1),
894 (2, vals::Clkdiv::DIV_BY_2),
895 (3, vals::Clkdiv::DIV_BY_3),
896 (4, vals::Clkdiv::DIV_BY_4),
897 (5, vals::Clkdiv::DIV_BY_5),
898 (6, vals::Clkdiv::DIV_BY_6),
899 (7, vals::Clkdiv::DIV_BY_7),
900 (8, vals::Clkdiv::DIV_BY_8),
901 ];
902
903 // Quoting from SLAU 846 section 18.2.3.4:
904 // "Select oversampling by 3 or 8 to achieve higher speed with UARTclk/8 or UARTclk/3. In this case
905 // the receiver tolerance to clock deviation is reduced."
906 //
907 // "Select oversampling by 16 to increase the tolerance of the receiver to clock deviations. The
908 // maximum speed is limited to UARTclk/16."
909 //
910 // Based on these requirements, prioritize higher oversampling first to increase tolerance to clock
911 // deviation. If no valid BRD value can be found satisifying the highest sample rate, then reduce
912 // sample rate until valid parameters are found.
913 const OVS: [(u8, vals::Hse); 3] = [(16, vals::Hse::OVS16), (8, vals::Hse::OVS8), (3, vals::Hse::OVS3)];
914
915 // 3x oversampling is not supported with manchester coding, DALI or IrDA.
916 let x3_invalid = {
917 let ctl0 = regs.ctl0().read();
918 let irctl = regs.irctl().read();
919
920 ctl0.menc() || matches!(ctl0.mode(), vals::Mode::DALI) || irctl.iren()
921 };
922 let mut found = None;
923
924 'outer: for &(oversampling, hse_value) in &OVS {
925 if matches!(hse_value, vals::Hse::OVS3) && x3_invalid {
926 continue;
927 }
928
929 // Verify that the selected oversampling does not require a clock faster than what the hardware
930 // is provided.
931 let Some(min_clock) = baudrate.checked_mul(oversampling as u32) else {
932 trace!(
933 "{}x oversampling would cause overflow for clock: {} Hz",
934 oversampling,
935 clock
936 );
937 continue;
938 };
939
940 if min_clock > clock {
941 trace!("{} oversampling is too high for clock: {} Hz", oversampling, clock);
942 continue;
943 }
944
945 for &(div, div_value) in &DIVS {
946 trace!(
947 "Trying div: {}, oversampling {} for {} baud",
948 div,
949 oversampling,
950 baudrate
951 );
952
953 let Some((ibrd, fbrd)) = calculate_brd(clock, div, baudrate, oversampling) else {
954 trace!("Calculating BRD overflowed: trying another divider");
955 continue;
956 };
957
958 if ibrd < MIN_IBRD || fbrd > MAX_FBRD {
959 trace!("BRD was invalid: trying another divider");
960 continue;
961 }
962
963 found = Some((hse_value, div_value, ibrd, fbrd));
964 break 'outer;
965 }
966 }
967
968 let Some((hse, div, ibrd, fbrd)) = found else {
969 return Err(ConfigError::InvalidBaudRate);
970 };
971
972 regs.clkdiv().write(|w| {
973 w.set_ratio(div);
974 });
975
976 regs.ibrd().write(|w| {
977 w.set_divint(ibrd);
978 });
979
980 regs.fbrd().write(|w| {
981 w.set_divfrac(fbrd);
982 });
983
984 regs.ctl0().modify(|w| {
985 w.set_hse(hse);
986 });
987
988 Ok(())
989}
990
991/// Calculate the integer and fractional parts of the `BRD` value.
992///
993/// Returns [`None`] if calculating this results in overflows.
994///
995/// Values returned are `(ibrd, fbrd)`
996fn calculate_brd(clock: u32, div: u8, baud: u32, oversampling: u8) -> Option<(u16, u8)> {
997 use fixed::types::U26F6;
998
999 // Calculate BRD according to SLAU 846 section 18.2.3.4.
1000 //
1001 // BRD is a 22-bit value with 16 integer bits and 6 fractional bits.
1002 //
1003 // uart_clock = clock / div
1004 // brd = ibrd.fbrd = uart_clock / (oversampling * baud)"
1005 //
1006 // It is tempting to rearrange the equation such that there is only a single division in
1007 // order to reduce error. However this is wrong since the denominator ends up being too
1008 // small to represent in 6 fraction bits. This means that FBRD would always be 0.
1009 //
1010 // Calculations are done in a U16F6 format. However the fixed crate has no such representation.
1011 // U26F6 is used since it has the same number of fractional bits and we verify at the end that
1012 // the integer part did not overflow.
1013 let clock = U26F6::from_num(clock);
1014 let div = U26F6::from_num(div);
1015 let oversampling = U26F6::from_num(oversampling);
1016 let baud = U26F6::from_num(baud);
1017
1018 let uart_clock = clock.checked_div(div)?;
1019
1020 // oversampling * baud
1021 let denom = oversampling.checked_mul(baud)?;
1022 // uart_clock / (oversampling * baud)
1023 let brd = uart_clock.checked_div(denom)?;
1024
1025 // Checked is used to determine overflow in the 10 most singificant bits since the
1026 // actual representation of BRD is U16F6.
1027 let ibrd = brd.checked_to_num::<u16>()?;
1028
1029 // We need to scale FBRD's representation to an integer.
1030 let fbrd_scale = U26F6::from_num(2_u32.checked_pow(U26F6::FRAC_NBITS)?);
1031
1032 // It is suggested that 0.5 is added to ensure that any fractional parts round up to the next
1033 // integer. If it doesn't round up then it'll get discarded which is okay.
1034 let half = U26F6::from_num(1) / U26F6::from_num(2);
1035 // fbrd = INT(((FRAC(BRD) * 64) + 0.5))
1036 let fbrd = brd
1037 .frac()
1038 .checked_mul(fbrd_scale)?
1039 .checked_add(half)?
1040 .checked_to_num::<u8>()?;
1041
1042 Some((ibrd, fbrd))
1043}
1044
1045fn read_with_error(r: Regs) -> Result<u8, Error> {
1046 let rx = r.rxdata().read();
1047
1048 if rx.frmerr() {
1049 return Err(Error::Framing);
1050 } else if rx.parerr() {
1051 return Err(Error::Parity);
1052 } else if rx.brkerr() {
1053 return Err(Error::Break);
1054 } else if rx.ovrerr() {
1055 return Err(Error::Overrun);
1056 } else if rx.nerr() {
1057 return Err(Error::Noise);
1058 }
1059
1060 Ok(rx.data())
1061}
1062
1063/// This function assumes CTL0.ENABLE is set (for errata cases).
1064fn busy(r: Regs) -> bool {
1065 // Errata UART_ERR_08
1066 if cfg!(any(
1067 mspm0g151x, mspm0g351x, mspm0l110x, mspm0l130x, mspm0l134x, mspm0c110x,
1068 )) {
1069 let stat = r.stat().read();
1070 // "Poll TXFIFO status and the CTL0.ENABLE register bit to identify BUSY status."
1071 !stat.txfe()
1072 } else {
1073 r.stat().read().busy()
1074 }
1075}
1076
1077// TODO: Implement when dma uart is implemented.
1078fn dma_enabled(_r: Regs) -> bool {
1079 false
1080}
1081
1082pub(crate) trait SealedInstance {
1083 fn info() -> &'static Info;
1084 fn state() -> &'static State;
1085 fn buffered_state() -> &'static BufferedState;
1086}
1087
1088macro_rules! impl_uart_instance {
1089 ($instance: ident) => {
1090 impl crate::uart::SealedInstance for crate::peripherals::$instance {
1091 fn info() -> &'static crate::uart::Info {
1092 use crate::interrupt::typelevel::Interrupt;
1093 use crate::uart::Info;
1094
1095 const INFO: Info = Info {
1096 regs: crate::pac::$instance,
1097 interrupt: crate::interrupt::typelevel::$instance::IRQ,
1098 };
1099 &INFO
1100 }
1101
1102 fn state() -> &'static crate::uart::State {
1103 use crate::uart::State;
1104
1105 static STATE: State = State::new();
1106 &STATE
1107 }
1108
1109 fn buffered_state() -> &'static crate::uart::BufferedState {
1110 use crate::uart::BufferedState;
1111
1112 static STATE: BufferedState = BufferedState::new();
1113 &STATE
1114 }
1115 }
1116
1117 impl crate::uart::Instance for crate::peripherals::$instance {
1118 type Interrupt = crate::interrupt::typelevel::$instance;
1119 }
1120 };
1121}
1122
1123macro_rules! impl_uart_tx_pin {
1124 ($instance: ident, $pin: ident, $pf: expr) => {
1125 impl crate::uart::TxPin<crate::peripherals::$instance> for crate::peripherals::$pin {
1126 fn pf_num(&self) -> u8 {
1127 $pf
1128 }
1129 }
1130 };
1131}
1132
1133macro_rules! impl_uart_rx_pin {
1134 ($instance: ident, $pin: ident, $pf: expr) => {
1135 impl crate::uart::RxPin<crate::peripherals::$instance> for crate::peripherals::$pin {
1136 fn pf_num(&self) -> u8 {
1137 $pf
1138 }
1139 }
1140 };
1141}
1142
1143macro_rules! impl_uart_cts_pin {
1144 ($instance: ident, $pin: ident, $pf: expr) => {
1145 impl crate::uart::CtsPin<crate::peripherals::$instance> for crate::peripherals::$pin {
1146 fn pf_num(&self) -> u8 {
1147 $pf
1148 }
1149 }
1150 };
1151}
1152
1153macro_rules! impl_uart_rts_pin {
1154 ($instance: ident, $pin: ident, $pf: expr) => {
1155 impl crate::uart::RtsPin<crate::peripherals::$instance> for crate::peripherals::$pin {
1156 fn pf_num(&self) -> u8 {
1157 $pf
1158 }
1159 }
1160 };
1161}
1162
1163#[cfg(test)]
1164mod tests {
1165 use super::calculate_brd;
1166
1167 /// This is a smoke test based on the example in SLAU 846 section 18.2.3.4.
1168 #[test]
1169 fn datasheet() {
1170 let brd = calculate_brd(40_000_000, 1, 19200, 16);
1171
1172 assert!(matches!(brd, Some((130, 13))));
1173 }
1174}