1use 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#[derive(Copy, Clone, Debug, Eq, PartialEq, thiserror::Error)]
31#[non_exhaustive]
32pub enum Error {
33 #[error("Framing error")]
35 Framing,
36 #[error("Noise error")]
38 Noise,
39 #[error("RX buffer overrun")]
41 Overrun,
42 #[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
113pub enum Event {
115 Rbne,
117 Tbe,
119 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#[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#[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
172pub struct Serial<USART, TXPIN, RXPIN> {
174 usart: USART,
175 pins: (TXPIN, RXPIN),
176}
177
178pub struct Rx<USART> {
180 usart: *const usart0::RegisterBlock,
181 _instance: PhantomData<USART>,
182}
183
184unsafe impl<USART> Send for Rx<USART> {}
185
186pub 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 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 usart
214 .ctl0()
215 .modify(|_, w| w.ten().enabled().ren().enabled().uen().enabled());
216
217 Self { usart, pins }
218 }
219
220 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 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 usart
252 .ctl0()
253 .modify(|_, w| w.ten().enabled().uen().enabled());
254
255 Self {
256 usart,
257 pins: (txpin, ()),
258 }
259 }
260
261 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 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 usart
287 .ctl0()
288 .modify(|_, w| w.ren().enabled().uen().enabled());
289
290 Self {
291 usart,
292 pins: ((), rxpin),
293 }
294 }
295
296 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 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 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 pub fn listen(&mut self) {
332 unsafe { &*self.usart }
333 .ctl0()
334 .modify(|_, w| w.rbneie().enabled());
335 }
336
337 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 pub fn listen(&mut self) {
348 unsafe { &*self.usart }
349 .ctl0()
350 .modify(|_, w| w.tbeie().enabled());
351 }
352
353 pub fn unlisten(&mut self) {
355 unsafe { &*self.usart }
356 .ctl0()
357 .modify(|_, w| w.tbeie().disabled());
358 }
359}
360
361impl<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
452impl<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 fn enable_configure(&self, config: Config, clocks: Clocks, bus: &mut Self::Bus) {
520 USART::enable(bus);
522 USART::reset(bus);
523
524 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 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 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 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 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 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 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 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 unsafe { &*self.payload.usart }
788 .intc()
789 .write(|w| w.tcc().clear());
790
791 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}