gd32f1x0_hal/
serial.rs

1// Copyright 2021 The gd32f1x0-hal authors.
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5//! # Serial Communication (USART)
6//!
7//! This module contains the functions to utilize the USART (Universal
8//! synchronous asynchronous receiver transmitter).
9
10use crate::dma::{
11    self, CircBuffer, CircReadDma, Priority, R, ReadDma, Receive, RxDma, Transfer, TransferPayload,
12    Transmit, TxDma, W, Width, WriteDma,
13};
14use crate::gpio::gpioa::{PA2, PA3, PA9, PA10, PA14, PA15};
15use crate::gpio::gpiob::{PB6, PB7};
16use crate::gpio::{AF0, AF1, Alternate};
17use crate::pac::{self, Usart0, usart0, usart0::ctl1::Stb};
18use crate::rcu::{Clocks, Enable, GetBusFreq, Reset, sealed::RcuBus};
19use crate::time::{Bps, U32Ext};
20use core::convert::Infallible;
21use core::fmt;
22use core::hint::spin_loop;
23use core::marker::PhantomData;
24use core::ops::Deref;
25use core::sync::atomic::{self, Ordering};
26use embedded_dma::{ReadBuffer, WriteBuffer};
27use embedded_io::{ErrorKind, ErrorType, Read, ReadReady, Write, WriteReady};
28
29/// Serial error
30#[derive(Copy, Clone, Debug, Eq, PartialEq, thiserror::Error)]
31#[non_exhaustive]
32pub enum Error {
33    /// Framing error
34    #[error("Framing error")]
35    Framing,
36    /// Noise error
37    #[error("Noise error")]
38    Noise,
39    /// RX buffer overrun
40    #[error("RX buffer overrun")]
41    Overrun,
42    /// Parity check error
43    #[error("Parity check error")]
44    Parity,
45}
46
47impl From<Infallible> for Error {
48    fn from(e: Infallible) -> Self {
49        match e {}
50    }
51}
52
53impl embedded_io::Error for Error {
54    fn kind(&self) -> ErrorKind {
55        match self {
56            Self::Framing | Self::Noise | Self::Parity => ErrorKind::InvalidData,
57            Self::Overrun => ErrorKind::Other,
58        }
59    }
60}
61
62pub enum Parity {
63    ParityNone,
64    ParityEven,
65    ParityOdd,
66}
67
68pub type StopBits = Stb;
69
70pub struct Config {
71    pub baudrate: Bps,
72    pub parity: Parity,
73    pub stopbits: StopBits,
74}
75
76impl Config {
77    pub fn baudrate(mut self, baudrate: Bps) -> Self {
78        self.baudrate = baudrate;
79        self
80    }
81
82    pub fn parity_none(mut self) -> Self {
83        self.parity = Parity::ParityNone;
84        self
85    }
86
87    pub fn parity_even(mut self) -> Self {
88        self.parity = Parity::ParityEven;
89        self
90    }
91
92    pub fn parity_odd(mut self) -> Self {
93        self.parity = Parity::ParityOdd;
94        self
95    }
96
97    pub fn stopbits(mut self, stopbits: StopBits) -> Self {
98        self.stopbits = stopbits;
99        self
100    }
101}
102
103impl Default for Config {
104    fn default() -> Config {
105        Config {
106            baudrate: 115_200_u32.bps(),
107            parity: Parity::ParityNone,
108            stopbits: StopBits::Stop1,
109        }
110    }
111}
112
113/// Interrupt event
114pub enum Event {
115    /// New data has been received
116    Rbne,
117    /// New data can be sent
118    Tbe,
119    /// Idle line state detected
120    Idle,
121}
122
123pub trait TxPin<USART> {}
124pub trait RxPin<USART> {}
125
126impl TxPin<Usart0> for PA9<Alternate<AF1>> {}
127impl RxPin<Usart0> for PA10<Alternate<AF1>> {}
128impl TxPin<Usart0> for PB6<Alternate<AF0>> {}
129impl RxPin<Usart0> for PB7<Alternate<AF0>> {}
130
131// Two USARTs
132#[cfg(any(
133    feature = "gd32f130x6",
134    feature = "gd32f130x8",
135    feature = "gd32f150x6",
136    feature = "gd32f150x8",
137    feature = "gd32f170x6",
138    feature = "gd32f170x8",
139    feature = "gd32f190x6",
140    feature = "gd32f190x8",
141))]
142mod pins {
143    use super::*;
144    use crate::gpio::gpiob::PB0;
145    use crate::gpio::{AF4, gpioa::PA8};
146    use crate::pac::Usart1;
147
148    impl TxPin<Usart1> for PA2<Alternate<AF1>> {}
149    impl RxPin<Usart1> for PA3<Alternate<AF1>> {}
150    impl TxPin<Usart1> for PA8<Alternate<AF4>> {}
151    impl RxPin<Usart1> for PB0<Alternate<AF4>> {}
152    impl TxPin<Usart1> for PA14<Alternate<AF1>> {}
153    impl RxPin<Usart1> for PA15<Alternate<AF1>> {}
154}
155
156// Only one USART
157#[cfg(any(
158    feature = "gd32f130x4",
159    feature = "gd32f150x4",
160    feature = "gd32f170x4",
161    feature = "gd32f190x4"
162))]
163mod pins {
164    use super::*;
165
166    impl TxPin<Usart0> for PA2<Alternate<AF1>> {}
167    impl RxPin<Usart0> for PA3<Alternate<AF1>> {}
168    impl TxPin<Usart0> for PA14<Alternate<AF1>> {}
169    impl RxPin<Usart0> for PA15<Alternate<AF1>> {}
170}
171
172/// Serial abstraction
173pub struct Serial<USART, TXPIN, RXPIN> {
174    usart: USART,
175    pins: (TXPIN, RXPIN),
176}
177
178/// Serial receiver
179pub struct Rx<USART> {
180    usart: *const usart0::RegisterBlock,
181    _instance: PhantomData<USART>,
182}
183
184unsafe impl<USART> Send for Rx<USART> {}
185
186/// Serial transmitter
187pub struct Tx<USART> {
188    usart: *const usart0::RegisterBlock,
189    _instance: PhantomData<USART>,
190}
191
192unsafe impl<USART> Send for Tx<USART> {}
193
194impl<
195    USART: RcuBus + Enable + Reset + Deref<Target = usart0::RegisterBlock>,
196    TXPIN: TxPin<USART>,
197    RXPIN: RxPin<USART>,
198> Serial<USART, TXPIN, RXPIN>
199where
200    USART::Bus: GetBusFreq,
201{
202    /// Configures the USART and creates a new Serial instance.
203    pub fn usart(
204        usart: USART,
205        pins: (TXPIN, RXPIN),
206        config: Config,
207        clocks: Clocks,
208        bus: &mut USART::Bus,
209    ) -> Self {
210        usart.enable_configure(config, clocks, bus);
211
212        // Enable transmitter, receiver and the USART as a whole.
213        usart
214            .ctl0()
215            .modify(|_, w| w.ten().enabled().ren().enabled().uen().enabled());
216
217        Self { usart, pins }
218    }
219
220    /// Separates the serial struct into separate channel objects for sending (Tx) and receiving (Rx).
221    pub fn split(self) -> (Tx<USART>, Rx<USART>) {
222        (
223            Tx {
224                usart: &*self.usart,
225                _instance: PhantomData,
226            },
227            Rx {
228                usart: &*self.usart,
229                _instance: PhantomData,
230            },
231        )
232    }
233}
234
235impl<USART: RcuBus + Enable + Reset + Deref<Target = usart0::RegisterBlock>, TXPIN: TxPin<USART>>
236    Serial<USART, TXPIN, ()>
237where
238    USART::Bus: GetBusFreq,
239{
240    /// Configures the USART and creates a new TX-only Serial instance.
241    pub fn usart_tx(
242        usart: USART,
243        txpin: TXPIN,
244        config: Config,
245        clocks: Clocks,
246        bus: &mut USART::Bus,
247    ) -> Self {
248        usart.enable_configure(config, clocks, bus);
249
250        // Enable transmitter and the USART as a whole.
251        usart
252            .ctl0()
253            .modify(|_, w| w.ten().enabled().uen().enabled());
254
255        Self {
256            usart,
257            pins: (txpin, ()),
258        }
259    }
260
261    /// Erase the pin.
262    pub fn downgrade_tx(self) -> Tx<USART> {
263        Tx {
264            usart: &*self.usart,
265            _instance: PhantomData,
266        }
267    }
268}
269
270impl<USART: RcuBus + Enable + Reset + Deref<Target = usart0::RegisterBlock>, RXPIN: RxPin<USART>>
271    Serial<USART, (), RXPIN>
272where
273    USART::Bus: GetBusFreq,
274{
275    /// Configures the USART and creates a new RX-only Serial instance.
276    pub fn usart_rx(
277        usart: USART,
278        rxpin: RXPIN,
279        config: Config,
280        clocks: Clocks,
281        bus: &mut USART::Bus,
282    ) -> Self {
283        usart.enable_configure(config, clocks, bus);
284
285        // Enable receiver and the USART as a whole.
286        usart
287            .ctl0()
288            .modify(|_, w| w.ren().enabled().uen().enabled());
289
290        Self {
291            usart,
292            pins: ((), rxpin),
293        }
294    }
295
296    /// Erase the pin.
297    pub fn downgrade_rx(self) -> Rx<USART> {
298        Rx {
299            usart: &*self.usart,
300            _instance: PhantomData,
301        }
302    }
303}
304
305impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN, RXPIN> Serial<USART, TXPIN, RXPIN> {
306    pub fn release(self) -> (USART, (TXPIN, RXPIN)) {
307        (self.usart, self.pins)
308    }
309
310    /// Enable an interrupt event.
311    pub fn listen(&mut self, event: Event) {
312        match event {
313            Event::Rbne => self.usart.ctl0().modify(|_, w| w.rbneie().enabled()),
314            Event::Tbe => self.usart.ctl0().modify(|_, w| w.tbeie().enabled()),
315            Event::Idle => self.usart.ctl0().modify(|_, w| w.idleie().enabled()),
316        }
317    }
318
319    /// Disable an interrupt event.
320    pub fn unlisten(&mut self, event: Event) {
321        match event {
322            Event::Rbne => self.usart.ctl0().modify(|_, w| w.rbneie().disabled()),
323            Event::Tbe => self.usart.ctl0().modify(|_, w| w.tbeie().disabled()),
324            Event::Idle => self.usart.ctl0().modify(|_, w| w.idleie().disabled()),
325        }
326    }
327}
328
329impl<USART: Deref<Target = usart0::RegisterBlock>> Rx<USART> {
330    /// Enable the RBNE interrupt.
331    pub fn listen(&mut self) {
332        unsafe { &*self.usart }
333            .ctl0()
334            .modify(|_, w| w.rbneie().enabled());
335    }
336
337    /// Disable the RBNE interrupt.
338    pub fn unlisten(&mut self) {
339        unsafe { &*self.usart }
340            .ctl0()
341            .modify(|_, w| w.rbneie().disabled());
342    }
343}
344
345impl<USART: Deref<Target = usart0::RegisterBlock>> Tx<USART> {
346    /// Enable the TBE interrupt.
347    pub fn listen(&mut self) {
348        unsafe { &*self.usart }
349            .ctl0()
350            .modify(|_, w| w.tbeie().enabled());
351    }
352
353    /// Disable the TBE interrupt.
354    pub fn unlisten(&mut self) {
355        unsafe { &*self.usart }
356            .ctl0()
357            .modify(|_, w| w.tbeie().disabled());
358    }
359}
360
361// Implement writing traits if the USART has a TX pin assigned.
362impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN: TxPin<USART>, RXPIN> Write
363    for Serial<USART, TXPIN, RXPIN>
364{
365    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
366        self.usart.write_buffer(buf)
367    }
368
369    fn flush(&mut self) -> Result<(), Self::Error> {
370        nb::block!(self.usart.flush())?;
371        Ok(())
372    }
373}
374
375impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN: TxPin<USART>, RXPIN> WriteReady
376    for Serial<USART, TXPIN, RXPIN>
377{
378    fn write_ready(&mut self) -> Result<bool, Self::Error> {
379        Ok(self.usart.write_ready())
380    }
381}
382
383#[cfg(feature = "embedded-hal-02")]
384impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN: TxPin<USART>, RXPIN>
385    embedded_hal_02::serial::Write<u8> for Serial<USART, TXPIN, RXPIN>
386{
387    type Error = Infallible;
388
389    fn flush(&mut self) -> nb::Result<(), Self::Error> {
390        self.usart.flush()
391    }
392
393    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
394        self.usart.write(byte)
395    }
396}
397
398impl<USART> ErrorType for Tx<USART> {
399    type Error = Error;
400}
401
402impl<USART: Deref<Target = usart0::RegisterBlock>> Write for Tx<USART> {
403    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
404        unsafe { &*self.usart }.write_buffer(buf)
405    }
406
407    fn flush(&mut self) -> Result<(), Self::Error> {
408        nb::block!(unsafe { &*self.usart }.flush())?;
409        Ok(())
410    }
411}
412
413impl<USART: Deref<Target = usart0::RegisterBlock>> WriteReady for Tx<USART> {
414    fn write_ready(&mut self) -> Result<bool, Self::Error> {
415        Ok(unsafe { &*self.usart }.write_ready())
416    }
417}
418
419#[cfg(feature = "embedded-hal-02")]
420impl<USART: Deref<Target = usart0::RegisterBlock>> embedded_hal_02::serial::Write<u8>
421    for Tx<USART>
422{
423    type Error = Infallible;
424
425    fn flush(&mut self) -> nb::Result<(), Self::Error> {
426        unsafe { &*self.usart }.flush()
427    }
428
429    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
430        unsafe { &*self.usart }.write(byte)
431    }
432}
433
434impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN: TxPin<USART>, RXPIN> fmt::Write
435    for Serial<USART, TXPIN, RXPIN>
436{
437    fn write_str(&mut self, s: &str) -> fmt::Result {
438        self.write_all(s.as_bytes()).map_err(|_| core::fmt::Error)
439    }
440}
441
442impl<USART: Deref<Target = usart0::RegisterBlock>> fmt::Write for Tx<USART> {
443    fn write_str(&mut self, s: &str) -> fmt::Result {
444        self.write_all(s.as_bytes()).map_err(|_| core::fmt::Error)
445    }
446}
447
448impl<USART, TXPIN, RXPIN> ErrorType for Serial<USART, TXPIN, RXPIN> {
449    type Error = Error;
450}
451
452// Implement reading traits if the USART has an RX pin assigned.
453impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN, RXPIN: RxPin<USART>> Read
454    for Serial<USART, TXPIN, RXPIN>
455{
456    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
457        self.usart.read_buffer(buf)
458    }
459}
460
461impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN, RXPIN: RxPin<USART>> ReadReady
462    for Serial<USART, TXPIN, RXPIN>
463{
464    fn read_ready(&mut self) -> Result<bool, Self::Error> {
465        Ok(self.usart.read_ready())
466    }
467}
468
469impl<USART> ErrorType for Rx<USART> {
470    type Error = Error;
471}
472
473impl<USART: Deref<Target = usart0::RegisterBlock>> Read for Rx<USART> {
474    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
475        unsafe { &*self.usart }.read_buffer(buf)
476    }
477}
478
479impl<USART: Deref<Target = usart0::RegisterBlock>> ReadReady for Rx<USART> {
480    fn read_ready(&mut self) -> Result<bool, Self::Error> {
481        Ok(unsafe { &*self.usart }.read_ready())
482    }
483}
484
485#[cfg(feature = "embedded-hal-02")]
486impl<USART: Deref<Target = usart0::RegisterBlock>, TXPIN, RXPIN: RxPin<USART>>
487    embedded_hal_02::serial::Read<u8> for Serial<USART, TXPIN, RXPIN>
488{
489    type Error = Error;
490
491    fn read(&mut self) -> nb::Result<u8, Error> {
492        self.usart.read()
493    }
494}
495
496#[cfg(feature = "embedded-hal-02")]
497impl<USART: Deref<Target = usart0::RegisterBlock>> embedded_hal_02::serial::Read<u8> for Rx<USART> {
498    type Error = Error;
499
500    fn read(&mut self) -> nb::Result<u8, Error> {
501        unsafe { &*self.usart }.read()
502    }
503}
504
505trait UsartConfigExt {
506    type Bus;
507
508    fn enable_configure(&self, config: Config, clocks: Clocks, bus: &mut Self::Bus);
509}
510
511impl<USART: RcuBus + Enable + Reset + Deref<Target = usart0::RegisterBlock>> UsartConfigExt
512    for USART
513where
514    USART::Bus: GetBusFreq,
515{
516    type Bus = USART::Bus;
517
518    /// Enable, reset and configure the USART.
519    fn enable_configure(&self, config: Config, clocks: Clocks, bus: &mut Self::Bus) {
520        // Enable clock for USART, and reset it.
521        USART::enable(bus);
522        USART::reset(bus);
523
524        // Configure baud rate.
525        let baud_rate_ratio = <USART as RcuBus>::Bus::get_frequency(&clocks).0 / config.baudrate.0;
526        assert!((16..=0xFFFF).contains(&baud_rate_ratio));
527        self.baud().write(|w| unsafe { w.bits(baud_rate_ratio) });
528
529        // Configure parity. Note that the parity bit counts towards the word length, so we have to
530        // increase it to 9 bits if parity is enabled so as to still get 8 data bits.
531        match config.parity {
532            Parity::ParityNone => {
533                self.ctl0().modify(|_, w| w.pcen().disabled().wl().bit8());
534            }
535            Parity::ParityEven => {
536                self.ctl0()
537                    .modify(|_, w| w.pcen().enabled().wl().bit9().pm().even());
538            }
539            Parity::ParityOdd => {
540                self.ctl0()
541                    .modify(|_, w| w.pcen().enabled().wl().bit9().pm().odd());
542            }
543        }
544
545        // Configure stop bits.
546        self.ctl1().modify(|_, w| w.stb().variant(config.stopbits));
547    }
548}
549
550trait UsartReadWrite {
551    fn read(&mut self) -> nb::Result<u8, Error>;
552    fn read_ready(&self) -> bool;
553    fn flush(&mut self) -> nb::Result<(), Infallible>;
554    fn write(&mut self, byte: u8) -> nb::Result<(), Infallible>;
555    fn write_ready(&self) -> bool;
556
557    /// Reads into the given buffer, blocking until at least one byte is available.
558    fn read_buffer(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
559        let mut bytes_read = 0;
560        while bytes_read < buf.len() {
561            match self.read() {
562                Ok(b) => {
563                    buf[bytes_read] = b;
564                    bytes_read += 1;
565                }
566                Err(nb::Error::WouldBlock) => {
567                    if bytes_read > 0 {
568                        break;
569                    }
570                    spin_loop();
571                }
572                Err(nb::Error::Other(e)) => {
573                    return Err(e);
574                }
575            }
576        }
577        Ok(bytes_read)
578    }
579
580    /// Writes at least one byte from the given buffer, blocking if necessary.
581    fn write_buffer(&mut self, buf: &[u8]) -> Result<usize, Error> {
582        let mut bytes_written = 0;
583        while bytes_written < buf.len() {
584            match self.write(buf[bytes_written]) {
585                Ok(()) => {
586                    bytes_written += 1;
587                }
588                Err(nb::Error::WouldBlock) => {
589                    if bytes_written > 0 {
590                        break;
591                    }
592                    spin_loop();
593                }
594                Err(nb::Error::Other(_)) => {
595                    unreachable!()
596                }
597            }
598        }
599        Ok(bytes_written)
600    }
601}
602
603impl<USART: Deref<Target = usart0::RegisterBlock>> UsartReadWrite for USART {
604    fn read(&mut self) -> nb::Result<u8, Error> {
605        let status = self.stat().read();
606
607        if status.perr().bit_is_set() {
608            self.intc().write(|w| w.pec().clear());
609            Err(nb::Error::Other(Error::Parity))
610        } else if status.ferr().bit_is_set() {
611            self.intc().write(|w| w.fec().clear());
612            Err(nb::Error::Other(Error::Framing))
613        } else if status.nerr().bit_is_set() {
614            self.intc().write(|w| w.nec().clear());
615            Err(nb::Error::Other(Error::Noise))
616        } else if status.orerr().bit_is_set() {
617            self.intc().write(|w| w.orec().clear());
618            // Discard the previous received byte.
619            self.cmd().write(|w| w.rxfcmd().discard());
620            Err(nb::Error::Other(Error::Overrun))
621        } else if status.rbne().bit_is_set() {
622            Ok(self.rdata().read().rdata().bits() as u8)
623        } else {
624            Err(nb::Error::WouldBlock)
625        }
626    }
627
628    fn read_ready(&self) -> bool {
629        self.stat().read().rbne().bit_is_set()
630    }
631
632    fn flush(&mut self) -> nb::Result<(), Infallible> {
633        let status = self.stat().read();
634        if status.tc().bit_is_set() {
635            Ok(())
636        } else {
637            Err(nb::Error::WouldBlock)
638        }
639    }
640
641    fn write(&mut self, byte: u8) -> nb::Result<(), Infallible> {
642        let status = self.stat().read();
643        if status.tbe().bit_is_set() {
644            self.tdata()
645                .write(|w| unsafe { w.tdata().bits(byte.into()) });
646            Ok(())
647        } else {
648            Err(nb::Error::WouldBlock)
649        }
650    }
651
652    fn write_ready(&self) -> bool {
653        self.stat().read().tbe().bit_is_set()
654    }
655}
656
657macro_rules! serialdma {
658    ($(
659        $USARTX:ty: (
660            $RxDmaX:ident,
661            $TxDmaX:ident,
662            $dmarxch:ty,
663            $dmatxch:ty,
664        ),
665    )+) => {
666        $(
667            pub type $RxDmaX = RxDma<Rx<$USARTX>, $dmarxch>;
668            pub type $TxDmaX = TxDma<Tx<$USARTX>, $dmatxch>;
669
670            impl Receive for $RxDmaX {
671                type RxChannel = $dmarxch;
672                type TransmittedWord = u8;
673            }
674
675            impl Transmit for $TxDmaX {
676                type TxChannel = $dmatxch;
677                type ReceivedWord = u8;
678            }
679
680            impl TransferPayload for $RxDmaX {
681                fn start(&mut self) {
682                    self.channel.start();
683                }
684
685                fn stop(&mut self) {
686                    self.channel.stop();
687                }
688            }
689
690            impl TransferPayload for $TxDmaX {
691                fn start(&mut self) {
692                    self.channel.start();
693                }
694
695                fn stop(&mut self) {
696                    self.channel.stop();
697                }
698            }
699
700            impl Rx<$USARTX> {
701                pub fn with_dma(self, channel: $dmarxch) -> $RxDmaX {
702                    RxDma {
703                        payload: self,
704                        channel,
705                    }
706                }
707            }
708
709            impl Tx<$USARTX> {
710                pub fn with_dma(self, channel: $dmatxch) -> $TxDmaX {
711                    TxDma {
712                        payload: self,
713                        channel,
714                    }
715                }
716            }
717
718            impl $RxDmaX {
719                pub fn split(mut self) -> (Rx<$USARTX>, $dmarxch) {
720                    self.stop();
721                    let RxDma { payload, channel } = self;
722                    (payload, channel)
723                }
724            }
725
726            impl $TxDmaX {
727                pub fn split(mut self) -> (Tx<$USARTX>, $dmatxch) {
728                    self.stop();
729                    let TxDma { payload, channel } = self;
730                    (payload, channel)
731                }
732            }
733
734            impl<B> CircReadDma<B, u8> for $RxDmaX
735            where
736                &'static mut [B; 2]: WriteBuffer<Word = u8>,
737                B: 'static,
738            {
739                fn circ_read(mut self, mut buffer: &'static mut [B; 2]) -> CircBuffer<B, Self> {
740                    // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
741                    // until the end of the transfer.
742                    let (ptr, len) = unsafe { buffer.write_buffer() };
743                    self.channel
744                        .set_peripheral_address(unsafe { &(*<$USARTX>::ptr()).rdata() as *const _ as u32 }, false);
745                    self.channel.set_memory_address(ptr as u32, true);
746                    self.channel.set_transfer_length(len);
747
748                    atomic::compiler_fence(Ordering::Release);
749
750                    self.channel
751                        .configure_from_peripheral(Priority::Medium, Width::Bits8, Width::Bits8, true);
752
753                    self.start();
754
755                    CircBuffer::new(buffer, self)
756                }
757            }
758
759            impl<B> ReadDma<B, u8> for $RxDmaX
760            where
761                B: WriteBuffer<Word = u8>,
762            {
763                fn read(mut self, mut buffer: B) -> Transfer<W, B, Self> {
764                    // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
765                    // until the end of the transfer.
766                    let (ptr, len) = unsafe { buffer.write_buffer() };
767                    self.channel
768                        .set_peripheral_address(unsafe { &(*<$USARTX>::ptr()).rdata() as *const _ as u32 }, false);
769                    self.channel.set_memory_address(ptr as u32, true);
770                    self.channel.set_transfer_length(len);
771
772                    atomic::compiler_fence(Ordering::Release);
773                    self.channel
774                        .configure_from_peripheral(Priority::Medium, Width::Bits8, Width::Bits8, false);
775                    self.start();
776
777                    Transfer::w(buffer, self)
778                }
779            }
780
781            impl<B> WriteDma<B, u8> for $TxDmaX
782            where
783                B: ReadBuffer<Word = u8>,
784            {
785                fn write(mut self, buffer: B) -> Transfer<R, B, Self> {
786                    // Clear transmission complete bit.
787                    unsafe { &*self.payload.usart }
788                        .intc()
789                        .write(|w| w.tcc().clear());
790
791                    // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
792                    // until the end of the transfer.
793                    let (ptr, len) = unsafe { buffer.read_buffer() };
794
795                    self.channel
796                        .set_peripheral_address(unsafe { &(*<$USARTX>::ptr()).tdata() as *const _ as u32 }, false);
797
798                    self.channel.set_memory_address(ptr as u32, true);
799                    self.channel.set_transfer_length(len);
800
801                    atomic::compiler_fence(Ordering::Release);
802
803                    self.channel
804                        .configure_to_peripheral(Priority::Medium, Width::Bits8, Width::Bits8, false);
805                    self.start();
806
807                    Transfer::r(buffer, self)
808                }
809            }
810        )+
811    }
812}
813
814serialdma! {
815    pac::Usart0: (
816        RxDma0,
817        TxDma0,
818        dma::C2,
819        dma::C1,
820    ),
821}
822
823#[cfg(any(
824    feature = "gd32f130x6",
825    feature = "gd32f130x8",
826    feature = "gd32f150x6",
827    feature = "gd32f150x8",
828    feature = "gd32f170x6",
829    feature = "gd32f170x8",
830    feature = "gd32f190x6",
831    feature = "gd32f190x8",
832))]
833serialdma! {
834    pac::Usart1: (
835        RxDma1,
836        TxDma1,
837        dma::C4,
838        dma::C3,
839    ),
840}