1#![macro_use]
3#![warn(missing_docs)]
4
5use core::future::poll_fn;
10use core::marker::PhantomData;
11use core::sync::atomic::{compiler_fence, AtomicU8, Ordering};
12use core::task::Poll;
13
14use embassy_embedded_hal::SetConfig;
15#[cfg(dma)]
16use embassy_hal_internal::drop::OnDrop;
17use embassy_hal_internal::PeripheralRef;
18use embassy_sync::waitqueue::AtomicWaker;
19#[cfg(dma)]
20use futures_util::future::{select, Either};
21
22#[cfg(dma)]
23use crate::pac::usart::regs::Sr;
24use crate::pac::usart::Usart as Regs;
25use crate::pac::usart::{regs, vals};
26
27#[cfg(dma)]
28use crate::dma::ChannelAndRequest;
29use crate::gpio::{self, AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
30use crate::interrupt::typelevel::Interrupt as _;
31use crate::interrupt::{self, Interrupt, InterruptExt};
32#[cfg(dma)]
33use crate::mode::{Async};
34use crate::mode::{Blocking, Mode};
35use crate::rcc::{RccInfo, SealedRccPeripheral};
36use crate::time::Hertz;
37use crate::Peripheral;
38
39pub struct InterruptHandler<T: Instance> {
41 _phantom: PhantomData<T>,
42}
43
44impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
45 unsafe fn on_interrupt() {
46 on_interrupt(T::info().regs, T::state())
47 }
48}
49
50unsafe fn on_interrupt(r: Regs, s: &'static State) {
51 let (sr, cr1, cr3) = (sr(r).read(), r.cr1().read(), r.cr3().read());
52
53 let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
54 if has_errors {
55 r.cr1().modify(|w| {
57 w.set_rxneie(false);
59 w.set_peie(false);
61 w.set_idleie(false);
63 });
64 r.cr3().modify(|w| {
65 w.set_eie(false);
67 w.set_dmar(false);
69 });
70 } else if cr1.idleie() && sr.idle() {
71 r.cr1().modify(|w| {
73 w.set_idleie(false);
75 });
76 } else if cr1.tcie() && sr.tc() {
77 r.cr1().modify(|w| {
79 w.set_tcie(false);
81 });
82 } else if cr1.rxneie() {
83 } else {
87 return;
88 }
89
90 compiler_fence(Ordering::SeqCst);
91 s.rx_waker.wake();
92}
93
94#[derive(Clone, Copy, PartialEq, Eq, Debug)]
95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96pub enum DataBits {
98 DataBits8,
100 DataBits9,
102}
103
104#[derive(Clone, Copy, PartialEq, Eq, Debug)]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106pub enum Parity {
108 ParityNone,
110 ParityEven,
112 ParityOdd,
114}
115
116#[derive(Clone, Copy, PartialEq, Eq, Debug)]
117#[cfg_attr(feature = "defmt", derive(defmt::Format))]
118pub enum StopBits {
120 #[doc = "1 stop bit"]
121 STOP1,
122 #[doc = "2 stop bits"]
125 STOP2,
126 }
129
130#[non_exhaustive]
131#[derive(Clone, Copy, PartialEq, Eq, Debug)]
132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
133pub enum ConfigError {
135 BaudrateTooLow,
137 BaudrateTooHigh,
139 RxOrTxNotEnabled,
141}
142
143#[non_exhaustive]
144#[derive(Clone, Copy, PartialEq, Eq, Debug)]
145pub struct Config {
147 pub baudrate: u32,
149 pub data_bits: DataBits,
151 pub stop_bits: StopBits,
153 pub parity: Parity,
155
156 pub detect_previous_overrun: bool,
161
162 pub rx_pull: Pull,
164
165 half_duplex: bool,
167}
168
169impl Config {
170 fn tx_af(&self) -> AfType {
171 AfType::output(OutputType::PushPull, Speed::Medium)
172 }
173
174 fn rx_af(&self) -> AfType {
175 AfType::input(self.rx_pull)
176 }
177}
178
179impl Default for Config {
180 fn default() -> Self {
181 Self {
182 baudrate: 115200,
183 data_bits: DataBits::DataBits8,
184 stop_bits: StopBits::STOP1,
185 parity: Parity::ParityNone,
186 detect_previous_overrun: false,
188 rx_pull: Pull::None,
189 half_duplex: false,
190 }
191 }
192}
193
194#[derive(Clone, Copy, PartialEq, Eq, Debug)]
195#[cfg_attr(feature = "defmt", derive(defmt::Format))]
196pub enum HalfDuplexConfig {
198 PushPull,
200 OpenDrainExternal,
202 OpenDrainInternal,
204}
205
206impl HalfDuplexConfig {
207 fn af_type(self) -> gpio::AfType {
208 match self {
209 HalfDuplexConfig::PushPull => AfType::output(OutputType::PushPull, Speed::Medium),
210 HalfDuplexConfig::OpenDrainExternal => {
211 AfType::output(OutputType::OpenDrain, Speed::Medium)
212 }
213 HalfDuplexConfig::OpenDrainInternal => {
214 AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Up)
215 }
216 }
217 }
218}
219
220#[derive(Debug, Eq, PartialEq, Copy, Clone)]
222#[cfg_attr(feature = "defmt", derive(defmt::Format))]
223#[non_exhaustive]
224pub enum Error {
225 Framing,
227 Noise,
229 Overrun,
231 Parity,
233 BufferTooLong,
235}
236
237#[allow(dead_code)]
238enum ReadCompletionEvent {
239 DmaCompleted,
241 Idle(usize),
243}
244
245pub struct Uart<'d, M: Mode> {
254 tx: UartTx<'d, M>,
255 rx: UartRx<'d, M>,
256}
257
258impl<'d, M: Mode> SetConfig for Uart<'d, M> {
259 type Config = Config;
260 type ConfigError = ConfigError;
261
262 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
263 self.tx.set_config(config)?;
264 self.rx.set_config(config)
265 }
266}
267
268pub struct UartTx<'d, M: Mode> {
273 info: &'static Info,
274 state: &'static State,
275 kernel_clock: Hertz,
276 tx: Option<PeripheralRef<'d, AnyPin>>,
277 cts: Option<PeripheralRef<'d, AnyPin>>,
278 de: Option<PeripheralRef<'d, AnyPin>>,
279 #[cfg(dma)]
280 tx_dma: Option<ChannelAndRequest<'d>>,
281 _phantom: PhantomData<M>,
282}
283
284impl<'d, M: Mode> SetConfig for UartTx<'d, M> {
285 type Config = Config;
286 type ConfigError = ConfigError;
287
288 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
289 self.set_config(config)
290 }
291}
292
293pub struct UartRx<'d, M: Mode> {
323 info: &'static Info,
324 state: &'static State,
325 kernel_clock: Hertz,
326 rx: Option<PeripheralRef<'d, AnyPin>>,
327 rts: Option<PeripheralRef<'d, AnyPin>>,
328 #[cfg(dma)] rx_dma: Option<ChannelAndRequest<'d>>,
329 #[allow(dead_code)]
330 detect_previous_overrun: bool,
331 buffered_sr: py32_metapac::usart::regs::Sr,
332 _phantom: PhantomData<M>,
333}
334
335impl<'d, M: Mode> SetConfig for UartRx<'d, M> {
336 type Config = Config;
337 type ConfigError = ConfigError;
338
339 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
340 self.set_config(config)
341 }
342}
343
344#[cfg(dma)]
345impl<'d> UartTx<'d, Async> {
346 pub fn new<T: Instance>(
348 peri: impl Peripheral<P = T> + 'd,
349 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
350 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
351 config: Config,
352 ) -> Result<Self, ConfigError> {
353 Self::new_inner(
354 peri,
355 new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
356 None,
357 new_dma!(tx_dma),
358 config,
359 )
360 }
361
362 pub fn new_with_cts<T: Instance>(
364 peri: impl Peripheral<P = T> + 'd,
365 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
366 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
367 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
368 config: Config,
369 ) -> Result<Self, ConfigError> {
370 Self::new_inner(
371 peri,
372 new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
373 new_pin!(cts, AfType::input(Pull::None)),
374 new_dma!(tx_dma),
375 config,
376 )
377 }
378
379 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
381 let r = self.info.regs;
382
383 let mut cr1 = r.cr1().read();
385 if r.cr3().read().hdsel() && !cr1.te() {
386 cr1.set_te(true);
387 cr1.set_re(false);
388 r.cr1().write_value(cr1);
389 }
390
391 let ch = self.tx_dma.as_mut().unwrap();
392 r.cr3().modify(|reg| {
393 reg.set_dmat(true);
394 });
395 let transfer = unsafe { ch.write(buffer, tdr(r), Default::default()) };
398 transfer.await;
399 Ok(())
400 }
401
402 pub async fn flush(&mut self) -> Result<(), Error> {
404 flush(&self.info, &self.state).await
405 }
406}
407
408impl<'d> UartTx<'d, Blocking> {
409 pub fn new_blocking<T: Instance>(
413 peri: impl Peripheral<P = T> + 'd,
414 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
415 config: Config,
416 ) -> Result<Self, ConfigError> {
417 Self::new_inner(
418 peri,
419 new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
420 None,
421 #[cfg(dma)] None,
422 config,
423 )
424 }
425
426 pub fn new_blocking_with_cts<T: Instance>(
428 peri: impl Peripheral<P = T> + 'd,
429 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
430 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
431 config: Config,
432 ) -> Result<Self, ConfigError> {
433 Self::new_inner(
434 peri,
435 new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)),
436 new_pin!(cts, AfType::input(config.rx_pull)),
437 #[cfg(dma)] None,
438 config,
439 )
440 }
441}
442
443impl<'d, M: Mode> UartTx<'d, M> {
444 fn new_inner<T: Instance>(
445 _peri: impl Peripheral<P = T> + 'd,
446 tx: Option<PeripheralRef<'d, AnyPin>>,
447 cts: Option<PeripheralRef<'d, AnyPin>>,
448 #[cfg(dma)] tx_dma: Option<ChannelAndRequest<'d>>,
449 config: Config,
450 ) -> Result<Self, ConfigError> {
451 let mut this = Self {
452 info: T::info(),
453 state: T::state(),
454 kernel_clock: T::frequency(),
455 tx,
456 cts,
457 de: None,
458 #[cfg(dma)] tx_dma,
459 _phantom: PhantomData,
460 };
461 this.enable_and_configure(&config)?;
462 Ok(this)
463 }
464
465 fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
466 let info = self.info;
467 let state = self.state;
468 state.tx_rx_refcount.store(1, Ordering::Relaxed);
469
470 info.rcc.enable_and_reset();
471
472 info.regs.cr3().modify(|w| {
473 w.set_ctse(self.cts.is_some());
474 });
475 configure(info, self.kernel_clock, config, false, true)?;
476
477 Ok(())
478 }
479
480 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
482 reconfigure(self.info, self.kernel_clock, config)
483 }
484
485 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
487 let r = self.info.regs;
488
489 let mut cr1 = r.cr1().read();
491 if r.cr3().read().hdsel() && !cr1.te() {
492 cr1.set_te(true);
493 cr1.set_re(false);
494 r.cr1().write_value(cr1);
495 }
496
497 for &b in buffer {
498 while !sr(r).read().txe() {}
499 unsafe { tdr(r).write_volatile(b) };
500 }
501 Ok(())
502 }
503
504 pub fn blocking_flush(&mut self) -> Result<(), Error> {
506 blocking_flush(self.info)
507 }
508
509 pub fn send_break(&self) {
511 send_break(&self.info.regs);
512 }
513}
514
515#[allow(dead_code)]
516async fn flush(info: &Info, state: &State) -> Result<(), Error> {
518 let r = info.regs;
519 if r.cr1().read().te() && !sr(r).read().tc() {
520 r.cr1().modify(|w| {
521 w.set_tcie(true);
523 });
524
525 compiler_fence(Ordering::SeqCst);
526
527 let abort = poll_fn(move |cx| {
529 state.rx_waker.register(cx.waker());
530
531 let sr = sr(r).read();
532 if sr.tc() {
533 return Poll::Ready(());
535 }
536
537 Poll::Pending
538 });
539
540 abort.await;
541 }
542
543 Ok(())
544}
545
546fn blocking_flush(info: &Info) -> Result<(), Error> {
547 let r = info.regs;
548 if r.cr1().read().te() {
549 while !sr(r).read().tc() {}
550 }
551
552 Ok(())
553}
554
555pub fn send_break(regs: &Regs) {
557 while regs.cr1().read().sbk() {}
559
560 regs.cr1().modify(|w| w.set_sbk(true));
562}
563
564#[cfg(dma)]
565impl<'d> UartRx<'d, Async> {
566 pub fn new<T: Instance>(
570 peri: impl Peripheral<P = T> + 'd,
571 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
572 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
573 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
574 config: Config,
575 ) -> Result<Self, ConfigError> {
576 Self::new_inner(
577 peri,
578 new_pin!(rx, AfType::input(config.rx_pull)),
579 None,
580 new_dma!(rx_dma),
581 config,
582 )
583 }
584
585 pub fn new_with_rts<T: Instance>(
587 peri: impl Peripheral<P = T> + 'd,
588 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
589 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
590 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
591 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
592 config: Config,
593 ) -> Result<Self, ConfigError> {
594 Self::new_inner(
595 peri,
596 new_pin!(rx, AfType::input(config.rx_pull)),
597 new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
598 new_dma!(rx_dma),
599 config,
600 )
601 }
602
603 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
605 self.inner_read(buffer, false).await?;
606
607 Ok(())
608 }
609
610 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
612 self.inner_read(buffer, true).await
613 }
614
615 async fn inner_read_run(
616 &mut self,
617 buffer: &mut [u8],
618 enable_idle_line_detection: bool,
619 ) -> Result<ReadCompletionEvent, Error> {
620 let r = self.info.regs;
621
622 if r.cr3().read().hdsel() && r.cr1().read().te() {
625 flush(&self.info, &self.state).await?;
626
627 r.cr1().modify(|reg| {
629 reg.set_re(true);
630 reg.set_te(false);
631 });
632 }
633
634 let on_drop = OnDrop::new(move || {
636 r.cr1().modify(|w| {
639 w.set_rxneie(false);
641 w.set_peie(false);
643 w.set_idleie(false);
645 });
646 r.cr3().modify(|w| {
647 w.set_eie(false);
649 w.set_dmar(false);
651 });
652 });
653
654 let ch = self.rx_dma.as_mut().unwrap();
655
656 let buffer_len = buffer.len();
657
658 let transfer = unsafe { ch.read(rdr(r), buffer, Default::default()) };
662
663 if !self.detect_previous_overrun {
665 let sr = sr(r).read();
666 unsafe { rdr(r).read_volatile() };
668 clear_interrupt_flags(r, sr);
669 }
670
671 r.cr1().modify(|w| {
672 w.set_rxneie(false);
674 w.set_peie(w.pce());
676 });
677
678 r.cr3().modify(|w| {
679 w.set_eie(true);
681 w.set_dmar(true);
683 });
684
685 compiler_fence(Ordering::SeqCst);
686
687 let cr3 = r.cr3().read();
692
693 if !cr3.dmar() {
694 let sr = sr(r).read();
700 unsafe { rdr(r).read_volatile() };
702 clear_interrupt_flags(r, sr);
703
704 if sr.pe() {
705 return Err(Error::Parity);
706 }
707 if sr.fe() {
708 return Err(Error::Framing);
709 }
710 if sr.ne() {
711 return Err(Error::Noise);
712 }
713 if sr.ore() {
714 return Err(Error::Overrun);
715 }
716
717 unreachable!();
718 }
719
720 if enable_idle_line_detection {
721 let sr = sr(r).read();
723 unsafe { rdr(r).read_volatile() };
725 clear_interrupt_flags(r, sr);
726
727 r.cr1().modify(|w| {
729 w.set_idleie(true);
730 });
731 }
732
733 compiler_fence(Ordering::SeqCst);
734
735 let s = self.state;
737 let abort = poll_fn(move |cx| {
738 s.rx_waker.register(cx.waker());
739
740 let sr = sr(r).read();
741
742 unsafe { rdr(r).read_volatile() };
744 clear_interrupt_flags(r, sr);
745
746 if enable_idle_line_detection {
747 r.cr1().modify(|w| {
749 w.set_idleie(true);
750 });
751 }
752
753 compiler_fence(Ordering::SeqCst);
754
755 let has_errors = sr.pe() || sr.fe() || sr.ne() || sr.ore();
756
757 if has_errors {
758 if sr.pe() {
761 return Poll::Ready(Err(Error::Parity));
762 }
763 if sr.fe() {
764 return Poll::Ready(Err(Error::Framing));
765 }
766 if sr.ne() {
767 return Poll::Ready(Err(Error::Noise));
768 }
769 if sr.ore() {
770 return Poll::Ready(Err(Error::Overrun));
771 }
772 }
773
774 if enable_idle_line_detection && sr.idle() {
775 return Poll::Ready(Ok(()));
777 }
778
779 Poll::Pending
780 });
781
782 let r = match select(transfer, abort).await {
786 Either::Left(((), _)) => Ok(ReadCompletionEvent::DmaCompleted),
788
789 Either::Right((Ok(()), transfer)) => Ok(ReadCompletionEvent::Idle(
791 buffer_len - transfer.get_remaining_transfers() as usize,
792 )),
793
794 Either::Right((Err(e), _)) => Err(e),
796 };
797
798 drop(on_drop);
799
800 r
801 }
802
803 async fn inner_read(
804 &mut self,
805 buffer: &mut [u8],
806 enable_idle_line_detection: bool,
807 ) -> Result<usize, Error> {
808 if buffer.is_empty() {
809 return Ok(0);
810 } else if buffer.len() > 0xFFFF {
811 return Err(Error::BufferTooLong);
812 }
813
814 let buffer_len = buffer.len();
815
816 let res = self
818 .inner_read_run(buffer, enable_idle_line_detection)
819 .await;
820
821 match res {
822 Ok(ReadCompletionEvent::DmaCompleted) => Ok(buffer_len),
823 Ok(ReadCompletionEvent::Idle(n)) => Ok(n),
824 Err(e) => Err(e),
825 }
826 }
827}
828
829impl<'d> UartRx<'d, Blocking> {
830 pub fn new_blocking<T: Instance>(
834 peri: impl Peripheral<P = T> + 'd,
835 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
836 config: Config,
837 ) -> Result<Self, ConfigError> {
838 Self::new_inner(
839 peri,
840 new_pin!(rx, AfType::input(config.rx_pull)),
841 None,
842 #[cfg(dma)] None,
843 config,
844 )
845 }
846
847 pub fn new_blocking_with_rts<T: Instance>(
849 peri: impl Peripheral<P = T> + 'd,
850 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
851 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
852 config: Config,
853 ) -> Result<Self, ConfigError> {
854 Self::new_inner(
855 peri,
856 new_pin!(rx, AfType::input(config.rx_pull)),
857 new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
858 #[cfg(dma)] None,
859 config,
860 )
861 }
862}
863
864impl<'d, M: Mode> UartRx<'d, M> {
865 fn new_inner<T: Instance>(
866 _peri: impl Peripheral<P = T> + 'd,
867 rx: Option<PeripheralRef<'d, AnyPin>>,
868 rts: Option<PeripheralRef<'d, AnyPin>>,
869 #[cfg(dma)] rx_dma: Option<ChannelAndRequest<'d>>,
870 config: Config,
871 ) -> Result<Self, ConfigError> {
872 let mut this = Self {
873 _phantom: PhantomData,
874 info: T::info(),
875 state: T::state(),
876 kernel_clock: T::frequency(),
877 rx,
878 rts,
879 #[cfg(dma)] rx_dma,
880 detect_previous_overrun: config.detect_previous_overrun,
881 buffered_sr: py32_metapac::usart::regs::Sr(0),
882 };
883 this.enable_and_configure(&config)?;
884 Ok(this)
885 }
886
887 fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
888 let info = self.info;
889 let state = self.state;
890 state.tx_rx_refcount.store(1, Ordering::Relaxed);
891
892 info.rcc.enable_and_reset();
893
894 info.regs.cr3().write(|w| {
895 w.set_rtse(self.rts.is_some());
896 });
897 configure(info, self.kernel_clock, &config, true, false)?;
898
899 info.interrupt.unpend();
900 unsafe { info.interrupt.enable() };
901
902 Ok(())
903 }
904
905 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
907 reconfigure(self.info, self.kernel_clock, config)
908 }
909
910 fn check_rx_flags(&mut self) -> Result<bool, Error> {
911 let r = self.info.regs;
912 loop {
913 if self.buffered_sr.pe() {
915 self.buffered_sr.set_pe(false);
916 return Err(Error::Parity);
917 } else if self.buffered_sr.fe() {
918 self.buffered_sr.set_fe(false);
919 return Err(Error::Framing);
920 } else if self.buffered_sr.ne() {
921 self.buffered_sr.set_ne(false);
922 return Err(Error::Noise);
923 } else if self.buffered_sr.ore() {
924 self.buffered_sr.set_ore(false);
925 return Err(Error::Overrun);
926 } else if self.buffered_sr.rxne() {
927 self.buffered_sr.set_rxne(false);
928 return Ok(true);
929 } else {
930 let sr = r.sr().read();
932 if !sr.rxne() {
933 return Ok(false);
934 }
935
936 self.buffered_sr = sr;
938 }
939 }
940 }
941
942 pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
944 let r = self.info.regs;
945 if self.check_rx_flags()? {
946 Ok(unsafe { rdr(r).read_volatile() })
947 } else {
948 Err(nb::Error::WouldBlock)
949 }
950 }
951
952 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
954 let r = self.info.regs;
955
956 if r.cr3().read().hdsel() && r.cr1().read().te() {
959 blocking_flush(self.info)?;
960
961 r.cr1().modify(|reg| {
963 reg.set_re(true);
964 reg.set_te(false);
965 });
966 }
967
968 for b in buffer {
969 while !self.check_rx_flags()? {}
970 unsafe { *b = rdr(r).read_volatile() }
971 }
972 Ok(())
973 }
974}
975
976impl<'d, M: Mode> Drop for UartTx<'d, M> {
977 fn drop(&mut self) {
978 self.tx.as_ref().map(|x| x.set_as_disconnected());
979 self.cts.as_ref().map(|x| x.set_as_disconnected());
980 self.de.as_ref().map(|x| x.set_as_disconnected());
981 drop_tx_rx(self.info, self.state);
982 }
983}
984
985impl<'d, M: Mode> Drop for UartRx<'d, M> {
986 fn drop(&mut self) {
987 self.rx.as_ref().map(|x| x.set_as_disconnected());
988 self.rts.as_ref().map(|x| x.set_as_disconnected());
989 drop_tx_rx(self.info, self.state);
990 }
991}
992
993fn drop_tx_rx(info: &Info, state: &State) {
994 let is_last_drop = critical_section::with(|_| {
996 let refcount = state.tx_rx_refcount.load(Ordering::Relaxed);
997 assert!(refcount >= 1);
998 state.tx_rx_refcount.store(refcount - 1, Ordering::Relaxed);
999 refcount == 1
1000 });
1001 if is_last_drop {
1002 info.rcc.disable();
1003 }
1004}
1005
1006#[cfg(dma)]
1007impl<'d> Uart<'d, Async> {
1008 pub fn new<T: Instance>(
1010 peri: impl Peripheral<P = T> + 'd,
1011 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
1012 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
1013 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1014 #[cfg(dma)] tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
1015 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
1016 config: Config,
1017 ) -> Result<Self, ConfigError> {
1018 Self::new_inner(
1019 peri,
1020 new_pin!(rx, config.rx_af()),
1021 new_pin!(tx, config.tx_af()),
1022 None,
1023 None,
1024 None,
1025 new_dma!(tx_dma),
1026 new_dma!(rx_dma),
1027 config,
1028 )
1029 }
1030
1031 pub fn new_with_rtscts<T: Instance>(
1033 peri: impl Peripheral<P = T> + 'd,
1034 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
1035 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
1036 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1037 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
1038 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
1039 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
1040 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
1041 config: Config,
1042 ) -> Result<Self, ConfigError> {
1043 Self::new_inner(
1044 peri,
1045 new_pin!(rx, config.rx_af()),
1046 new_pin!(tx, config.tx_af()),
1047 new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
1048 new_pin!(cts, AfType::input(Pull::None)),
1049 None,
1050 new_dma!(tx_dma),
1051 new_dma!(rx_dma),
1052 config,
1053 )
1054 }
1055
1056 #[doc(alias("HDSEL"))]
1068 pub fn new_half_duplex<T: Instance>(
1069 peri: impl Peripheral<P = T> + 'd,
1070 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
1071 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
1072 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
1073 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
1074 mut config: Config,
1075 half_duplex: HalfDuplexConfig,
1076 ) -> Result<Self, ConfigError> {
1077 config.half_duplex = true;
1078
1079 Self::new_inner(
1080 peri,
1081 None,
1082 new_pin!(tx, half_duplex.af_type()),
1083 None,
1084 None,
1085 None,
1086 new_dma!(tx_dma),
1087 new_dma!(rx_dma),
1088 config,
1089 )
1090 }
1091
1092 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
1094 self.tx.write(buffer).await
1095 }
1096
1097 pub async fn flush(&mut self) -> Result<(), Error> {
1099 self.tx.flush().await
1100 }
1101
1102 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
1104 self.rx.read(buffer).await
1105 }
1106
1107 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
1109 self.rx.read_until_idle(buffer).await
1110 }
1111}
1112
1113impl<'d> Uart<'d, Blocking> {
1114 pub fn new_blocking<T: Instance>(
1116 peri: impl Peripheral<P = T> + 'd,
1117 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
1118 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
1119 config: Config,
1120 ) -> Result<Self, ConfigError> {
1121 Self::new_inner(
1122 peri,
1123 new_pin!(rx, config.rx_af()),
1124 new_pin!(tx, config.tx_af()),
1125 None,
1126 None,
1127 None,
1128 #[cfg(dma)] None,
1129 #[cfg(dma)] None,
1130 config,
1131 )
1132 }
1133
1134 pub fn new_blocking_with_rtscts<T: Instance>(
1136 peri: impl Peripheral<P = T> + 'd,
1137 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
1138 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
1139 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
1140 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
1141 config: Config,
1142 ) -> Result<Self, ConfigError> {
1143 Self::new_inner(
1144 peri,
1145 new_pin!(rx, config.rx_af()),
1146 new_pin!(tx, config.tx_af()),
1147 new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)),
1148 new_pin!(cts, AfType::input(Pull::None)),
1149 None,
1150 #[cfg(dma)] None,
1151 #[cfg(dma)] None,
1152 config,
1153 )
1154 }
1155
1156 #[doc(alias("HDSEL"))]
1167 pub fn new_blocking_half_duplex<T: Instance>(
1168 peri: impl Peripheral<P = T> + 'd,
1169 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
1170 mut config: Config,
1171 half_duplex: HalfDuplexConfig,
1172 ) -> Result<Self, ConfigError> {
1173 config.half_duplex = true;
1174
1175 Self::new_inner(
1176 peri,
1177 None,
1178 new_pin!(tx, half_duplex.af_type()),
1179 None,
1180 None,
1181 None,
1182 #[cfg(dma)] None,
1183 #[cfg(dma)] None,
1184 config,
1185 )
1186 }
1187}
1188
1189impl<'d, M: Mode> Uart<'d, M> {
1190 fn new_inner<T: Instance>(
1191 _peri: impl Peripheral<P = T> + 'd,
1192 rx: Option<PeripheralRef<'d, AnyPin>>,
1193 tx: Option<PeripheralRef<'d, AnyPin>>,
1194 rts: Option<PeripheralRef<'d, AnyPin>>,
1195 cts: Option<PeripheralRef<'d, AnyPin>>,
1196 de: Option<PeripheralRef<'d, AnyPin>>,
1197 #[cfg(dma)] tx_dma: Option<ChannelAndRequest<'d>>,
1198 #[cfg(dma)] rx_dma: Option<ChannelAndRequest<'d>>,
1199 config: Config,
1200 ) -> Result<Self, ConfigError> {
1201 let info = T::info();
1202 let state = T::state();
1203 let kernel_clock = T::frequency();
1204
1205 let mut this = Self {
1206 tx: UartTx {
1207 _phantom: PhantomData,
1208 info,
1209 state,
1210 kernel_clock,
1211 tx,
1212 cts,
1213 de,
1214 #[cfg(dma)] tx_dma,
1215 },
1216 rx: UartRx {
1217 _phantom: PhantomData,
1218 info,
1219 state,
1220 kernel_clock,
1221 rx,
1222 rts,
1223 #[cfg(dma)] rx_dma,
1224 detect_previous_overrun: config.detect_previous_overrun,
1225 buffered_sr: py32_metapac::usart::regs::Sr(0),
1226 },
1227 };
1228 this.enable_and_configure(&config)?;
1229 Ok(this)
1230 }
1231
1232 fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
1233 let info = self.rx.info;
1234 let state = self.rx.state;
1235 state.tx_rx_refcount.store(2, Ordering::Relaxed);
1236
1237 info.rcc.enable_and_reset();
1238
1239 info.regs.cr3().write(|w| {
1240 w.set_rtse(self.rx.rts.is_some());
1241 w.set_ctse(self.tx.cts.is_some());
1242 });
1243 configure(info, self.rx.kernel_clock, config, true, true)?;
1244
1245 info.interrupt.unpend();
1246 unsafe { info.interrupt.enable() };
1247
1248 Ok(())
1249 }
1250
1251 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
1253 self.tx.blocking_write(buffer)
1254 }
1255
1256 pub fn blocking_flush(&mut self) -> Result<(), Error> {
1258 self.tx.blocking_flush()
1259 }
1260
1261 pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
1263 self.rx.nb_read()
1264 }
1265
1266 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
1268 self.rx.blocking_read(buffer)
1269 }
1270
1271 pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) {
1275 (self.tx, self.rx)
1276 }
1277
1278 pub fn send_break(&self) {
1280 self.tx.send_break();
1281 }
1282}
1283
1284fn reconfigure(info: &Info, kernel_clock: Hertz, config: &Config) -> Result<(), ConfigError> {
1285 info.interrupt.disable();
1286 let r = info.regs;
1287
1288 let cr = r.cr1().read();
1289 configure(info, kernel_clock, config, cr.re(), cr.te())?;
1290
1291 info.interrupt.unpend();
1292 unsafe { info.interrupt.enable() };
1293
1294 Ok(())
1295}
1296
1297fn configure(
1298 info: &Info,
1299 kernel_clock: Hertz,
1300 config: &Config,
1301 enable_rx: bool,
1302 enable_tx: bool,
1303) -> Result<(), ConfigError> {
1304 let r = info.regs;
1305 let kind = info.kind;
1306
1307 if !enable_rx && !enable_tx {
1308 return Err(ConfigError::RxOrTxNotEnabled);
1309 }
1310
1311 static DIVS: [(u16, ()); 1] = [(1, ())];
1312
1313 let (mul, brr_min, brr_max) = match kind {
1314 Kind::Uart => {
1315 trace!("USART: Kind::Uart");
1316 (1, 0x10, 0x1_0000)
1317 }
1318 };
1319
1320 fn calculate_brr(baud: u32, pclk: u32, presc: u32, mul: u32) -> u32 {
1321 let clock = pclk / presc;
1324
1325 let brr = clock / baud * mul;
1327
1328 let rounding = ((clock % baud) * mul + (baud / 2)) / baud;
1331
1332 brr + rounding
1333 }
1334
1335 r.cr1().modify(|w| {
1337 w.set_ue(false);
1338 });
1339
1340 let mut over8 = false;
1341 let mut found_brr = None;
1342 for &(presc, _presc_val) in &DIVS {
1343 let brr = calculate_brr(config.baudrate, kernel_clock.0, presc as u32, mul);
1344 trace!(
1345 "USART: presc={}, div=0x{:08x} (mantissa = {}, fraction = {})",
1346 presc,
1347 brr,
1348 brr >> 4,
1349 brr & 0x0F
1350 );
1351
1352 if brr < brr_min {
1353 if brr * 2 >= brr_min && kind == Kind::Uart {
1354 over8 = true;
1355 r.brr()
1356 .write_value(regs::Brr(((brr << 1) & !0xF) | (brr & 0x07)));
1357 found_brr = Some(brr);
1358 break;
1359 }
1360 return Err(ConfigError::BaudrateTooHigh);
1361 }
1362
1363 if brr < brr_max {
1364 r.brr().write_value(regs::Brr(brr));
1365 found_brr = Some(brr);
1366 break;
1367 }
1368 }
1369
1370 let brr = found_brr.ok_or(ConfigError::BaudrateTooLow)?;
1371 let oversampling = if over8 { "8 bit" } else { "16 bit" };
1372 trace!(
1373 "Using {} oversampling, desired baudrate: {}, actual baudrate: {}",
1374 oversampling,
1375 config.baudrate,
1376 kernel_clock.0 / brr * mul
1377 );
1378
1379 r.cr2().write(|w| {
1380 w.set_stop(match config.stop_bits {
1381 StopBits::STOP1 => vals::Stop::STOP1,
1383 StopBits::STOP2 => vals::Stop::STOP2,
1385 });
1386 });
1387
1388 r.cr3().modify(|w| {
1389 w.set_hdsel(config.half_duplex);
1390 w.set_over8(vals::Over8::from_bits(over8 as _));
1391 });
1392
1393 r.cr1().write(|w| {
1394 w.set_ue(true);
1396
1397 if config.half_duplex {
1398 w.set_te(false);
1401 w.set_re(true);
1402 } else {
1403 w.set_te(enable_tx);
1405 w.set_re(enable_rx);
1407 }
1408
1409 w.set_m0(if config.parity != Parity::ParityNone {
1412 trace!("USART: m0: vals::M0::BIT9");
1413 vals::M0::BIT9
1414 } else {
1415 trace!("USART: m0: vals::M0::BIT8");
1416 vals::M0::BIT8
1417 });
1418 w.set_pce(config.parity != Parity::ParityNone);
1420 w.set_ps(match config.parity {
1421 Parity::ParityOdd => {
1422 trace!("USART: set_ps: vals::Ps::ODD");
1423 vals::Ps::ODD
1424 }
1425 Parity::ParityEven => {
1426 trace!("USART: set_ps: vals::Ps::EVEN");
1427 vals::Ps::EVEN
1428 }
1429 _ => {
1430 trace!("USART: set_ps: vals::Ps::EVEN");
1431 vals::Ps::EVEN
1432 }
1433 });
1434 });
1435
1436 Ok(())
1437}
1438
1439impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, M> {
1440 type Error = Error;
1441 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
1442 self.nb_read()
1443 }
1444}
1445
1446impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, M> {
1447 type Error = Error;
1448 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
1449 self.blocking_write(buffer)
1450 }
1451 fn bflush(&mut self) -> Result<(), Self::Error> {
1452 self.blocking_flush()
1453 }
1454}
1455
1456impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, M> {
1457 type Error = Error;
1458 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
1459 self.nb_read()
1460 }
1461}
1462
1463impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, M> {
1464 type Error = Error;
1465 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
1466 self.blocking_write(buffer)
1467 }
1468 fn bflush(&mut self) -> Result<(), Self::Error> {
1469 self.blocking_flush()
1470 }
1471}
1472
1473impl embedded_hal_nb::serial::Error for Error {
1474 fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
1475 match *self {
1476 Self::Framing => embedded_hal_nb::serial::ErrorKind::FrameFormat,
1477 Self::Noise => embedded_hal_nb::serial::ErrorKind::Noise,
1478 Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun,
1479 Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity,
1480 Self::BufferTooLong => embedded_hal_nb::serial::ErrorKind::Other,
1481 }
1482 }
1483}
1484
1485impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, M> {
1486 type Error = Error;
1487}
1488
1489impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, M> {
1490 type Error = Error;
1491}
1492
1493impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, M> {
1494 type Error = Error;
1495}
1496
1497impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> {
1498 fn read(&mut self) -> nb::Result<u8, Self::Error> {
1499 self.nb_read()
1500 }
1501}
1502
1503impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> {
1504 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
1505 self.blocking_write(&[char]).map_err(nb::Error::Other)
1506 }
1507
1508 fn flush(&mut self) -> nb::Result<(), Self::Error> {
1509 self.blocking_flush().map_err(nb::Error::Other)
1510 }
1511}
1512
1513impl<'d, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, M> {
1514 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
1515 self.nb_read()
1516 }
1517}
1518
1519impl<'d, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, M> {
1520 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
1521 self.blocking_write(&[char]).map_err(nb::Error::Other)
1522 }
1523
1524 fn flush(&mut self) -> nb::Result<(), Self::Error> {
1525 self.blocking_flush().map_err(nb::Error::Other)
1526 }
1527}
1528
1529impl embedded_io::Error for Error {
1530 fn kind(&self) -> embedded_io::ErrorKind {
1531 embedded_io::ErrorKind::Other
1532 }
1533}
1534
1535impl<M: Mode> embedded_io::ErrorType for Uart<'_, M> {
1536 type Error = Error;
1537}
1538
1539impl<M: Mode> embedded_io::ErrorType for UartTx<'_, M> {
1540 type Error = Error;
1541}
1542
1543impl<M: Mode> embedded_io::Write for Uart<'_, M> {
1544 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1545 self.blocking_write(buf)?;
1546 Ok(buf.len())
1547 }
1548
1549 fn flush(&mut self) -> Result<(), Self::Error> {
1550 self.blocking_flush()
1551 }
1552}
1553
1554impl<M: Mode> embedded_io::Write for UartTx<'_, M> {
1555 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1556 self.blocking_write(buf)?;
1557 Ok(buf.len())
1558 }
1559
1560 fn flush(&mut self) -> Result<(), Self::Error> {
1561 self.blocking_flush()
1562 }
1563}
1564
1565#[cfg(dma)]
1566impl embedded_io_async::Write for Uart<'_, Async> {
1567 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1568 self.write(buf).await?;
1569 Ok(buf.len())
1570 }
1571
1572 async fn flush(&mut self) -> Result<(), Self::Error> {
1573 self.flush().await
1574 }
1575}
1576
1577#[cfg(dma)]
1578impl embedded_io_async::Write for UartTx<'_, Async> {
1579 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1580 self.write(buf).await?;
1581 Ok(buf.len())
1582 }
1583
1584 async fn flush(&mut self) -> Result<(), Self::Error> {
1585 self.flush().await
1586 }
1587}
1588
1589pub use buffered::*;
1590
1591pub use crate::usart::buffered::InterruptHandler as BufferedInterruptHandler;
1592mod buffered;
1593
1594#[cfg(dma)]
1595mod ringbuffered;
1596#[cfg(dma)]
1597pub use ringbuffered::RingBufferedUartRx;
1598
1599fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
1600 r.dr().as_ptr() as _
1601}
1602
1603fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
1604 r.dr().as_ptr() as _
1605}
1606
1607fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::pac::common::RW> {
1608 r.sr()
1609}
1610
1611#[allow(unused)]
1612fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) {
1613 }
1615
1616#[derive(Clone, Copy, PartialEq, Eq)]
1617enum Kind {
1618 Uart,
1619}
1620
1621struct State {
1622 rx_waker: AtomicWaker,
1623 tx_rx_refcount: AtomicU8,
1624}
1625
1626impl State {
1627 const fn new() -> Self {
1628 Self {
1629 rx_waker: AtomicWaker::new(),
1630 tx_rx_refcount: AtomicU8::new(0),
1631 }
1632 }
1633}
1634
1635struct Info {
1636 regs: Regs,
1637 rcc: RccInfo,
1638 interrupt: Interrupt,
1639 kind: Kind,
1640}
1641
1642#[allow(private_interfaces)]
1643pub(crate) trait SealedInstance: crate::rcc::RccPeripheral {
1644 fn info() -> &'static Info;
1645 fn state() -> &'static State;
1646 fn buffered_state() -> &'static buffered::State;
1647}
1648
1649#[allow(private_bounds)]
1651pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
1652 type Interrupt: interrupt::typelevel::Interrupt;
1654}
1655
1656pin_trait!(RxPin, Instance);
1657pin_trait!(TxPin, Instance);
1658pin_trait!(CtsPin, Instance);
1659pin_trait!(RtsPin, Instance);
1660pin_trait!(CkPin, Instance);
1661pin_trait!(DePin, Instance);
1662
1663#[cfg(dma)] dma_trait!(TxDma, Instance);
1664#[cfg(dma)] dma_trait!(RxDma, Instance);
1665
1666macro_rules! impl_usart {
1667 ($inst:ident, $irq:ident, $kind:expr) => {
1668 #[allow(private_interfaces)]
1669 impl SealedInstance for crate::peripherals::$inst {
1670 fn info() -> &'static Info {
1671 static INFO: Info = Info {
1672 regs: unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) },
1673 rcc: crate::peripherals::$inst::RCC_INFO,
1674 interrupt: crate::interrupt::typelevel::$irq::IRQ,
1675 kind: $kind,
1676 };
1677 &INFO
1678 }
1679
1680 fn state() -> &'static State {
1681 static STATE: State = State::new();
1682 &STATE
1683 }
1684
1685 fn buffered_state() -> &'static buffered::State {
1686 static BUFFERED_STATE: buffered::State = buffered::State::new();
1687 &BUFFERED_STATE
1688 }
1689 }
1690
1691 impl Instance for crate::peripherals::$inst {
1692 type Interrupt = crate::interrupt::typelevel::$irq;
1693 }
1694 };
1695}
1696
1697foreach_interrupt!(
1698 ($inst:ident, usart, LPUART, $signal_name:ident, $irq:ident) => {
1699 impl_usart!($inst, $irq, Kind::Lpuart);
1700 };
1701 ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
1702 impl_usart!($inst, $irq, Kind::Uart);
1703 };
1704);