stm32f4xx_hal/
serial.rs

1//!
2//! Asynchronous serial communication using USART peripherals
3//!
4//! # Word length
5//!
6//! By default, the UART/USART uses 8 data bits. The `Serial`, `Rx`, and `Tx` structs implement
7//! the embedded-hal read and write traits with `u8` as the word type.
8//!
9//! You can also configure the hardware to use 9 data bits with the `Config` `wordlength_9()`
10//! function. After creating a `Serial` with this option, use the `with_u16_data()` function to
11//! convert the `Serial<_, u8>` object into a `Serial<_, u16>` that can send and receive `u16`s.
12//!
13//! In this mode, the `Serial<_, u16>`, `Rx<_, u16>`, and `Tx<_, u16>` structs instead implement
14//! the embedded-hal read and write traits with `u16` as the word type. You can use these
15//! implementations for 9-bit words.
16
17use 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/// Serial error kind
42///
43/// This represents a common set of serial operation errors. HAL implementations are
44/// free to define more specific or additional error types. However, by providing
45/// a mapping to these common serial errors, generic code can still react to them.
46#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
47#[non_exhaustive]
48pub enum Error {
49    /// The peripheral receive buffer was overrun.
50    Overrun,
51    /// Received data does not conform to the peripheral configuration.
52    /// Can be caused by a misconfigured device on either end of the serial line.
53    FrameFormat,
54    /// Parity check failed.
55    Parity,
56    /// Serial line is too noisy to read valid data.
57    Noise,
58    /// A different error occurred. The original error may contain more information.
59    Other,
60}
61
62/// UART interrupt events
63#[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 interrupt enable
69    Idle = 1 << 4,
70    /// RXNE interrupt enable
71    RxNotEmpty = 1 << 5,
72    /// Transmission complete interrupt enable
73    TransmissionComplete = 1 << 6,
74    /// TXE interrupt enable
75    TxEmpty = 1 << 7,
76    /// PE interrupt enable
77    ParityError = 1 << 8,
78}
79
80/// UART/USART status flags
81#[enumflags2::bitflags]
82#[cfg_attr(feature = "defmt", derive(defmt::Format))]
83#[derive(Debug, Eq, PartialEq, Copy, Clone)]
84#[repr(u16)]
85pub enum Flag {
86    /// Parity error
87    ParityError = 1 << 0,
88    /// Framing error
89    FramingError = 1 << 1,
90    /// Noise detected flag
91    Noise = 1 << 2,
92    /// Overrun error
93    Overrun = 1 << 3,
94    /// IDLE line detected
95    Idle = 1 << 4,
96    /// Read data register not empty
97    RxNotEmpty = 1 << 5,
98    /// Transmission complete
99    TransmissionComplete = 1 << 6,
100    /// Transmit data register empty
101    TxEmpty = 1 << 7,
102    /// LIN break detection flag
103    LinBreak = 1 << 8,
104    /// CTS flag
105    Cts = 1 << 9,
106}
107
108/// UART clearable flags
109#[enumflags2::bitflags]
110#[cfg_attr(feature = "defmt", derive(defmt::Format))]
111#[derive(Debug, Eq, PartialEq, Copy, Clone)]
112#[repr(u16)]
113pub enum CFlag {
114    /// Read data register not empty
115    RxNotEmpty = 1 << 5,
116    /// Transmission complete
117    TransmissionComplete = 1 << 6,
118    /// LIN break detection flag
119    LinBreak = 1 << 8,
120}
121
122pub mod config;
123
124pub use config::Config;
125
126pub use gpio::alt::SerialAsync as CommonPins;
127
128// Implemented by all USART/UART instances
129pub 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
146/// Trait for [`Rx`] interrupt handling.
147pub trait RxISR {
148    /// Return true if the line idle status is set
149    fn is_idle(&self) -> bool;
150
151    /// Return true if the rx register is not empty (and can be read)
152    fn is_rx_not_empty(&self) -> bool;
153
154    /// Clear idle line interrupt flag
155    fn clear_idle_interrupt(&self);
156}
157
158/// Trait for [`Tx`] interrupt handling.
159pub trait TxISR {
160    /// Return true if the tx register is empty (and can accept data)
161    fn is_tx_empty(&self) -> bool;
162}
163
164/// Trait for listening [`Rx`] interrupt events.
165pub trait RxListen {
166    /// Start listening for an rx not empty interrupt event
167    ///
168    /// Note, you will also have to enable the corresponding interrupt
169    /// in the NVIC to start receiving events.
170    fn listen(&mut self);
171
172    /// Stop listening for the rx not empty interrupt event
173    fn unlisten(&mut self);
174
175    /// Start listening for a line idle interrupt event
176    ///
177    /// Note, you will also have to enable the corresponding interrupt
178    /// in the NVIC to start receiving events.
179    fn listen_idle(&mut self);
180
181    /// Stop listening for the line idle interrupt event
182    fn unlisten_idle(&mut self);
183}
184
185/// Trait for listening [`Tx`] interrupt event.
186pub trait TxListen {
187    /// Start listening for a tx empty interrupt event
188    ///
189    /// Note, you will also have to enable the corresponding interrupt
190    /// in the NVIC to start receiving events.
191    fn listen(&mut self);
192
193    /// Stop listening for the tx empty interrupt event
194    fn unlisten(&mut self);
195}
196
197/// Serial abstraction
198pub struct Serial<USART: CommonPins, WORD = u8> {
199    tx: Tx<USART, WORD>,
200    rx: Rx<USART, WORD>,
201}
202
203/// Serial receiver containing RX pin
204pub struct Rx<USART: CommonPins, WORD = u8> {
205    _word: PhantomData<WORD>,
206    usart: USART,
207    pin: Option<USART::Rx<PushPull>>,
208}
209
210/// Serial transmitter containing TX pin
211pub 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        // Enable clock.
265        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        // Reset other registers to disable advanced USART features
285        uart.cr2().reset();
286        uart.cr3().reset();
287        // IrDA configuration - see STM32F411xC/E (RM0383) sections:
288        // 19.3.12 "IrDA SIR ENDEC block"
289        // 19.6.7 "Guard time and prescaler register (USART_GTPR)"
290        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        // Enable transmission and receiving
297        // and configure frame
298
299        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    // The frequency to calculate USARTDIV is this:
322    //
323    // (Taken from STM32F411xC/E Reference Manual,
324    // Section 19.3.4, Equation 1)
325    //
326    // 16 bit oversample: OVER8 = 0
327    // 8 bit oversample:  OVER8 = 1
328    //
329    // USARTDIV =          (pclk)
330    //            ------------------------
331    //            8 x (2 - OVER8) x (baud)
332    //
333    // BUT, the USARTDIV has 4 "fractional" bits, which effectively
334    // means that we need to "correct" the equation as follows:
335    //
336    // USARTDIV =      (pclk) * 16
337    //            ------------------------
338    //            8 x (2 - OVER8) x (baud)
339    //
340    // When OVER8 is enabled, we can only use the lowest three
341    // fractional bits, so we'll need to shift those last four bits
342    // right one bit
343
344    // Calculate correct baudrate divisor on the fly
345    if (pclk_freq / 16) >= baud {
346        // We have the ability to oversample to 16 bits, take
347        // advantage of it.
348        //
349        // We also add `baud / 2` to the `pclk_freq` to ensure
350        // rounding of values to the closest scale, rather than the
351        // floored behavior of normal integer division.
352        let div = (pclk_freq + (baud / 2)) / baud;
353        Ok((false, div))
354    } else if (pclk_freq / 8) >= baud {
355        // We are close enough to pclk where we can only
356        // oversample 8.
357        //
358        // See note above regarding `baud` and rounding.
359        let div = ((pclk_freq * 2) + (baud / 2)) / baud;
360
361        // Ensure the the fractional bits (only 3) are
362        // right-aligned.
363        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    /// Converts this Serial into a version that can read and write `u16` values instead of `u8`s
511    ///
512    /// This can be used with a word length of 9 bits.
513    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    /// Converts this Serial into a version that can read and write `u8` values instead of `u16`s
523    ///
524    /// This can be used with a word length of 8 bits.
525    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    /// This clears `Idle`, `Overrun`, `Noise`, `FrameError` and `ParityError` flags
546    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    /// This clears `Idle`, `Overrun`, `Noise`, `FrameError` and `ParityError` flags
561    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}