stm32l4xx_hal/
serial.rs

1//! Serial module
2//!
3//! This module support both polling and interrupt based accesses to the serial peripherals.
4
5use core::fmt;
6use core::marker::PhantomData;
7use core::ops::DerefMut;
8use core::ptr;
9use core::sync::atomic::{self, Ordering};
10use embedded_dma::StaticWriteBuffer;
11use stable_deref_trait::StableDeref;
12
13use crate::hal::serial::{self, Write};
14
15use crate::dma::{
16    dma1, CircBuffer, DMAFrame, FrameReader, FrameSender, Receive, RxDma, TransferPayload,
17    Transmit, TxDma,
18};
19use crate::dmamux::{DmaInput, DmaMux};
20use crate::gpio::{self, Alternate, OpenDrain, PushPull};
21use crate::pac;
22use crate::rcc::{Clocks, Enable, RccBus, Reset};
23use crate::time::{Bps, U32Ext};
24
25#[cfg(any(
26    //feature = "stm32l451", // missing PAC support
27    // feature = "stm32l452", // missing PAC support
28    // feature = "stm32l462", // missing PAC support
29    // feature = "stm32l471", // missing PAC support
30    feature = "stm32l475",
31    feature = "stm32l476",
32    feature = "stm32l485",
33    feature = "stm32l486",
34    feature = "stm32l496",
35    feature = "stm32l4a6",
36    // feature = "stm32l4p5",
37    // feature = "stm32l4q5",
38    // feature = "stm32l4r5",
39    // feature = "stm32l4s5",
40    // feature = "stm32l4r7",
41    // feature = "stm32l4s7",
42    feature = "stm32l4r9",
43    feature = "stm32l4s9",
44))]
45use crate::dma::dma2;
46
47/// Interrupt event
48pub enum Event {
49    /// New data has been received
50    Rxne,
51    /// New data can be sent
52    Txe,
53    /// The line has gone idle
54    Idle,
55    /// Character match
56    CharacterMatch,
57    /// Receiver timeout
58    ReceiverTimeout,
59}
60
61/// Serial error
62#[non_exhaustive]
63#[derive(Debug)]
64pub enum Error {
65    /// Framing error
66    Framing,
67    /// Noise error
68    Noise,
69    /// RX buffer overrun
70    Overrun,
71    /// Parity check error
72    Parity,
73}
74
75/// USART parity settings
76pub enum Parity {
77    /// No parity
78    ParityNone,
79    /// Even parity
80    ParityEven,
81    /// Odd parity
82    ParityOdd,
83}
84
85/// USART stopbits settings
86pub enum StopBits {
87    /// 1 stop bit
88    STOP1,
89    /// 0.5 stop bits
90    STOP0P5,
91    /// 2 stop bits
92    STOP2,
93    // 1.5 stop bits
94    STOP1P5,
95}
96
97/// USART oversampling settings
98pub enum Oversampling {
99    /// Oversample 8 times (allows for faster data rates)
100    Over8,
101    /// Oversample 16 times (higher stability)
102    Over16,
103}
104
105/// USART Configuration structure
106pub struct Config {
107    baudrate: Bps,
108    parity: Parity,
109    stopbits: StopBits,
110    oversampling: Oversampling,
111    character_match: Option<u8>,
112    receiver_timeout: Option<u32>,
113    disable_overrun: bool,
114    onebit_sampling: bool,
115}
116
117impl Config {
118    /// Set the baudrate to a specific value
119    pub fn baudrate(mut self, baudrate: Bps) -> Self {
120        self.baudrate = baudrate;
121        self
122    }
123
124    /// Set parity to none
125    pub fn parity_none(mut self) -> Self {
126        self.parity = Parity::ParityNone;
127        self
128    }
129
130    /// Set parity to even
131    pub fn parity_even(mut self) -> Self {
132        self.parity = Parity::ParityEven;
133        self
134    }
135
136    /// Set parity to odd
137    pub fn parity_odd(mut self) -> Self {
138        self.parity = Parity::ParityOdd;
139        self
140    }
141
142    /// Set the number of stopbits
143    pub fn stopbits(mut self, stopbits: StopBits) -> Self {
144        self.stopbits = stopbits;
145        self
146    }
147
148    /// Set the oversampling size
149    pub fn oversampling(mut self, oversampling: Oversampling) -> Self {
150        self.oversampling = oversampling;
151        self
152    }
153
154    /// Set the character match character
155    pub fn character_match(mut self, character_match: u8) -> Self {
156        self.character_match = Some(character_match);
157        self
158    }
159
160    /// Set the receiver timeout, the value is the number of bit durations
161    ///
162    /// Note that it only takes 24 bits, using more than this will cause a panic.
163    pub fn receiver_timeout(mut self, receiver_timeout: u32) -> Self {
164        assert!(receiver_timeout < 1 << 24);
165        self.receiver_timeout = Some(receiver_timeout);
166        self
167    }
168
169    /// Disable overrun detection
170    pub fn with_overrun_disabled(mut self) -> Self {
171        self.disable_overrun = true;
172        self
173    }
174
175    /// Change to onebit sampling
176    pub fn with_onebit_sampling(mut self) -> Self {
177        self.onebit_sampling = true;
178        self
179    }
180}
181
182impl Default for Config {
183    fn default() -> Config {
184        let baudrate = 115_200_u32.bps();
185        Config {
186            baudrate,
187            parity: Parity::ParityNone,
188            stopbits: StopBits::STOP1,
189            oversampling: Oversampling::Over16,
190            character_match: None,
191            receiver_timeout: None,
192            disable_overrun: false,
193            onebit_sampling: false,
194        }
195    }
196}
197
198impl From<Bps> for Config {
199    fn from(baudrate: Bps) -> Config {
200        Config {
201            baudrate,
202            ..Default::default()
203        }
204    }
205}
206
207/// Serial abstraction
208pub struct Serial<USART, PINS> {
209    usart: USART,
210    pins: PINS,
211}
212
213/// Serial receiver
214pub struct Rx<USART> {
215    _usart: PhantomData<USART>,
216}
217
218/// Serial transmitter
219pub struct Tx<USART> {
220    _usart: PhantomData<USART>,
221}
222
223macro_rules! hal {
224    ($(
225        $(#[$meta:meta])*
226        $USARTX:ident: (
227            $usartX:ident,
228            $pclkX:ident,
229            tx: ($txdma:ident, $dmatxch:path, $dmatxsel:path),
230            rx: ($rxdma:ident, $dmarxch:path, $dmarxsel:path)
231        ),
232    )+) => {
233        $(
234            impl<PINS> Serial<pac::$USARTX, PINS> {
235                /// Configures the serial interface and creates the interface
236                /// struct.
237                ///
238                /// `Config` is a config struct that configures baud rate, stop bits and parity.
239                ///
240                /// `Clocks` passes information about the current frequencies of
241                /// the clocks.  The existence of the struct ensures that the
242                /// clock settings are fixed.
243                ///
244                /// The `serial` struct takes ownership over the `USARTX` device
245                /// registers and the specified `PINS`
246                ///
247                /// `MAPR` and `APBX` are register handles which are passed for
248                /// configuration. (`MAPR` is used to map the USART to the
249                /// corresponding pins. `APBX` is used to reset the USART.)
250                pub fn $usartX(
251                    usart: pac::$USARTX,
252                    pins: PINS,
253                    config: impl Into<Config>,
254                    clocks: Clocks,
255                    apb: &mut <pac::$USARTX as RccBus>::Bus,
256                ) -> Self
257                where
258                    PINS: Pins<pac::$USARTX>,
259                {
260                    let config = config.into();
261
262                    // enable or reset $USARTX
263                    <pac::$USARTX>::enable(apb);
264                    <pac::$USARTX>::reset(apb);
265
266                    // Reset other registers to disable advanced USART features
267                    usart.cr1.reset();
268                    usart.cr2.reset();
269                    usart.cr3.reset();
270
271                    // Configure baud rate
272                    match config.oversampling {
273                        Oversampling::Over8 => {
274                            let uartdiv = 2 * clocks.$pclkX().raw() / config.baudrate.0;
275                            assert!(uartdiv >= 16, "impossible baud rate");
276
277                            let lower = (uartdiv & 0xf) >> 1;
278                            let brr = (uartdiv & !0xf) | lower;
279
280                            usart.cr1.modify(|_, w| w.over8().set_bit());
281                            usart.brr.write(|w| unsafe { w.bits(brr) });
282                        }
283                        Oversampling::Over16 => {
284                            let brr = clocks.$pclkX().raw() / config.baudrate.0;
285                            assert!(brr >= 16, "impossible baud rate");
286
287                            usart.brr.write(|w| unsafe { w.bits(brr) });
288                        }
289                    }
290
291                    if let Some(val) = config.receiver_timeout {
292                        usart.rtor.modify(|_, w| w.rto().bits(val));
293                    }
294
295                    // enable DMA transfers
296                    usart.cr3.modify(|_, w| w.dmat().set_bit().dmar().set_bit());
297
298                    // Configure hardware flow control (CTS/RTS or RS485 Driver Enable)
299                    if PINS::FLOWCTL {
300                        usart.cr3.modify(|_, w| w.rtse().set_bit().ctse().set_bit());
301                    } else if PINS::DEM {
302                        usart.cr3.modify(|_, w| w.dem().set_bit());
303
304                        // Pre/post driver enable set conservative to the max time
305                        usart.cr1.modify(|_, w| w.deat().bits(0b1111).dedt().bits(0b1111));
306                    } else {
307                        usart.cr3.modify(|_, w| w.rtse().clear_bit().ctse().clear_bit());
308                    }
309
310                    // Enable One bit sampling method
311                    usart.cr3.modify(|_, w| {
312                        if config.onebit_sampling {
313                            w.onebit().set_bit();
314                        }
315
316                        if config.disable_overrun {
317                            w.ovrdis().set_bit();
318                        }
319
320                        // configure Half Duplex
321                        if PINS::HALF_DUPLEX {
322                            w.hdsel().set_bit();
323                        }
324
325                        w
326                    });
327
328                    // Configure parity and word length
329                    // Unlike most uart devices, the "word length" of this usart device refers to
330                    // the size of the data plus the parity bit. I.e. "word length"=8, parity=even
331                    // results in 7 bits of data. Therefore, in order to get 8 bits and one parity
332                    // bit, we need to set the "word" length to 9 when using parity bits.
333                    let (word_length, parity_control_enable, parity) = match config.parity {
334                        Parity::ParityNone => (false, false, false),
335                        Parity::ParityEven => (true, true, false),
336                        Parity::ParityOdd => (true, true, true),
337                    };
338                    usart.cr1.modify(|_r, w| {
339                        w
340                            .m0().bit(word_length)
341                            .ps().bit(parity)
342                            .pce().bit(parity_control_enable)
343                    });
344
345                    // Configure stop bits
346                    let stop_bits = match config.stopbits {
347                        StopBits::STOP1 => 0b00,
348                        StopBits::STOP0P5 => 0b01,
349                        StopBits::STOP2 => 0b10,
350                        StopBits::STOP1P5 => 0b11,
351                    };
352                    usart.cr2.modify(|_r, w| {
353                        w.stop().bits(stop_bits);
354
355                        // Setup character match (if requested)
356                        if let Some(c) = config.character_match {
357                            w.add().bits(c);
358                        }
359
360                        if config.receiver_timeout.is_some() {
361                            w.rtoen().set_bit();
362                        }
363
364                        w
365                    });
366
367
368                    // UE: enable USART
369                    // RE: enable receiver
370                    // TE: enable transceiver
371                    usart
372                        .cr1
373                        .modify(|_, w| w.ue().set_bit().re().set_bit().te().set_bit());
374
375                    Serial { usart, pins }
376                }
377
378                /// Starts listening for an interrupt event
379                pub fn listen(&mut self, event: Event) {
380                    match event {
381                        Event::Rxne => {
382                            self.usart.cr1.modify(|_, w| w.rxneie().set_bit())
383                        },
384                        Event::Txe => {
385                            self.usart.cr1.modify(|_, w| w.txeie().set_bit())
386                        },
387                        Event::Idle => {
388                            self.usart.cr1.modify(|_, w| w.idleie().set_bit())
389                        },
390                        Event::CharacterMatch => {
391                            self.usart.cr1.modify(|_, w| w.cmie().set_bit())
392                        },
393                        Event::ReceiverTimeout => {
394                            self.usart.cr1.modify(|_, w| w.rtoie().set_bit())
395                        },
396                    }
397                }
398
399                /// Check for, and return, any errors
400                ///
401                /// See [`Rx::check_for_error`].
402                pub fn check_for_error() -> Result<(), Error> {
403                    let mut rx: Rx<pac::$USARTX> = Rx {
404                        _usart: PhantomData,
405                    };
406                    rx.check_for_error()
407                }
408
409                /// Stops listening for an interrupt event
410                pub fn unlisten(&mut self, event: Event) {
411                    match event {
412                        Event::Rxne => {
413                            self.usart.cr1.modify(|_, w| w.rxneie().clear_bit())
414                        },
415                        Event::Txe => {
416                            self.usart.cr1.modify(|_, w| w.txeie().clear_bit())
417                        },
418                        Event::Idle => {
419                            self.usart.cr1.modify(|_, w| w.idleie().clear_bit())
420                        },
421                        Event::CharacterMatch => {
422                            self.usart.cr1.modify(|_, w| w.cmie().clear_bit())
423                        },
424                        Event::ReceiverTimeout => {
425                            self.usart.cr1.modify(|_, w| w.rtoie().clear_bit())
426                        },
427                    }
428                }
429
430                /// Splits the `Serial` abstraction into a transmitter and a receiver half
431                pub fn split(self) -> (Tx<pac::$USARTX>, Rx<pac::$USARTX>) {
432                    (
433                        Tx {
434                            _usart: PhantomData,
435                        },
436                        Rx {
437                            _usart: PhantomData,
438                        },
439                    )
440                }
441
442                /// Frees the USART peripheral
443                pub fn release(self) -> (pac::$USARTX, PINS) {
444                    (self.usart, self.pins)
445                }
446            }
447
448            impl<PINS> serial::Read<u8> for Serial<pac::$USARTX, PINS> {
449                type Error = Error;
450
451                fn read(&mut self) -> nb::Result<u8, Error> {
452                    let mut rx: Rx<pac::$USARTX> = Rx {
453                        _usart: PhantomData,
454                    };
455                    rx.read()
456                }
457            }
458
459            impl serial::Read<u8> for Rx<pac::$USARTX> {
460                type Error = Error;
461
462                fn read(&mut self) -> nb::Result<u8, Error> {
463                    self.check_for_error()?;
464
465                    // NOTE(unsafe) atomic read with no side effects
466                    let isr = unsafe { (*pac::$USARTX::ptr()).isr.read() };
467
468                    if isr.rxne().bit_is_set() {
469                        // NOTE(read_volatile) see `write_volatile` below
470                        return Ok(unsafe {
471                            ptr::read_volatile(&(*pac::$USARTX::ptr()).rdr as *const _ as *const _)
472                        });
473                    }
474
475                    Err(nb::Error::WouldBlock)
476                }
477            }
478
479            impl<PINS> serial::Write<u8> for Serial<pac::$USARTX, PINS> {
480                type Error = Error;
481
482                fn flush(&mut self) -> nb::Result<(), Error> {
483                    let mut tx: Tx<pac::$USARTX> = Tx {
484                        _usart: PhantomData,
485                    };
486                    tx.flush()
487                }
488
489                fn write(&mut self, byte: u8) -> nb::Result<(), Error> {
490                    let mut tx: Tx<pac::$USARTX> = Tx {
491                        _usart: PhantomData,
492                    };
493                    tx.write(byte)
494                }
495            }
496
497            impl serial::Write<u8> for Tx<pac::$USARTX> {
498                // NOTE(Void) See section "29.7 USART interrupts"; the only possible errors during
499                // transmission are: clear to send (which is disabled in this case) errors and
500                // framing errors (which only occur in SmartCard mode); neither of these apply to
501                // our hardware configuration
502                type Error = Error;
503
504                fn flush(&mut self) -> nb::Result<(), Error> {
505                    // NOTE(unsafe) atomic read with no side effects
506                    let isr = unsafe { (*pac::$USARTX::ptr()).isr.read() };
507
508                    if isr.tc().bit_is_set() {
509                        Ok(())
510                    } else {
511                        Err(nb::Error::WouldBlock)
512                    }
513                }
514
515                fn write(&mut self, byte: u8) -> nb::Result<(), Error> {
516                    // NOTE(unsafe) atomic read with no side effects
517                    let isr = unsafe { (*pac::$USARTX::ptr()).isr.read() };
518
519                    if isr.txe().bit_is_set() {
520                        // NOTE(unsafe) atomic write to stateless register
521                        // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
522                        unsafe {
523                            ptr::write_volatile(&(*pac::$USARTX::ptr()).tdr as *const _ as *mut _, byte)
524                        }
525                        Ok(())
526                    } else {
527                        Err(nb::Error::WouldBlock)
528                    }
529                }
530            }
531
532            impl embedded_hal::blocking::serial::write::Default<u8>
533                for Tx<pac::$USARTX> {}
534
535            pub type $rxdma = RxDma<Rx<pac::$USARTX>, $dmarxch>;
536            pub type $txdma = TxDma<Tx<pac::$USARTX>, $dmatxch>;
537
538            impl Receive for $rxdma {
539                type RxChannel = $dmarxch;
540                type TransmittedWord = u8;
541            }
542
543            impl Transmit for $txdma {
544                type TxChannel = $dmatxch;
545                type ReceivedWord = u8;
546            }
547
548            impl TransferPayload for $rxdma {
549                fn start(&mut self) {
550                    self.channel.start();
551                }
552                fn stop(&mut self) {
553                    self.channel.stop();
554                }
555            }
556
557            impl TransferPayload for $txdma {
558                fn start(&mut self) {
559                    self.channel.start();
560                }
561                fn stop(&mut self) {
562                    self.channel.stop();
563                }
564            }
565
566            impl Rx<pac::$USARTX> {
567                pub fn with_dma(self, channel: $dmarxch) -> $rxdma {
568                    RxDma {
569                        payload: self,
570                        channel,
571                    }
572                }
573
574                /// Check for, and return, any errors
575                ///
576                /// The `read` methods can only return one error at a time, but
577                /// there might actually be multiple errors. This method will
578                /// return and clear a currently active error. Once it returns
579                /// `Ok(())`, it should be possible to proceed with the next
580                /// `read` call unimpeded.
581                pub fn check_for_error(&mut self) -> Result<(), Error> {
582                    // NOTE(unsafe): Only used for atomic access.
583                    let isr = unsafe { (*pac::$USARTX::ptr()).isr.read() };
584                    let icr = unsafe { &(*pac::$USARTX::ptr()).icr };
585
586                    if isr.pe().bit_is_set() {
587                        icr.write(|w| w.pecf().clear());
588                        return Err(Error::Parity);
589                    }
590                    if isr.fe().bit_is_set() {
591                        icr.write(|w| w.fecf().clear());
592                        return Err(Error::Framing);
593                    }
594                    if isr.nf().bit_is_set() {
595                        icr.write(|w| w.ncf().clear());
596                        return Err(Error::Noise);
597                    }
598                    if isr.ore().bit_is_set() {
599                        icr.write(|w| w.orecf().clear());
600                        return Err(Error::Overrun);
601                    }
602
603                    Ok(())
604                }
605
606                /// Checks to see if the USART peripheral has detected an idle line and clears
607                /// the flag
608                pub fn is_idle(&mut self, clear: bool) -> bool {
609                    let isr = unsafe { &(*pac::$USARTX::ptr()).isr.read() };
610                    let icr = unsafe { &(*pac::$USARTX::ptr()).icr };
611
612                    if isr.idle().bit_is_set() {
613                        if clear {
614                            icr.write(|w| w.idlecf().set_bit() );
615                        }
616                        true
617                    } else {
618                        false
619                    }
620                }
621
622
623                /// Checks to see if the USART peripheral has detected an receiver timeout and
624                /// clears the flag
625                pub fn is_receiver_timeout(&mut self, clear: bool) -> bool {
626                    let isr = unsafe { &(*pac::$USARTX::ptr()).isr.read() };
627                    let icr = unsafe { &(*pac::$USARTX::ptr()).icr };
628
629                    if isr.rtof().bit_is_set() {
630                        if clear {
631                            icr.write(|w| w.rtocf().set_bit() );
632                        }
633                        true
634                    } else {
635                        false
636                    }
637                }
638
639                /// Checks to see if the USART peripheral has detected an character match and
640                /// clears the flag
641                pub fn check_character_match(&mut self, clear: bool) -> bool {
642                    let isr = unsafe { &(*pac::$USARTX::ptr()).isr.read() };
643                    let icr = unsafe { &(*pac::$USARTX::ptr()).icr };
644
645                    if isr.cmf().bit_is_set() {
646                        if clear {
647                            icr.write(|w| w.cmcf().set_bit() );
648                        }
649                        true
650                    } else {
651                        false
652                    }
653                }
654            }
655
656            impl crate::dma::CharacterMatch for Rx<pac::$USARTX> {
657                /// Checks to see if the USART peripheral has detected an character match and
658                /// clears the flag
659                fn check_character_match(&mut self, clear: bool) -> bool {
660                    self.check_character_match(clear)
661                }
662            }
663
664            impl crate::dma::ReceiverTimeout for Rx<pac::$USARTX> {
665                fn check_receiver_timeout(&mut self, clear: bool) -> bool {
666                    self.is_receiver_timeout(clear)
667                }
668            }
669
670            impl crate::dma::OperationError<(), Error> for Rx<pac::$USARTX>{
671                fn check_operation_error(&mut self) -> Result<(), Error> {
672                    self.check_for_error()
673                }
674            }
675
676            impl Tx<pac::$USARTX> {
677                pub fn with_dma(self, channel: $dmatxch) -> $txdma {
678                    TxDma {
679                        payload: self,
680                        channel,
681                    }
682                }
683            }
684
685            impl $rxdma {
686                pub fn split(mut self) -> (Rx<pac::$USARTX>, $dmarxch) {
687                    self.stop();
688                    let RxDma {payload, channel} = self;
689                    (
690                        payload,
691                        channel
692                    )
693                }
694            }
695
696            impl $txdma {
697                pub fn split(mut self) -> (Tx<pac::$USARTX>, $dmatxch) {
698                    self.stop();
699                    let TxDma {payload, channel} = self;
700                    (
701                        payload,
702                        channel,
703                    )
704                }
705            }
706
707            impl<B> crate::dma::CircReadDma<B, u8> for $rxdma
708            where
709                &'static mut B: StaticWriteBuffer<Word = u8>,
710                B: 'static,
711                Self: core::marker::Sized,
712            {
713                fn circ_read(mut self, mut buffer: &'static mut B,
714                ) -> CircBuffer<B, Self>
715                {
716                    let (ptr, len) = unsafe { buffer.static_write_buffer() };
717                    self.channel.set_peripheral_address(
718                        unsafe { &(*pac::$USARTX::ptr()).rdr as *const _ as u32 },
719                        false,
720                    );
721                    self.channel.set_memory_address(ptr as u32, true);
722                    self.channel.set_transfer_length(len as u16);
723
724                    // Tell DMA to request from serial
725                    self.channel.set_request_line($dmarxsel).unwrap();
726
727                    self.channel.ccr().modify(|_, w| {
728                        w
729                            // memory to memory mode disabled
730                            .mem2mem()
731                            .clear_bit()
732                            // medium channel priority level
733                            .pl()
734                            .medium()
735                            // 8-bit memory size
736                            .msize()
737                            .bits8()
738                            // 8-bit peripheral size
739                            .psize()
740                            .bits8()
741                            // circular mode disabled
742                            .circ()
743                            .set_bit()
744                            // write to memory
745                            .dir()
746                            .clear_bit()
747                    });
748
749                    // NOTE(compiler_fence) operations on `buffer` should not be reordered after
750                    // the next statement, which starts the DMA transfer
751                    atomic::compiler_fence(Ordering::Release);
752
753                    self.start();
754
755                    CircBuffer::new(buffer, self)
756                }
757            }
758
759            impl $rxdma {
760                /// Create a frame reader that can either react on the Character match interrupt or
761                /// Transfer Complete from the DMA.
762                pub fn frame_reader<BUFFER, const N: usize>(
763                    mut self,
764                    buffer: BUFFER,
765                ) -> FrameReader<BUFFER, Self, N>
766                    where
767                        BUFFER: Sized + StableDeref<Target = DMAFrame<N>> + DerefMut + 'static,
768                {
769                    let usart = unsafe{ &(*pac::$USARTX::ptr()) };
770
771                    // Setup DMA transfer
772                    let buf = &*buffer;
773                    self.channel.set_peripheral_address(&usart.rdr as *const _ as u32, false);
774                    self.channel.set_memory_address(unsafe { buf.buffer_address_for_dma() } as u32, true);
775                    self.channel.set_transfer_length(buf.max_len() as u16);
776
777                    // Tell DMA to request from serial
778                    self.channel.set_request_line($dmarxsel).unwrap();
779
780                    self.channel.ccr().modify(|_, w| {
781                        w
782                            // memory to memory mode disabled
783                            .mem2mem()
784                            .clear_bit()
785                            // medium channel priority level
786                            .pl()
787                            .medium()
788                            // 8-bit memory size
789                            .msize()
790                            .bits8()
791                            // 8-bit peripheral size
792                            .psize()
793                            .bits8()
794                            // Peripheral -> Mem
795                            .dir()
796                            .clear_bit()
797                    });
798
799                    // NOTE(compiler_fence) operations on `buffer` should not be reordered after
800                    // the next statement, which starts the DMA transfer
801                    atomic::compiler_fence(Ordering::Release);
802
803                    self.channel.start();
804
805                    FrameReader::new(buffer, self, usart.cr2.read().add().bits())
806                }
807            }
808
809            impl $txdma {
810                /// Creates a new DMA frame sender
811                pub fn frame_sender<BUFFER, const N: usize>(
812                    mut self,
813                ) -> FrameSender<BUFFER, Self, N>
814                    where
815                        BUFFER: Sized + StableDeref<Target = DMAFrame<N>> + DerefMut + 'static,
816                {
817                    let usart = unsafe{ &(*pac::$USARTX::ptr()) };
818
819                    // Setup DMA
820                    self.channel.set_peripheral_address(&usart.tdr as *const _ as u32, false);
821
822                    // Tell DMA to request from serial
823                    self.channel.set_request_line($dmatxsel).unwrap();
824
825                    self.channel.ccr().modify(|_, w| unsafe {
826                        w.mem2mem()
827                            .clear_bit()
828                            // 00: Low, 01: Medium, 10: High, 11: Very high
829                            .pl()
830                            .bits(0b01)
831                            // 00: 8-bits, 01: 16-bits, 10: 32-bits, 11: Reserved
832                            .msize()
833                            .bits(0b00)
834                            // 00: 8-bits, 01: 16-bits, 10: 32-bits, 11: Reserved
835                            .psize()
836                            .bits(0b00)
837                            // Mem -> Peripheral
838                            .dir()
839                            .set_bit()
840                    });
841
842                    FrameSender::new(self)
843                }
844            }
845        )+
846    }
847}
848
849hal! {
850    USART1: (usart1, pclk2, tx: (TxDma1, dma1::C4, DmaInput::Usart1Tx), rx: (RxDma1, dma1::C5, DmaInput::Usart1Rx)),
851    USART2: (usart2, pclk1, tx: (TxDma2, dma1::C7, DmaInput::Usart2Tx), rx: (RxDma2, dma1::C6, DmaInput::Usart2Rx)),
852}
853
854#[cfg(not(any(feature = "stm32l432", feature = "stm32l442")))]
855hal! {
856    USART3: (usart3, pclk1, tx: (TxDma3, dma1::C2, DmaInput::Usart3Tx), rx: (RxDma3, dma1::C3, DmaInput::Usart3Rx)),
857}
858
859#[cfg(any(
860    // feature = "stm32l451", // missing PAC support
861    // feature = "stm32l452", // missing PAC support
862    // feature = "stm32l462", // missing PAC support
863    // feature = "stm32l471", // missing PAC support
864    feature = "stm32l475",
865    feature = "stm32l476",
866    feature = "stm32l485",
867    feature = "stm32l486",
868    feature = "stm32l496",
869    feature = "stm32l4a6",
870    // feature = "stm32l4p5",
871    // feature = "stm32l4q5",
872    // feature = "stm32l4r5",
873    // feature = "stm32l4s5",
874    // feature = "stm32l4r7",
875    // feature = "stm32l4s7",
876    feature = "stm32l4r9",
877    feature = "stm32l4s9",
878))]
879hal! {
880    UART4: (uart4, pclk1, tx: (TxDma4, dma2::C3, DmaInput::Uart4Tx), rx: (RxDma4, dma2::C5, DmaInput::Uart4Rx)),
881}
882
883#[cfg(any(
884    // feature = "stm32l471", // missing PAC support
885    feature = "stm32l475",
886    feature = "stm32l476",
887    feature = "stm32l485",
888    feature = "stm32l486",
889    feature = "stm32l496",
890    feature = "stm32l4a6",
891    // feature = "stm32l4p5",
892    // feature = "stm32l4q5",
893    // feature = "stm32l4r5",
894    // feature = "stm32l4s5",
895    // feature = "stm32l4r7",
896    // feature = "stm32l4s7",
897    feature = "stm32l4r9",
898    feature = "stm32l4s9",
899))]
900hal! {
901    UART5: (uart5, pclk1, tx: (TxDma5, dma2::C1, DmaInput::Uart5Tx), rx: (RxDma5, dma2::C2, DmaInput::Uart5Rx)),
902}
903
904impl<USART, PINS> fmt::Write for Serial<USART, PINS>
905where
906    Serial<USART, PINS>: crate::hal::serial::Write<u8>,
907{
908    fn write_str(&mut self, s: &str) -> fmt::Result {
909        let _ = s
910            .as_bytes()
911            .iter()
912            .map(|c| nb::block!(self.write(*c)))
913            .last();
914        Ok(())
915    }
916}
917
918impl<USART> fmt::Write for Tx<USART>
919where
920    Tx<USART>: crate::hal::serial::Write<u8>,
921{
922    fn write_str(&mut self, s: &str) -> fmt::Result {
923        let _ = s
924            .as_bytes()
925            .iter()
926            .map(|c| nb::block!(self.write(*c)))
927            .last();
928        Ok(())
929    }
930}
931
932/// Marks pins as being as being TX pins for the given USART instance
933pub trait TxPin<Instance>: private::SealedTx {}
934
935/// Marks pins as being TX Half Duplex pins for the given USART instance
936pub trait TxHalfDuplexPin<Instance>: private::SealedTxHalfDuplex {}
937
938/// Marks pins as being as being RX pins for the given USART instance
939pub trait RxPin<Instance>: private::SealedRx {}
940
941/// Marks pins as being as being RTS pins for the given USART instance
942pub trait RtsDePin<Instance>: private::SealedRtsDe {}
943
944/// Marks pins as being as being CTS pins for the given USART instance
945pub trait CtsPin<Instance>: private::SealedCts {}
946
947macro_rules! impl_pin_traits {
948    (
949        $(
950            $instance:ident: {
951                $(
952                    $af:literal: {
953                        TX: $($tx:ident),*;
954                        RX: $($rx:ident),*;
955                        RTS_DE: $($rts_de:ident),*;
956                        CTS: $($cts:ident),*;
957                    }
958                )*
959            }
960        )*
961    ) => {
962        $(
963            $(
964                $(
965                    impl private::SealedTx for
966                        gpio::$tx<Alternate<PushPull, $af>> {}
967                    impl TxPin<pac::$instance> for
968                        gpio::$tx<Alternate<PushPull, $af>> {}
969                )*
970
971                $(
972                    impl private::SealedTxHalfDuplex for
973                        gpio::$tx<Alternate<OpenDrain, $af>> {}
974                    impl TxHalfDuplexPin<pac::$instance> for
975                        gpio::$tx<Alternate<OpenDrain, $af>> {}
976                )*
977
978                $(
979                    impl private::SealedRx for
980                        gpio::$rx<Alternate<PushPull, $af>> {}
981                    impl RxPin<pac::$instance> for
982                        gpio::$rx<Alternate<PushPull, $af>> {}
983                )*
984
985                $(
986                    impl private::SealedRtsDe for
987                        gpio::$rts_de<Alternate<PushPull, $af>> {}
988                    impl RtsDePin<pac::$instance> for
989                        gpio::$rts_de<Alternate<PushPull, $af>> {}
990                )*
991
992                $(
993                    impl private::SealedCts for
994                        gpio::$cts<Alternate<PushPull, $af>> {}
995                    impl CtsPin<pac::$instance> for
996                        gpio::$cts<Alternate<PushPull, $af>> {}
997                )*
998            )*
999        )*
1000    };
1001}
1002
1003impl_pin_traits! {
1004    USART1: {
1005        7: {
1006            TX: PA9, PB6;
1007            RX: PA10, PB7;
1008            RTS_DE: PA12, PB3;
1009            CTS: PA11, PB4;
1010        }
1011    }
1012    USART2: {
1013        7: {
1014            TX: PA2, PD5;
1015            RX: PA3, PD6;
1016            RTS_DE: PA1, PD4;
1017            CTS: PA0, PD3;
1018        }
1019        3: {
1020            TX: ;
1021            RX: PA15;
1022            RTS_DE: ;
1023            CTS: ;
1024        }
1025    }
1026    USART3: {
1027        7: {
1028            TX: PB10, PC4, PC10, PD8;
1029            RX: PB11, PC5, PC11, PD9;
1030            RTS_DE: PB1, PB14, PD2, PD12;
1031            CTS: PA6, PB13, PD11;
1032        }
1033    }
1034}
1035
1036#[cfg(any(
1037    // feature = "stm32l451",
1038    // feature = "stm32l452",
1039    // feature = "stm32l462",
1040    // feature = "stm32l471",
1041    feature = "stm32l475",
1042    feature = "stm32l476",
1043    feature = "stm32l485",
1044    feature = "stm32l486",
1045    feature = "stm32l496",
1046    feature = "stm32l4a6",
1047    // feature = "stm32l4p5",
1048    // feature = "stm32l4q5",
1049    // feature = "stm32l4r5",
1050    // feature = "stm32l4s5",
1051    // feature = "stm32l4r7",
1052    // feature = "stm32l4s7",
1053    feature = "stm32l4r9",
1054    feature = "stm32l4s9",
1055))]
1056impl_pin_traits! {
1057    UART4: {
1058        8: {
1059            TX: PA0, PC10;
1060            RX: PA1, PC11;
1061            RTS_DE: PA15;
1062            CTS: PB7;
1063        }
1064    }
1065}
1066
1067#[cfg(any(
1068    // feature = "stm32l471", ,, missing PAC support
1069    feature = "stm32l475",
1070    feature = "stm32l476",
1071    feature = "stm32l485",
1072    feature = "stm32l486",
1073    feature = "stm32l496",
1074    feature = "stm32l4a6",
1075    // feature = "stm32l4p5",
1076    // feature = "stm32l4q5",
1077    // feature = "stm32l4r5",
1078    // feature = "stm32l4s5",
1079    // feature = "stm32l4r7",
1080    // feature = "stm32l4s7",
1081    feature = "stm32l4r9",
1082    feature = "stm32l4s9",
1083))]
1084impl_pin_traits! {
1085    UART5: {
1086        8: {
1087            TX: PC12;
1088            RX: PD2;
1089            RTS_DE: PB4;
1090            CTS: PB5;
1091        }
1092    }
1093}
1094
1095/// Pins trait for detecting hardware flow control or RS485 mode.
1096pub trait Pins<USART> {
1097    const FLOWCTL: bool;
1098    const DEM: bool;
1099    const HALF_DUPLEX: bool;
1100}
1101
1102// No flow control, just Rx+Tx
1103impl<Instance, Tx, Rx> Pins<Instance> for (Tx, Rx)
1104where
1105    Tx: TxPin<Instance>,
1106    Rx: RxPin<Instance>,
1107{
1108    const FLOWCTL: bool = false;
1109    const DEM: bool = false;
1110    const HALF_DUPLEX: bool = false;
1111}
1112
1113// No flow control Half_duplex, just Tx
1114impl<Instance, Tx> Pins<Instance> for (Tx,)
1115where
1116    Tx: TxHalfDuplexPin<Instance>,
1117{
1118    const FLOWCTL: bool = false;
1119    const DEM: bool = false;
1120    const HALF_DUPLEX: bool = true;
1121}
1122
1123// Hardware flow control, Rx+Tx+Rts+Cts
1124impl<Instance, Tx, Rx, Rts, Cts> Pins<Instance> for (Tx, Rx, Rts, Cts)
1125where
1126    Tx: TxPin<Instance>,
1127    Rx: RxPin<Instance>,
1128    Rts: RtsDePin<Instance>,
1129    Cts: CtsPin<Instance>,
1130{
1131    const FLOWCTL: bool = true;
1132    const DEM: bool = false;
1133    const HALF_DUPLEX: bool = false;
1134}
1135
1136// DEM for RS485 mode
1137impl<Instance, Tx, Rx, De> Pins<Instance> for (Tx, Rx, De)
1138where
1139    Tx: TxPin<Instance>,
1140    Rx: RxPin<Instance>,
1141    De: RtsDePin<Instance>,
1142{
1143    const FLOWCTL: bool = false;
1144    const DEM: bool = true;
1145    const HALF_DUPLEX: bool = false;
1146}
1147
1148/// Contains supertraits used to restrict which traits users can implement
1149mod private {
1150    pub trait SealedTx {}
1151    pub trait SealedTxHalfDuplex {}
1152    pub trait SealedRx {}
1153    pub trait SealedRtsDe {}
1154    pub trait SealedCts {}
1155}