1use core::marker::PhantomData;
94use core::ops::Deref;
95use core::sync::atomic::{self, Ordering};
96use embedded_dma::{ReadBuffer, WriteBuffer};
97
98use crate::afio::{self, RInto, Rmp};
99#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))]
100use crate::dma::dma2;
101use crate::dma::{self, dma1, CircBuffer, RxDma, Transfer, TxDma};
102use crate::gpio::{Floating, PushPull, UpMode};
103use crate::pac::{self};
104use crate::rcc::{BusClock, Clocks, Enable, Rcc, Reset};
105use crate::time::{Bps, U32Ext};
106
107mod hal_02;
108mod hal_1;
109
110use crate::pacext::uart::{SrR, UartRB};
111
112pub trait SerialExt: Sized + Instance {
113 fn serial<Otype, PULL: UpMode>(
114 self,
115 pins: (
116 impl RInto<Self::Tx<Otype>, 0>,
117 impl RInto<Self::Rx<PULL>, 0>,
118 ),
119 config: impl Into<Config>,
120 rcc: &mut Rcc,
121 ) -> Serial<Self, Otype, PULL>;
122 fn tx<Otype>(
123 self,
124 tx_pin: impl RInto<Self::Tx<Otype>, 0>,
125 config: impl Into<Config>,
126 rcc: &mut Rcc,
127 ) -> Tx<Self>;
128 fn rx<PULL: UpMode>(
129 self,
130 rx_pin: impl RInto<Self::Rx<PULL>, 0>,
131 config: impl Into<Config>,
132 rcc: &mut Rcc,
133 ) -> Rx<Self>;
134}
135
136impl<USART: Instance> SerialExt for USART {
137 fn serial<Otype, PULL: UpMode>(
138 self,
139 pins: (
140 impl RInto<Self::Tx<Otype>, 0>,
141 impl RInto<Self::Rx<PULL>, 0>,
142 ),
143 config: impl Into<Config>,
144 rcc: &mut Rcc,
145 ) -> Serial<Self, Otype, PULL> {
146 Serial::new(self, pins, config, rcc)
147 }
148 fn tx<Otype>(
149 self,
150 tx_pin: impl RInto<Self::Tx<Otype>, 0>,
151 config: impl Into<Config>,
152 rcc: &mut Rcc,
153 ) -> Tx<Self> {
154 Serial::tx(self, tx_pin, config, rcc)
155 }
156 fn rx<PULL: UpMode>(
157 self,
158 rx_pin: impl RInto<Self::Rx<PULL>, 0>,
159 config: impl Into<Config>,
160 rcc: &mut Rcc,
161 ) -> Rx<Self> {
162 Serial::rx(self, rx_pin, config, rcc)
163 }
164}
165
166pub trait RBExt: UartRB {
167 fn set_stopbits(&self, bits: StopBits);
168}
169
170impl RBExt for pac::usart1::RegisterBlock {
171 fn set_stopbits(&self, bits: StopBits) {
172 use crate::pac::usart1::cr2::STOP;
173
174 self.cr2().write(|w| {
175 w.stop().variant(match bits {
176 StopBits::STOP0P5 => STOP::Stop0p5,
177 StopBits::STOP1 => STOP::Stop1,
178 StopBits::STOP1P5 => STOP::Stop1p5,
179 StopBits::STOP2 => STOP::Stop2,
180 })
181 });
182 }
183}
184
185#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))]
186impl RBExt for pac::uart4::RegisterBlock {
187 fn set_stopbits(&self, bits: StopBits) {
188 use crate::pac::uart4::cr2::STOP;
189
190 self.cr2().write(|w| {
193 w.stop().variant(match bits {
194 StopBits::STOP0P5 | StopBits::STOP1 => STOP::Stop1,
195 StopBits::STOP1P5 | StopBits::STOP2 => STOP::Stop2,
196 })
197 });
198 }
199}
200
201pub trait Instance:
202 crate::Sealed
203 + crate::Ptr<RB: RBExt>
204 + Deref<Target = Self::RB>
205 + Enable
206 + Reset
207 + BusClock
208 + afio::SerialAsync
209{
210}
211
212macro_rules! inst {
213 ($($USARTX:ty;)+) => {
214 $(
215 impl Instance for $USARTX { }
216 )+
217 };
218}
219
220inst! {
221 pac::USART1;
222 pac::USART2;
223 pac::USART3;
224}
225#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))]
226inst! {
227 pac::UART4;
228 pac::UART5;
229}
230
231#[derive(Debug)]
233#[non_exhaustive]
234pub enum Error {
235 Overrun,
237 FrameFormat,
240 Parity,
242 Noise,
244 Other,
246}
247
248pub enum WordLength {
249 Bits8,
252 Bits9,
255}
256
257pub enum Parity {
258 ParityNone,
259 ParityEven,
260 ParityOdd,
261}
262
263pub enum StopBits {
264 STOP1,
266 STOP0P5,
268 STOP2,
270 STOP1P5,
272}
273
274pub struct Config {
275 pub baudrate: Bps,
276 pub wordlength: WordLength,
277 pub parity: Parity,
278 pub stopbits: StopBits,
279}
280
281impl Config {
282 pub fn baudrate(mut self, baudrate: Bps) -> Self {
283 self.baudrate = baudrate;
284 self
285 }
286
287 pub fn wordlength(mut self, wordlength: WordLength) -> Self {
288 self.wordlength = wordlength;
289 self
290 }
291
292 pub fn wordlength_8bits(mut self) -> Self {
293 self.wordlength = WordLength::Bits8;
294 self
295 }
296
297 pub fn wordlength_9bits(mut self) -> Self {
298 self.wordlength = WordLength::Bits9;
299 self
300 }
301
302 pub fn parity(mut self, parity: Parity) -> Self {
303 self.parity = parity;
304 self
305 }
306
307 pub fn parity_none(mut self) -> Self {
308 self.parity = Parity::ParityNone;
309 self
310 }
311
312 pub fn parity_even(mut self) -> Self {
313 self.parity = Parity::ParityEven;
314 self
315 }
316
317 pub fn parity_odd(mut self) -> Self {
318 self.parity = Parity::ParityOdd;
319 self
320 }
321
322 pub fn stopbits(mut self, stopbits: StopBits) -> Self {
323 self.stopbits = stopbits;
324 self
325 }
326}
327
328impl Default for Config {
329 fn default() -> Config {
330 Config {
331 baudrate: 115_200_u32.bps(),
332 wordlength: WordLength::Bits8,
333 parity: Parity::ParityNone,
334 stopbits: StopBits::STOP1,
335 }
336 }
337}
338
339impl From<Bps> for Config {
340 fn from(baud: Bps) -> Self {
341 Config::default().baudrate(baud)
342 }
343}
344
345pub struct Serial<USART: Instance, Otype = PushPull, PULL = Floating> {
347 pub tx: Tx<USART>,
348 pub rx: Rx<USART>,
349 #[allow(clippy::type_complexity)]
350 pub token: ReleaseToken<USART, (Option<USART::Tx<Otype>>, Option<USART::Rx<PULL>>)>,
351}
352
353pub struct Tx<USART> {
355 _usart: PhantomData<USART>,
356}
357
358pub struct Rx<USART> {
360 _usart: PhantomData<USART>,
361}
362
363pub struct ReleaseToken<USART, PINS> {
365 usart: USART,
366 pins: PINS,
367}
368
369impl<USART: Instance, const R: u8> Rmp<USART, R> {
370 pub fn serial<Otype, PULL: UpMode>(
371 self,
372 pins: (
373 impl RInto<USART::Tx<Otype>, R>,
374 impl RInto<USART::Rx<PULL>, R>,
375 ),
376 config: impl Into<Config>,
377 rcc: &mut Rcc,
378 ) -> Serial<USART, Otype, PULL> {
379 Serial::_new(self.0, (Some(pins.0), Some(pins.1)), config, rcc)
380 }
381 pub fn tx<Otype>(
382 self,
383 tx_pin: impl RInto<USART::Tx<Otype>, R>,
384 config: impl Into<Config>,
385 rcc: &mut Rcc,
386 ) -> Tx<USART> {
387 Serial::_new(
388 self.0,
389 (Some(tx_pin), None::<USART::Rx<Floating>>),
390 config,
391 rcc,
392 )
393 .split()
394 .0
395 }
396 pub fn rx<PULL: UpMode>(
397 self,
398 rx_pin: impl RInto<USART::Rx<PULL>, R>,
399 config: impl Into<Config>,
400 rcc: &mut Rcc,
401 ) -> Rx<USART> {
402 Serial::_new(
403 self.0,
404 (None::<USART::Tx<Floating>>, Some(rx_pin)),
405 config,
406 rcc,
407 )
408 .split()
409 .1
410 }
411}
412
413impl<USART: Instance, Otype> Serial<USART, Otype, Floating> {
414 pub fn tx<const R: u8>(
415 usart: impl Into<Rmp<USART, R>>,
416 tx_pin: impl RInto<USART::Tx<Otype>, R>,
417 config: impl Into<Config>,
418 rcc: &mut Rcc,
419 ) -> Tx<USART> {
420 usart.into().tx(tx_pin, config, rcc)
421 }
422}
423
424impl<USART: Instance, PULL: UpMode> Serial<USART, PushPull, PULL> {
425 pub fn rx<const R: u8>(
426 usart: impl Into<Rmp<USART, R>>,
427 rx_pin: impl RInto<USART::Rx<PULL>, R>,
428 config: impl Into<Config>,
429 rcc: &mut Rcc,
430 ) -> Rx<USART> {
431 usart.into().rx(rx_pin, config, rcc)
432 }
433}
434
435impl<USART: Instance, Otype, PULL: UpMode> Serial<USART, Otype, PULL> {
436 pub fn new<const R: u8>(
452 usart: impl Into<Rmp<USART, R>>,
453 pins: (
454 impl RInto<USART::Tx<Otype>, R>,
455 impl RInto<USART::Rx<PULL>, R>,
456 ),
457 config: impl Into<Config>,
458 rcc: &mut Rcc,
459 ) -> Self {
460 usart.into().serial(pins, config, rcc)
461 }
462
463 fn _new<const R: u8>(
464 usart: USART,
465 pins: (
466 Option<impl RInto<USART::Tx<Otype>, R>>,
467 Option<impl RInto<USART::Rx<PULL>, R>>,
468 ),
469 config: impl Into<Config>,
470 rcc: &mut Rcc,
471 ) -> Self {
472 USART::enable(rcc);
474 USART::reset(rcc);
475
476 apply_config::<USART>(config.into(), &rcc.clocks);
477
478 let pins = (pins.0.map(RInto::rinto), pins.1.map(RInto::rinto));
479
480 usart.cr1().modify(|_r, w| {
484 w.ue().set_bit();
485 w.te().set_bit();
486 w.re().set_bit();
487 w
488 });
489
490 Serial {
491 tx: Tx {
492 _usart: PhantomData,
493 },
494 rx: Rx {
495 _usart: PhantomData,
496 },
497 token: ReleaseToken { usart, pins },
498 }
499 }
500}
501
502impl<USART: Instance, Otype, PULL> Serial<USART, Otype, PULL> {
503 pub fn reconfigure(
508 &mut self,
509 config: impl Into<Config>,
510 clocks: &Clocks,
511 ) -> nb::Result<(), Error> {
512 reconfigure(&mut self.tx, &mut self.rx, config, clocks)
513 }
514
515 #[allow(clippy::type_complexity)]
534 pub fn release(self) -> (USART, (Option<USART::Tx<Otype>>, Option<USART::Rx<PULL>>)) {
535 (self.token.usart, self.token.pins)
536 }
537
538 pub fn split(self) -> (Tx<USART>, Rx<USART>) {
548 (self.tx, self.rx)
549 }
550}
551
552fn apply_config<USART: Instance>(config: Config, clocks: &Clocks) {
553 let usart = unsafe { &*USART::ptr() };
554
555 let brr = USART::clock(clocks).raw() / config.baudrate.0;
557 assert!(brr >= 16, "impossible baud rate");
558 usart.brr().write(|w| unsafe { w.bits(brr as u16) });
559
560 usart.cr1().modify(|_r, w| {
562 w.m().bit(match config.wordlength {
563 WordLength::Bits8 => false,
564 WordLength::Bits9 => true,
565 });
566 use crate::pac::usart1::cr1::PS;
567 w.ps().variant(match config.parity {
568 Parity::ParityOdd => PS::Odd,
569 _ => PS::Even,
570 });
571 w.pce().bit(!matches!(config.parity, Parity::ParityNone));
572 w
573 });
574
575 usart.set_stopbits(config.stopbits);
577}
578
579pub fn reconfigure<USART: Instance>(
584 tx: &mut Tx<USART>,
585 #[allow(unused_variables)] rx: &mut Rx<USART>,
586 config: impl Into<Config>,
587 clocks: &Clocks,
588) -> nb::Result<(), Error> {
589 tx.flush()?;
594 apply_config::<USART>(config.into(), clocks);
595 Ok(())
596}
597
598impl<USART: Instance> Tx<USART> {
599 pub fn write_u16(&mut self, word: u16) -> nb::Result<(), Error> {
605 let usart = unsafe { &*USART::ptr() };
606
607 if usart.sr().read().txe().bit_is_set() {
608 usart.dr().write(|w| w.dr().set(word));
609 Ok(())
610 } else {
611 Err(nb::Error::WouldBlock)
612 }
613 }
614
615 pub fn write_u8(&mut self, word: u8) -> nb::Result<(), Error> {
616 self.write_u16(word as u16)
617 }
618
619 pub fn bwrite_all_u16(&mut self, buffer: &[u16]) -> Result<(), Error> {
620 for &w in buffer {
621 nb::block!(self.write_u16(w))?;
622 }
623 Ok(())
624 }
625
626 pub fn bwrite_all_u8(&mut self, buffer: &[u8]) -> Result<(), Error> {
627 for &w in buffer {
628 nb::block!(self.write_u8(w))?;
629 }
630 Ok(())
631 }
632
633 pub fn flush(&mut self) -> nb::Result<(), Error> {
634 let usart = unsafe { &*USART::ptr() };
635
636 if usart.sr().read().tc().bit_is_set() {
637 Ok(())
638 } else {
639 Err(nb::Error::WouldBlock)
640 }
641 }
642
643 pub fn bflush(&mut self) -> Result<(), Error> {
644 nb::block!(self.flush())
645 }
646
647 pub fn listen(&mut self) {
649 unsafe { (*USART::ptr()).cr1().modify(|_, w| w.txeie().set_bit()) };
650 }
651
652 pub fn unlisten(&mut self) {
654 unsafe { (*USART::ptr()).cr1().modify(|_, w| w.txeie().clear_bit()) };
655 }
656
657 pub fn is_tx_empty(&self) -> bool {
659 unsafe { (*USART::ptr()).sr().read().txe().bit_is_set() }
660 }
661
662 pub fn is_tx_complete(&self) -> bool {
663 unsafe { (*USART::ptr()).sr().read().tc().bit_is_set() }
664 }
665}
666
667impl<USART: Instance> core::fmt::Write for Tx<USART> {
668 fn write_str(&mut self, s: &str) -> core::fmt::Result {
669 s.bytes()
670 .try_for_each(|c| nb::block!(self.write_u8(c)))
671 .map_err(|_| core::fmt::Error)
672 }
673}
674
675impl<USART: Instance> Rx<USART> {
676 pub fn read_u16(&mut self) -> nb::Result<u16, Error> {
682 let usart = unsafe { &*USART::ptr() };
683 let sr = usart.sr().read();
684
685 let err = if sr.pe().bit_is_set() {
687 Some(Error::Parity)
688 } else if sr.fe().bit_is_set() {
689 Some(Error::FrameFormat)
690 } else if sr.nf().bit_is_set() {
691 Some(Error::Noise)
692 } else if sr.ore().bit_is_set() {
693 Some(Error::Overrun)
694 } else {
695 None
696 };
697
698 if let Some(err) = err {
699 let _ = usart.sr().read();
702 let _ = usart.dr().read();
703 Err(nb::Error::Other(err))
704 } else {
705 if sr.rxne().bit_is_set() {
707 Ok(usart.dr().read().dr().bits())
709 } else {
710 Err(nb::Error::WouldBlock)
711 }
712 }
713 }
714
715 pub fn read(&mut self) -> nb::Result<u8, Error> {
716 self.read_u16().map(|word16| word16 as u8)
717 }
718
719 pub fn listen(&mut self) {
721 unsafe { (*USART::ptr()).cr1().modify(|_, w| w.rxneie().set_bit()) };
722 }
723
724 pub fn unlisten(&mut self) {
726 unsafe { (*USART::ptr()).cr1().modify(|_, w| w.rxneie().clear_bit()) };
727 }
728
729 pub fn listen_idle(&mut self) {
731 unsafe { (*USART::ptr()).cr1().modify(|_, w| w.idleie().set_bit()) };
732 }
733
734 pub fn unlisten_idle(&mut self) {
736 unsafe { (*USART::ptr()).cr1().modify(|_, w| w.idleie().clear_bit()) };
737 }
738
739 pub fn is_idle(&self) -> bool {
741 unsafe { (*USART::ptr()).sr().read().idle().bit_is_set() }
742 }
743
744 pub fn is_rx_not_empty(&self) -> bool {
746 unsafe { (*USART::ptr()).sr().read().rxne().bit_is_set() }
747 }
748
749 pub fn clear_idle_interrupt(&self) {
751 unsafe {
752 let _ = (*USART::ptr()).sr().read();
753 let _ = (*USART::ptr()).dr().read();
754 }
755 }
756}
757
758pub enum Event {
760 Txe,
762 Rxne,
764 Idle,
766}
767
768impl<USART: Instance, Otype, PULL> Serial<USART, Otype, PULL> {
769 pub fn listen(&mut self, event: Event) {
773 match event {
774 Event::Rxne => self.rx.listen(),
775 Event::Txe => self.tx.listen(),
776 Event::Idle => self.rx.listen_idle(),
777 }
778 }
779
780 pub fn unlisten(&mut self, event: Event) {
784 match event {
785 Event::Rxne => self.rx.unlisten(),
786 Event::Txe => self.tx.unlisten(),
787 Event::Idle => self.rx.unlisten_idle(),
788 }
789 }
790
791 pub fn is_idle(&self) -> bool {
793 self.rx.is_idle()
794 }
795
796 pub fn is_tx_empty(&self) -> bool {
798 self.tx.is_tx_empty()
799 }
800
801 pub fn is_rx_not_empty(&self) -> bool {
803 self.rx.is_rx_not_empty()
804 }
805
806 pub fn clear_idle_interrupt(&self) {
808 self.rx.clear_idle_interrupt();
809 }
810}
811
812impl<USART: Instance, PINS> core::fmt::Write for Serial<USART, PINS> {
813 fn write_str(&mut self, s: &str) -> core::fmt::Result {
814 self.tx.write_str(s)
815 }
816}
817
818pub type Rx1 = Rx<pac::USART1>;
819pub type Tx1 = Tx<pac::USART1>;
820pub type Rx2 = Rx<pac::USART2>;
821pub type Tx2 = Tx<pac::USART2>;
822pub type Rx3 = Rx<pac::USART3>;
823pub type Tx3 = Tx<pac::USART3>;
824
825use crate::dma::{Receive, TransferPayload, Transmit};
826
827macro_rules! serialdma {
828 (
829 $USARTX:ty,
830 $rxdma:ident,
831 $txdma:ident,
832 rx: $dmarxch:ty,
833 tx: $dmatxch:ty
834 ) => {
835 pub type $rxdma = RxDma<Rx<$USARTX>, $dmarxch>;
836 pub type $txdma = TxDma<Tx<$USARTX>, $dmatxch>;
837
838 impl Receive for $rxdma {
839 type RxChannel = $dmarxch;
840 type TransmittedWord = u8;
841 }
842
843 impl Transmit for $txdma {
844 type TxChannel = $dmatxch;
845 type ReceivedWord = u8;
846 }
847
848 impl TransferPayload for $rxdma {
849 fn start(&mut self) {
850 self.channel.start();
851 }
852 fn stop(&mut self) {
853 self.channel.stop();
854 }
855 }
856
857 impl TransferPayload for $txdma {
858 fn start(&mut self) {
859 self.channel.start();
860 }
861 fn stop(&mut self) {
862 self.channel.stop();
863 }
864 }
865
866 impl Rx<$USARTX> {
867 pub fn with_dma(self, channel: $dmarxch) -> $rxdma {
868 unsafe {
869 (*<$USARTX>::ptr()).cr3().modify(|_, w| w.dmar().set_bit());
870 }
871 RxDma {
872 payload: self,
873 channel,
874 }
875 }
876 }
877
878 impl Tx<$USARTX> {
879 pub fn with_dma(self, channel: $dmatxch) -> $txdma {
880 unsafe {
881 (*<$USARTX>::ptr()).cr3().modify(|_, w| w.dmat().set_bit());
882 }
883 TxDma {
884 payload: self,
885 channel,
886 }
887 }
888 }
889
890 impl $rxdma {
891 pub fn release(mut self) -> (Rx<$USARTX>, $dmarxch) {
892 self.stop();
893 unsafe {
894 (*<$USARTX>::ptr())
895 .cr3()
896 .modify(|_, w| w.dmar().clear_bit());
897 }
898 let RxDma { payload, channel } = self;
899 (payload, channel)
900 }
901 }
902
903 impl $txdma {
904 pub fn release(mut self) -> (Tx<$USARTX>, $dmatxch) {
905 self.stop();
906 unsafe {
907 (*<$USARTX>::ptr())
908 .cr3()
909 .modify(|_, w| w.dmat().clear_bit());
910 }
911 let TxDma { payload, channel } = self;
912 (payload, channel)
913 }
914 }
915
916 impl<B> crate::dma::CircReadDma<B, u8> for $rxdma
917 where
918 &'static mut [B; 2]: WriteBuffer<Word = u8>,
919 B: 'static,
920 {
921 fn circ_read(mut self, mut buffer: &'static mut [B; 2]) -> CircBuffer<B, Self> {
922 let (ptr, len) = unsafe { buffer.write_buffer() };
925 self.channel.set_peripheral_address(
926 unsafe { (*<$USARTX>::ptr()).dr().as_ptr() as u32 },
927 false,
928 );
929 self.channel.set_memory_address(ptr as u32, true);
930 self.channel.set_transfer_length(len);
931
932 atomic::compiler_fence(Ordering::Release);
933
934 self.channel.ch().cr().modify(|_, w| {
935 w.mem2mem().clear_bit();
936 w.pl().medium();
937 w.msize().bits8();
938 w.psize().bits8();
939 w.circ().set_bit();
940 w.dir().clear_bit()
941 });
942
943 self.start();
944
945 CircBuffer::new(buffer, self)
946 }
947 }
948
949 impl<B> crate::dma::ReadDma<B, u8> for $rxdma
950 where
951 B: WriteBuffer<Word = u8>,
952 {
953 fn read(mut self, mut buffer: B) -> Transfer<dma::W, B, Self> {
954 let (ptr, len) = unsafe { buffer.write_buffer() };
957 self.channel.set_peripheral_address(
958 unsafe { (*<$USARTX>::ptr()).dr().as_ptr() as u32 },
959 false,
960 );
961 self.channel.set_memory_address(ptr as u32, true);
962 self.channel.set_transfer_length(len);
963
964 atomic::compiler_fence(Ordering::Release);
965 self.channel.ch().cr().modify(|_, w| {
966 w.mem2mem().clear_bit();
967 w.pl().medium();
968 w.msize().bits8();
969 w.psize().bits8();
970 w.circ().clear_bit();
971 w.dir().clear_bit()
972 });
973 self.start();
974
975 Transfer::w(buffer, self)
976 }
977 }
978
979 impl<B> crate::dma::WriteDma<B, u8> for $txdma
980 where
981 B: ReadBuffer<Word = u8>,
982 {
983 fn write(mut self, buffer: B) -> Transfer<dma::R, B, Self> {
984 let (ptr, len) = unsafe { buffer.read_buffer() };
987
988 self.channel.set_peripheral_address(
989 unsafe { (*<$USARTX>::ptr()).dr().as_ptr() as u32 },
990 false,
991 );
992
993 self.channel.set_memory_address(ptr as u32, true);
994 self.channel.set_transfer_length(len);
995
996 atomic::compiler_fence(Ordering::Release);
997
998 self.channel.ch().cr().modify(|_, w| {
999 w.mem2mem().clear_bit();
1000 w.pl().medium();
1001 w.msize().bits8();
1002 w.psize().bits8();
1003 w.circ().clear_bit();
1004 w.dir().set_bit()
1005 });
1006 self.start();
1007
1008 Transfer::r(buffer, self)
1009 }
1010 }
1011 };
1012}
1013
1014serialdma! {
1015 pac::USART1,
1016 RxDma1,
1017 TxDma1,
1018 rx: dma1::C5,
1019 tx: dma1::C4
1020}
1021serialdma! {
1022 pac::USART2,
1023 RxDma2,
1024 TxDma2,
1025 rx: dma1::C6,
1026 tx: dma1::C7
1027}
1028serialdma! {
1029 pac::USART3,
1030 RxDma3,
1031 TxDma3,
1032 rx: dma1::C3,
1033 tx: dma1::C2
1034}
1035#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))]
1036serialdma! {
1037 pac::UART4,
1038 RxDma4,
1039 TxDma4,
1040 rx: dma2::C3,
1041 tx: dma2::C5
1042}