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