aboutsummaryrefslogtreecommitdiff
path: root/embassy-mspm0/src/uart/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-mspm0/src/uart/mod.rs')
-rw-r--r--embassy-mspm0/src/uart/mod.rs1174
1 files changed, 1174 insertions, 0 deletions
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}