1use core::fmt;
18use core::marker::PhantomData;
19use enumflags2::BitFlags;
20
21#[allow(unused)]
22use crate::pacext::uart::UartRB;
23mod hal_02;
24mod hal_1;
25
26mod uart_impls;
27use uart_impls::RegisterBlockImpl;
28
29use crate::gpio::{self, PushPull};
30
31use crate::pac;
32
33use crate::rcc::{self, Rcc};
34
35pub mod dma;
36use crate::dma::{
37 traits::{DMASet, PeriAddress},
38 MemoryToPeripheral, PeripheralToMemory,
39};
40
41#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
47#[non_exhaustive]
48pub enum Error {
49 Overrun,
51 FrameFormat,
54 Parity,
56 Noise,
58 Other,
60}
61
62#[enumflags2::bitflags]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65#[derive(Debug, Eq, PartialEq, Copy, Clone)]
66#[repr(u16)]
67pub enum Event {
68 Idle = 1 << 4,
70 RxNotEmpty = 1 << 5,
72 TransmissionComplete = 1 << 6,
74 TxEmpty = 1 << 7,
76 ParityError = 1 << 8,
78}
79
80#[enumflags2::bitflags]
82#[cfg_attr(feature = "defmt", derive(defmt::Format))]
83#[derive(Debug, Eq, PartialEq, Copy, Clone)]
84#[repr(u16)]
85pub enum Flag {
86 ParityError = 1 << 0,
88 FramingError = 1 << 1,
90 Noise = 1 << 2,
92 Overrun = 1 << 3,
94 Idle = 1 << 4,
96 RxNotEmpty = 1 << 5,
98 TransmissionComplete = 1 << 6,
100 TxEmpty = 1 << 7,
102 LinBreak = 1 << 8,
104 Cts = 1 << 9,
106}
107
108#[enumflags2::bitflags]
110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
111#[derive(Debug, Eq, PartialEq, Copy, Clone)]
112#[repr(u16)]
113pub enum CFlag {
114 RxNotEmpty = 1 << 5,
116 TransmissionComplete = 1 << 6,
118 LinBreak = 1 << 8,
120}
121
122pub mod config;
123
124pub use config::Config;
125
126pub use gpio::alt::SerialAsync as CommonPins;
127
128pub trait Instance:
130 crate::Sealed
131 + crate::Ptr<RB: RegisterBlockImpl>
132 + crate::Steal
133 + core::ops::Deref<Target = Self::RB>
134 + rcc::Enable
135 + rcc::Reset
136 + rcc::BusClock
137 + CommonPins
138{
139 #[doc(hidden)]
140 #[inline(always)]
141 fn peri_address() -> u32 {
142 unsafe { &*Self::PTR }.peri_address()
143 }
144}
145
146pub trait RxISR {
148 fn is_idle(&self) -> bool;
150
151 fn is_rx_not_empty(&self) -> bool;
153
154 fn clear_idle_interrupt(&self);
156}
157
158pub trait TxISR {
160 fn is_tx_empty(&self) -> bool;
162}
163
164pub trait RxListen {
166 fn listen(&mut self);
171
172 fn unlisten(&mut self);
174
175 fn listen_idle(&mut self);
180
181 fn unlisten_idle(&mut self);
183}
184
185pub trait TxListen {
187 fn listen(&mut self);
192
193 fn unlisten(&mut self);
195}
196
197pub struct Serial<USART: CommonPins, WORD = u8> {
199 tx: Tx<USART, WORD>,
200 rx: Rx<USART, WORD>,
201}
202
203pub struct Rx<USART: CommonPins, WORD = u8> {
205 _word: PhantomData<WORD>,
206 usart: USART,
207 pin: Option<USART::Rx<PushPull>>,
208}
209
210pub struct Tx<USART: CommonPins, WORD = u8> {
212 _word: PhantomData<WORD>,
213 usart: USART,
214 pin: Option<USART::Tx<PushPull>>,
215}
216
217pub trait SerialExt: Sized + Instance {
218 fn serial<WORD>(
219 self,
220 pins: (impl Into<Self::Tx<PushPull>>, impl Into<Self::Rx<PushPull>>),
221 config: impl Into<config::Config>,
222 rcc: &mut Rcc,
223 ) -> Result<Serial<Self, WORD>, config::InvalidConfig>;
224
225 fn tx<WORD>(
226 self,
227 tx_pin: impl Into<Self::Tx<PushPull>>,
228 config: impl Into<config::Config>,
229 rcc: &mut Rcc,
230 ) -> Result<Tx<Self, WORD>, config::InvalidConfig>;
231
232 fn rx<WORD>(
233 self,
234 rx_pin: impl Into<Self::Rx<PushPull>>,
235 config: impl Into<config::Config>,
236 rcc: &mut Rcc,
237 ) -> Result<Rx<Self, WORD>, config::InvalidConfig>;
238}
239
240impl<USART: Instance, WORD> Serial<USART, WORD> {
241 pub fn new(
242 uart: USART,
243 pins: (
244 impl Into<USART::Tx<PushPull>>,
245 impl Into<USART::Rx<PushPull>>,
246 ),
247 config: impl Into<config::Config>,
248 rcc: &mut Rcc,
249 ) -> Result<Self, config::InvalidConfig> {
250 Self::_new(uart, (Some(pins.0), Some(pins.1)), config, rcc)
251 }
252 fn _new(
253 uart: USART,
254 pins: (
255 Option<impl Into<USART::Tx<PushPull>>>,
256 Option<impl Into<USART::Rx<PushPull>>>,
257 ),
258 config: impl Into<config::Config>,
259 rcc: &mut Rcc,
260 ) -> Result<Self, config::InvalidConfig> {
261 use self::config::*;
262
263 let config = config.into();
264 USART::enable(rcc);
266 USART::reset(rcc);
267
268 let pclk_freq = USART::clock(&rcc.clocks).raw();
269 let baud = config.baudrate.0;
270
271 if !USART::RB::IRDA && config.irda != IrdaMode::None {
272 return Err(config::InvalidConfig);
273 }
274
275 let (over8, div) = if config.irda != IrdaMode::None {
276 let div = (pclk_freq + (baud / 2)) / baud;
277 (false, div)
278 } else {
279 calculate_brr(pclk_freq, baud)?
280 };
281
282 uart.brr().write(|w| unsafe { w.bits(div as u16) });
283
284 uart.cr2().reset();
286 uart.cr3().reset();
287 if config.irda != IrdaMode::None && config.stopbits != StopBits::STOP1 {
291 return Err(config::InvalidConfig);
292 }
293
294 uart.configure_irda(config.irda, pclk_freq);
295
296 uart.cr1().write(|w| {
300 w.ue().set_bit();
301 w.over8().bit(over8);
302 w.te().set_bit();
303 w.re().set_bit();
304 w.m().bit(config.wordlength == WordLength::DataBits9);
305 w.pce().bit(config.parity != Parity::ParityNone);
306 w.ps().bit(config.parity == Parity::ParityOdd)
307 });
308
309 uart.enable_dma(config.dma);
310
311 let serial = Serial {
312 tx: Tx::new(uart, pins.0.map(Into::into)),
313 rx: Rx::new(unsafe { USART::steal() }, pins.1.map(Into::into)),
314 };
315 serial.tx.usart.set_stopbits(config.stopbits);
316 Ok(serial)
317 }
318}
319
320fn calculate_brr(pclk_freq: u32, baud: u32) -> Result<(bool, u32), config::InvalidConfig> {
321 if (pclk_freq / 16) >= baud {
346 let div = (pclk_freq + (baud / 2)) / baud;
353 Ok((false, div))
354 } else if (pclk_freq / 8) >= baud {
355 let div = ((pclk_freq * 2) + (baud / 2)) / baud;
360
361 let frac = div & 0xF;
364 let div = (div & !0xF) | (frac >> 1);
365 Ok((true, div))
366 } else {
367 Err(config::InvalidConfig)
368 }
369}
370
371impl<UART: CommonPins, WORD> Serial<UART, WORD> {
372 pub fn split(self) -> (Tx<UART, WORD>, Rx<UART, WORD>) {
373 (self.tx, self.rx)
374 }
375
376 #[allow(clippy::type_complexity)]
377 pub fn release(
378 self,
379 ) -> (
380 UART,
381 (Option<UART::Tx<PushPull>>, Option<UART::Rx<PushPull>>),
382 ) {
383 (self.tx.usart, (self.tx.pin, self.rx.pin))
384 }
385}
386
387macro_rules! halUsart {
388 ($USART:ty, $Serial:ident, $Rx:ident, $Tx:ident) => {
389 pub type $Serial<WORD = u8> = Serial<$USART, WORD>;
390 pub type $Tx<WORD = u8> = Tx<$USART, WORD>;
391 pub type $Rx<WORD = u8> = Rx<$USART, WORD>;
392
393 impl Instance for $USART {}
394 };
395}
396pub(crate) use halUsart;
397
398halUsart! { pac::USART1, Serial1, Rx1, Tx1 }
399halUsart! { pac::USART2, Serial2, Rx2, Tx2 }
400halUsart! { pac::USART6, Serial6, Rx6, Tx6 }
401
402#[cfg(feature = "usart3")]
403halUsart! { pac::USART3, Serial3, Rx3, Tx3 }
404
405#[cfg(feature = "uart4")]
406macro_rules! halUart {
407 ($UART:ty, $Serial:ident, $Rx:ident, $Tx:ident) => {
408 pub type $Serial<WORD = u8> = Serial<$UART, WORD>;
409 pub type $Tx<WORD = u8> = Tx<$UART, WORD>;
410 pub type $Rx<WORD = u8> = Rx<$UART, WORD>;
411
412 impl Instance for $UART {}
413 };
414}
415
416#[cfg(feature = "uart4")]
417halUart! { pac::UART4, Serial4, Rx4, Tx4 }
418#[cfg(feature = "uart5")]
419halUart! { pac::UART5, Serial5, Rx5, Tx5 }
420#[cfg(feature = "uart7")]
421halUart! { pac::UART7, Serial7, Rx7, Tx7 }
422#[cfg(feature = "uart8")]
423halUart! { pac::UART8, Serial8, Rx8, Tx8 }
424#[cfg(feature = "uart9")]
425halUart! { pac::UART9, Serial9, Rx9, Tx9 }
426#[cfg(feature = "uart10")]
427halUart! { pac::UART10, Serial10, Rx10, Tx10 }
428
429impl<UART: CommonPins> Rx<UART, u8> {
430 pub(crate) fn with_u16_data(self) -> Rx<UART, u16> {
431 Rx::new(self.usart, self.pin)
432 }
433}
434
435impl<UART: CommonPins> Rx<UART, u16> {
436 pub(crate) fn with_u8_data(self) -> Rx<UART, u8> {
437 Rx::new(self.usart, self.pin)
438 }
439}
440
441impl<UART: CommonPins> Tx<UART, u8> {
442 pub(crate) fn with_u16_data(self) -> Tx<UART, u16> {
443 Tx::new(self.usart, self.pin)
444 }
445}
446
447impl<UART: CommonPins> Tx<UART, u16> {
448 pub(crate) fn with_u8_data(self) -> Tx<UART, u8> {
449 Tx::new(self.usart, self.pin)
450 }
451}
452
453impl<UART: CommonPins, WORD> Rx<UART, WORD> {
454 pub(crate) fn new(usart: UART, pin: Option<UART::Rx<PushPull>>) -> Self {
455 Self {
456 _word: PhantomData,
457 usart,
458 pin,
459 }
460 }
461
462 pub fn join(self, tx: Tx<UART, WORD>) -> Serial<UART, WORD> {
463 Serial { tx, rx: self }
464 }
465}
466
467impl<UART: CommonPins, WORD> Tx<UART, WORD> {
468 pub(crate) fn new(usart: UART, pin: Option<UART::Tx<PushPull>>) -> Self {
469 Self {
470 _word: PhantomData,
471 usart,
472 pin,
473 }
474 }
475
476 pub fn join(self, rx: Rx<UART, WORD>) -> Serial<UART, WORD> {
477 Serial { tx: self, rx }
478 }
479}
480
481impl<UART: Instance, WORD> AsRef<Tx<UART, WORD>> for Serial<UART, WORD> {
482 #[inline(always)]
483 fn as_ref(&self) -> &Tx<UART, WORD> {
484 &self.tx
485 }
486}
487
488impl<UART: Instance, WORD> AsRef<Rx<UART, WORD>> for Serial<UART, WORD> {
489 #[inline(always)]
490 fn as_ref(&self) -> &Rx<UART, WORD> {
491 &self.rx
492 }
493}
494
495impl<UART: Instance, WORD> AsMut<Tx<UART, WORD>> for Serial<UART, WORD> {
496 #[inline(always)]
497 fn as_mut(&mut self) -> &mut Tx<UART, WORD> {
498 &mut self.tx
499 }
500}
501
502impl<UART: Instance, WORD> AsMut<Rx<UART, WORD>> for Serial<UART, WORD> {
503 #[inline(always)]
504 fn as_mut(&mut self) -> &mut Rx<UART, WORD> {
505 &mut self.rx
506 }
507}
508
509impl<UART: Instance> Serial<UART, u8> {
510 pub fn with_u16_data(self) -> Serial<UART, u16> {
514 Serial {
515 tx: self.tx.with_u16_data(),
516 rx: self.rx.with_u16_data(),
517 }
518 }
519}
520
521impl<UART: Instance> Serial<UART, u16> {
522 pub fn with_u8_data(self) -> Serial<UART, u8> {
526 Serial {
527 tx: self.tx.with_u8_data(),
528 rx: self.rx.with_u8_data(),
529 }
530 }
531}
532
533impl<UART: Instance, WORD> RxISR for Serial<UART, WORD>
534where
535 Rx<UART, WORD>: RxISR,
536{
537 fn is_idle(&self) -> bool {
538 self.rx.is_idle()
539 }
540
541 fn is_rx_not_empty(&self) -> bool {
542 self.rx.is_rx_not_empty()
543 }
544
545 fn clear_idle_interrupt(&self) {
547 self.rx.clear_idle_interrupt();
548 }
549}
550
551impl<UART: Instance, WORD> RxISR for Rx<UART, WORD> {
552 fn is_idle(&self) -> bool {
553 self.usart.is_idle()
554 }
555
556 fn is_rx_not_empty(&self) -> bool {
557 self.usart.is_rx_not_empty()
558 }
559
560 fn clear_idle_interrupt(&self) {
562 self.usart.clear_idle_interrupt();
563 }
564}
565
566impl<UART: Instance, WORD> TxISR for Serial<UART, WORD>
567where
568 Tx<UART, WORD>: TxISR,
569{
570 fn is_tx_empty(&self) -> bool {
571 self.tx.is_tx_empty()
572 }
573}
574
575impl<UART: Instance, WORD> TxISR for Tx<UART, WORD> {
576 fn is_tx_empty(&self) -> bool {
577 self.usart.is_tx_empty()
578 }
579}
580
581impl<UART: Instance, WORD> RxListen for Rx<UART, WORD> {
582 fn listen(&mut self) {
583 self.usart.listen_rxne()
584 }
585
586 fn unlisten(&mut self) {
587 self.usart.unlisten_rxne()
588 }
589
590 fn listen_idle(&mut self) {
591 self.usart.listen_idle()
592 }
593
594 fn unlisten_idle(&mut self) {
595 self.usart.unlisten_idle()
596 }
597}
598
599impl<UART: Instance, WORD> TxListen for Tx<UART, WORD> {
600 fn listen(&mut self) {
601 self.usart.listen_txe()
602 }
603
604 fn unlisten(&mut self) {
605 self.usart.unlisten_txe()
606 }
607}
608
609impl<UART: Instance, WORD> crate::ClearFlags for Serial<UART, WORD> {
610 type Flag = CFlag;
611
612 #[inline(always)]
613 fn clear_flags(&mut self, flags: impl Into<BitFlags<Self::Flag>>) {
614 self.tx.usart.clear_flags(flags.into())
615 }
616}
617
618impl<UART: Instance, WORD> crate::ReadFlags for Serial<UART, WORD> {
619 type Flag = Flag;
620
621 #[inline(always)]
622 fn flags(&self) -> BitFlags<Self::Flag> {
623 self.tx.usart.flags()
624 }
625}
626
627impl<UART: Instance, WORD> crate::Listen for Serial<UART, WORD> {
628 type Event = Event;
629
630 #[inline(always)]
631 fn listen(&mut self, event: impl Into<BitFlags<Event>>) {
632 self.tx.usart.listen_event(None, Some(event.into()));
633 }
634
635 #[inline(always)]
636 fn listen_only(&mut self, event: impl Into<BitFlags<Self::Event>>) {
637 self.tx
638 .usart
639 .listen_event(Some(BitFlags::ALL), Some(event.into()));
640 }
641
642 #[inline(always)]
643 fn unlisten(&mut self, event: impl Into<BitFlags<Event>>) {
644 self.tx.usart.listen_event(Some(event.into()), None);
645 }
646}
647
648impl<UART: Instance> fmt::Write for Serial<UART>
649where
650 Tx<UART>: fmt::Write,
651{
652 fn write_str(&mut self, s: &str) -> fmt::Result {
653 self.tx.write_str(s)
654 }
655}
656
657impl<UART: Instance> fmt::Write for Tx<UART> {
658 fn write_str(&mut self, s: &str) -> fmt::Result {
659 s.bytes()
660 .try_for_each(|c| nb::block!(self.usart.write_u8(c)))
661 .map_err(|_| fmt::Error)
662 }
663}
664
665impl<UART: Instance> SerialExt for UART {
666 fn serial<WORD>(
667 self,
668 pins: (impl Into<Self::Tx<PushPull>>, impl Into<Self::Rx<PushPull>>),
669 config: impl Into<config::Config>,
670 rcc: &mut Rcc,
671 ) -> Result<Serial<Self, WORD>, config::InvalidConfig> {
672 Serial::new(self, pins, config, rcc)
673 }
674 fn tx<WORD>(
675 self,
676 tx_pin: impl Into<Self::Tx<PushPull>>,
677 config: impl Into<config::Config>,
678 rcc: &mut Rcc,
679 ) -> Result<Tx<Self, WORD>, config::InvalidConfig> {
680 Serial::tx(self, tx_pin, config, rcc)
681 }
682 fn rx<WORD>(
683 self,
684 rx_pin: impl Into<Self::Rx<PushPull>>,
685 config: impl Into<config::Config>,
686 rcc: &mut Rcc,
687 ) -> Result<Rx<Self, WORD>, config::InvalidConfig> {
688 Serial::rx(self, rx_pin, config, rcc)
689 }
690}
691
692impl<UART: Instance, WORD> Serial<UART, WORD> {
693 pub fn tx(
694 usart: UART,
695 tx_pin: impl Into<UART::Tx<PushPull>>,
696 config: impl Into<config::Config>,
697 rcc: &mut Rcc,
698 ) -> Result<Tx<UART, WORD>, config::InvalidConfig> {
699 Self::_new(
700 usart,
701 (Some(tx_pin), None::<UART::Rx<PushPull>>),
702 config,
703 rcc,
704 )
705 .map(|s| s.split().0)
706 }
707}
708
709impl<UART: Instance, WORD> Serial<UART, WORD> {
710 pub fn rx(
711 usart: UART,
712 rx_pin: impl Into<UART::Rx<PushPull>>,
713 config: impl Into<config::Config>,
714 rcc: &mut Rcc,
715 ) -> Result<Rx<UART, WORD>, config::InvalidConfig> {
716 Self::_new(
717 usart,
718 (None::<UART::Tx<PushPull>>, Some(rx_pin)),
719 config,
720 rcc,
721 )
722 .map(|s| s.split().1)
723 }
724}
725
726unsafe impl<UART: Instance> PeriAddress for Rx<UART, u8> {
727 #[inline(always)]
728 fn address(&self) -> u32 {
729 self.usart.peri_address()
730 }
731
732 type MemSize = u8;
733}
734
735unsafe impl<UART: CommonPins, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, PeripheralToMemory>
736 for Rx<UART>
737where
738 UART: DMASet<STREAM, CHANNEL, PeripheralToMemory>,
739{
740}
741
742unsafe impl<UART: Instance> PeriAddress for Tx<UART, u8> {
743 #[inline(always)]
744 fn address(&self) -> u32 {
745 self.usart.peri_address()
746 }
747
748 type MemSize = u8;
749}
750
751unsafe impl<UART: CommonPins, STREAM, const CHANNEL: u8> DMASet<STREAM, CHANNEL, MemoryToPeripheral>
752 for Tx<UART>
753where
754 UART: DMASet<STREAM, CHANNEL, MemoryToPeripheral>,
755{
756}