aboutsummaryrefslogtreecommitdiff
path: root/embassy-nxp/src/usart/lpc55.rs
diff options
context:
space:
mode:
authorRaul Alimbekov <[email protected]>2025-12-16 09:05:22 +0300
committerGitHub <[email protected]>2025-12-16 09:05:22 +0300
commitc9a04b4b732b7a3b696eb8223664c1a7942b1875 (patch)
tree6dbe5c02e66eed8d8762f13f95afd24f8db2b38c /embassy-nxp/src/usart/lpc55.rs
parentcde24a3ef1117653ba5ed4184102b33f745782fb (diff)
parent5ae6e060ec1c90561719aabdc29d5b6e7b8b0a82 (diff)
Merge branch 'main' into main
Diffstat (limited to 'embassy-nxp/src/usart/lpc55.rs')
-rw-r--r--embassy-nxp/src/usart/lpc55.rs226
1 files changed, 115 insertions, 111 deletions
diff --git a/embassy-nxp/src/usart/lpc55.rs b/embassy-nxp/src/usart/lpc55.rs
index 9034ed429..d77f08fd8 100644
--- a/embassy-nxp/src/usart/lpc55.rs
+++ b/embassy-nxp/src/usart/lpc55.rs
@@ -1,19 +1,21 @@
1#![macro_use]
2
1use core::fmt::Debug; 3use core::fmt::Debug;
2use core::future::poll_fn; 4use core::future::poll_fn;
3use core::marker::PhantomData; 5use core::marker::PhantomData;
4use core::sync::atomic::{AtomicBool, Ordering}; 6use core::sync::atomic::{AtomicBool, Ordering};
5use core::task::Poll; 7use core::task::Poll;
6 8
7use embassy_futures::select::{select, Either}; 9use embassy_futures::select::{Either, select};
8use embassy_hal_internal::interrupt::InterruptExt; 10use embassy_hal_internal::interrupt::InterruptExt;
9use embassy_hal_internal::{Peri, PeripheralType}; 11use embassy_hal_internal::{Peri, PeripheralType};
10use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
11use embedded_io::{self, ErrorKind}; 13use embedded_io::{self, ErrorKind};
12 14
13use crate::dma::{AnyChannel, Channel}; 15use crate::dma::{AnyChannel, Channel};
14use crate::gpio::{match_iocon, AnyPin, Bank, SealedPin}; 16use crate::gpio::{AnyPin, SealedPin};
15use crate::interrupt::typelevel::{Binding, Interrupt as _};
16use crate::interrupt::Interrupt; 17use crate::interrupt::Interrupt;
18use crate::interrupt::typelevel::Binding;
17use crate::pac::flexcomm::Flexcomm as FlexcommReg; 19use crate::pac::flexcomm::Flexcomm as FlexcommReg;
18use crate::pac::iocon::vals::PioFunc; 20use crate::pac::iocon::vals::PioFunc;
19use crate::pac::usart::Usart as UsartReg; 21use crate::pac::usart::Usart as UsartReg;
@@ -113,8 +115,8 @@ impl Default for Config {
113 115
114/// Internal DMA state of UART RX. 116/// Internal DMA state of UART RX.
115pub struct DmaState { 117pub struct DmaState {
116 rx_err_waker: AtomicWaker, 118 pub(crate) rx_err_waker: AtomicWaker,
117 rx_err: AtomicBool, 119 pub(crate) rx_err: AtomicBool,
118} 120}
119 121
120/// # Type parameters 122/// # Type parameters
@@ -146,7 +148,8 @@ impl<'d, M: Mode> UsartTx<'d, M> {
146 tx_dma: Peri<'d, impl Channel>, 148 tx_dma: Peri<'d, impl Channel>,
147 config: Config, 149 config: Config,
148 ) -> Self { 150 ) -> Self {
149 Usart::<M>::init::<T>(Some(tx.into()), None, config); 151 let tx_func = tx.pin_func();
152 Usart::<M>::init::<T>(Some((tx.into(), tx_func)), None, config);
150 Self::new_inner(T::info(), Some(tx_dma.into())) 153 Self::new_inner(T::info(), Some(tx_dma.into()))
151 } 154 }
152 155
@@ -179,7 +182,8 @@ impl<'d, M: Mode> UsartTx<'d, M> {
179 182
180impl<'d> UsartTx<'d, Blocking> { 183impl<'d> UsartTx<'d, Blocking> {
181 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self { 184 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self {
182 Usart::<Blocking>::init::<T>(Some(tx.into()), None, config); 185 let tx_func = tx.pin_func();
186 Usart::<Blocking>::init::<T>(Some((tx.into(), tx_func)), None, config);
183 Self::new_inner(T::info(), None) 187 Self::new_inner(T::info(), None)
184 } 188 }
185} 189}
@@ -208,7 +212,8 @@ impl<'d, M: Mode> UsartRx<'d, M> {
208 rx_dma: Peri<'d, impl Channel>, 212 rx_dma: Peri<'d, impl Channel>,
209 config: Config, 213 config: Config,
210 ) -> Self { 214 ) -> Self {
211 Usart::<M>::init::<T>(None, Some(rx.into()), config); 215 let rx_func = rx.pin_func();
216 Usart::<M>::init::<T>(None, Some((rx.into(), rx_func)), config);
212 Self::new_inner(T::info(), T::dma_state(), has_irq, Some(rx_dma.into())) 217 Self::new_inner(T::info(), T::dma_state(), has_irq, Some(rx_dma.into()))
213 } 218 }
214 219
@@ -280,7 +285,8 @@ impl<'d, M: Mode> UsartRx<'d, M> {
280 285
281impl<'d> UsartRx<'d, Blocking> { 286impl<'d> UsartRx<'d, Blocking> {
282 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self { 287 pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self {
283 Usart::<Blocking>::init::<T>(None, Some(rx.into()), config); 288 let rx_func = rx.pin_func();
289 Usart::<Blocking>::init::<T>(None, Some((rx.into(), rx_func)), config);
284 Self::new_inner(T::info(), T::dma_state(), false, None) 290 Self::new_inner(T::info(), T::dma_state(), false, None)
285 } 291 }
286} 292}
@@ -405,7 +411,10 @@ impl<'d> Usart<'d, Blocking> {
405 rx: Peri<'d, impl RxPin<T>>, 411 rx: Peri<'d, impl RxPin<T>>,
406 config: Config, 412 config: Config,
407 ) -> Self { 413 ) -> Self {
408 Self::new_inner(usart, tx.into(), rx.into(), false, None, None, config) 414 let tx_func = tx.pin_func();
415 let rx_func = rx.pin_func();
416
417 Self::new_inner(usart, tx.into(), tx_func, rx.into(), rx_func, false, None, None, config)
409 } 418 }
410} 419}
411 420
@@ -419,10 +428,15 @@ impl<'d> Usart<'d, Async> {
419 rx_dma: Peri<'d, impl RxChannel<T>>, 428 rx_dma: Peri<'d, impl RxChannel<T>>,
420 config: Config, 429 config: Config,
421 ) -> Self { 430 ) -> Self {
431 let tx_func = tx.pin_func();
432 let rx_func = rx.pin_func();
433
422 Self::new_inner( 434 Self::new_inner(
423 uart, 435 uart,
424 tx.into(), 436 tx.into(),
437 tx_func,
425 rx.into(), 438 rx.into(),
439 rx_func,
426 true, 440 true,
427 Some(tx_dma.into()), 441 Some(tx_dma.into()),
428 Some(rx_dma.into()), 442 Some(rx_dma.into()),
@@ -435,20 +449,26 @@ impl<'d, M: Mode> Usart<'d, M> {
435 fn new_inner<T: Instance>( 449 fn new_inner<T: Instance>(
436 _usart: Peri<'d, T>, 450 _usart: Peri<'d, T>,
437 mut tx: Peri<'d, AnyPin>, 451 mut tx: Peri<'d, AnyPin>,
452 tx_func: PioFunc,
438 mut rx: Peri<'d, AnyPin>, 453 mut rx: Peri<'d, AnyPin>,
454 rx_func: PioFunc,
439 has_irq: bool, 455 has_irq: bool,
440 tx_dma: Option<Peri<'d, AnyChannel>>, 456 tx_dma: Option<Peri<'d, AnyChannel>>,
441 rx_dma: Option<Peri<'d, AnyChannel>>, 457 rx_dma: Option<Peri<'d, AnyChannel>>,
442 config: Config, 458 config: Config,
443 ) -> Self { 459 ) -> Self {
444 Self::init::<T>(Some(tx.reborrow()), Some(rx.reborrow()), config); 460 Self::init::<T>(Some((tx.reborrow(), tx_func)), Some((rx.reborrow(), rx_func)), config);
445 Self { 461 Self {
446 tx: UsartTx::new_inner(T::info(), tx_dma), 462 tx: UsartTx::new_inner(T::info(), tx_dma),
447 rx: UsartRx::new_inner(T::info(), T::dma_state(), has_irq, rx_dma), 463 rx: UsartRx::new_inner(T::info(), T::dma_state(), has_irq, rx_dma),
448 } 464 }
449 } 465 }
450 466
451 fn init<T: Instance>(tx: Option<Peri<'_, AnyPin>>, rx: Option<Peri<'_, AnyPin>>, config: Config) { 467 fn init<T: Instance>(
468 tx: Option<(Peri<'_, AnyPin>, PioFunc)>,
469 rx: Option<(Peri<'_, AnyPin>, PioFunc)>,
470 config: Config,
471 ) {
452 Self::configure_flexcomm(T::info().fc_reg, T::instance_number()); 472 Self::configure_flexcomm(T::info().fc_reg, T::instance_number());
453 Self::configure_clock::<T>(&config); 473 Self::configure_clock::<T>(&config);
454 Self::pin_config::<T>(tx, rx); 474 Self::pin_config::<T>(tx, rx);
@@ -553,31 +573,27 @@ impl<'d, M: Mode> Usart<'d, M> {
553 .modify(|w| w.set_brgval((brg_value - 1) as u16)); 573 .modify(|w| w.set_brgval((brg_value - 1) as u16));
554 } 574 }
555 575
556 fn pin_config<T: Instance>(tx: Option<Peri<'_, AnyPin>>, rx: Option<Peri<'_, AnyPin>>) { 576 fn pin_config<T: Instance>(tx: Option<(Peri<'_, AnyPin>, PioFunc)>, rx: Option<(Peri<'_, AnyPin>, PioFunc)>) {
557 if let Some(tx_pin) = tx { 577 if let Some((tx_pin, func)) = tx {
558 match_iocon!(register, tx_pin.pin_bank(), tx_pin.pin_number(), { 578 tx_pin.pio().modify(|w| {
559 register.modify(|w| { 579 w.set_func(func);
560 w.set_func(T::tx_pin_func()); 580 w.set_mode(iocon::vals::PioMode::INACTIVE);
561 w.set_mode(iocon::vals::PioMode::INACTIVE); 581 w.set_slew(iocon::vals::PioSlew::STANDARD);
562 w.set_slew(iocon::vals::PioSlew::STANDARD); 582 w.set_invert(false);
563 w.set_invert(false); 583 w.set_digimode(iocon::vals::PioDigimode::DIGITAL);
564 w.set_digimode(iocon::vals::PioDigimode::DIGITAL); 584 w.set_od(iocon::vals::PioOd::NORMAL);
565 w.set_od(iocon::vals::PioOd::NORMAL); 585 });
566 });
567 })
568 } 586 }
569 587
570 if let Some(rx_pin) = rx { 588 if let Some((rx_pin, func)) = rx {
571 match_iocon!(register, rx_pin.pin_bank(), rx_pin.pin_number(), { 589 rx_pin.pio().modify(|w| {
572 register.modify(|w| { 590 w.set_func(func);
573 w.set_func(T::rx_pin_func()); 591 w.set_mode(iocon::vals::PioMode::INACTIVE);
574 w.set_mode(iocon::vals::PioMode::INACTIVE); 592 w.set_slew(iocon::vals::PioSlew::STANDARD);
575 w.set_slew(iocon::vals::PioSlew::STANDARD); 593 w.set_invert(false);
576 w.set_invert(false); 594 w.set_digimode(iocon::vals::PioDigimode::DIGITAL);
577 w.set_digimode(iocon::vals::PioDigimode::DIGITAL); 595 w.set_od(iocon::vals::PioOd::NORMAL);
578 w.set_od(iocon::vals::PioOd::NORMAL); 596 });
579 });
580 })
581 }; 597 };
582 } 598 }
583 599
@@ -804,18 +820,16 @@ impl<'d> embedded_io::Read for Usart<'d, Blocking> {
804 } 820 }
805} 821}
806 822
807struct Info { 823pub(crate) struct Info {
808 usart_reg: UsartReg, 824 pub(crate) usart_reg: UsartReg,
809 fc_reg: FlexcommReg, 825 pub(crate) fc_reg: FlexcommReg,
810 interrupt: Interrupt, 826 pub(crate) interrupt: Interrupt,
811} 827}
812 828
813trait SealedInstance { 829pub(crate) trait SealedInstance {
814 fn info() -> &'static Info; 830 fn info() -> &'static Info;
815 fn dma_state() -> &'static DmaState; 831 fn dma_state() -> &'static DmaState;
816 fn instance_number() -> usize; 832 fn instance_number() -> usize;
817 fn tx_pin_func() -> PioFunc;
818 fn rx_pin_func() -> PioFunc;
819} 833}
820 834
821/// UART instance. 835/// UART instance.
@@ -825,10 +839,13 @@ pub trait Instance: SealedInstance + PeripheralType {
825 type Interrupt: crate::interrupt::typelevel::Interrupt; 839 type Interrupt: crate::interrupt::typelevel::Interrupt;
826} 840}
827 841
828macro_rules! impl_instance { 842macro_rules! impl_usart_instance {
829 ($inst:ident, $fc:ident, $tx_pin:ident, $rx_pin:ident, $fc_num:expr) => { 843 ($inst:ident, $fc:ident, $fc_num:expr) => {
830 impl $crate::usart::inner::SealedInstance for $crate::peripherals::$inst { 844 impl crate::usart::SealedInstance for $crate::peripherals::$inst {
831 fn info() -> &'static Info { 845 fn info() -> &'static crate::usart::Info {
846 use crate::interrupt::typelevel::Interrupt;
847 use crate::usart::Info;
848
832 static INFO: Info = Info { 849 static INFO: Info = Info {
833 usart_reg: crate::pac::$inst, 850 usart_reg: crate::pac::$inst,
834 fc_reg: crate::pac::$fc, 851 fc_reg: crate::pac::$fc,
@@ -837,7 +854,13 @@ macro_rules! impl_instance {
837 &INFO 854 &INFO
838 } 855 }
839 856
840 fn dma_state() -> &'static DmaState { 857 fn dma_state() -> &'static crate::usart::DmaState {
858 use core::sync::atomic::AtomicBool;
859
860 use embassy_sync::waitqueue::AtomicWaker;
861
862 use crate::usart::DmaState;
863
841 static STATE: DmaState = DmaState { 864 static STATE: DmaState = DmaState {
842 rx_err_waker: AtomicWaker::new(), 865 rx_err_waker: AtomicWaker::new(),
843 rx_err: AtomicBool::new(false), 866 rx_err: AtomicBool::new(false),
@@ -848,14 +871,6 @@ macro_rules! impl_instance {
848 fn instance_number() -> usize { 871 fn instance_number() -> usize {
849 $fc_num 872 $fc_num
850 } 873 }
851 #[inline]
852 fn tx_pin_func() -> PioFunc {
853 PioFunc::$tx_pin
854 }
855 #[inline]
856 fn rx_pin_func() -> PioFunc {
857 PioFunc::$rx_pin
858 }
859 } 874 }
860 impl $crate::usart::Instance for $crate::peripherals::$inst { 875 impl $crate::usart::Instance for $crate::peripherals::$inst {
861 type Interrupt = crate::interrupt::typelevel::$fc; 876 type Interrupt = crate::interrupt::typelevel::$fc;
@@ -863,73 +878,62 @@ macro_rules! impl_instance {
863 }; 878 };
864} 879}
865 880
866impl_instance!(USART0, FLEXCOMM0, ALT1, ALT1, 0); 881pub(crate) trait SealedTxPin<T: Instance>: crate::gpio::Pin {
867impl_instance!(USART1, FLEXCOMM1, ALT2, ALT2, 1); 882 fn pin_func(&self) -> PioFunc;
868impl_instance!(USART2, FLEXCOMM2, ALT1, ALT1, 2); 883}
869impl_instance!(USART3, FLEXCOMM3, ALT1, ALT1, 3); 884
870impl_instance!(USART4, FLEXCOMM4, ALT1, ALT2, 4); 885pub(crate) trait SealedRxPin<T: Instance>: crate::gpio::Pin {
871impl_instance!(USART5, FLEXCOMM5, ALT3, ALT3, 5); 886 fn pin_func(&self) -> PioFunc;
872impl_instance!(USART6, FLEXCOMM6, ALT2, ALT2, 6); 887}
873impl_instance!(USART7, FLEXCOMM7, ALT7, ALT7, 7);
874 888
875/// Trait for TX pins. 889/// Trait for TX pins.
876pub trait TxPin<T: Instance>: crate::gpio::Pin {} 890#[allow(private_bounds)]
891pub trait TxPin<T: Instance>: SealedTxPin<T> + crate::gpio::Pin {}
892
877/// Trait for RX pins. 893/// Trait for RX pins.
878pub trait RxPin<T: Instance>: crate::gpio::Pin {} 894#[allow(private_bounds)]
895pub trait RxPin<T: Instance>: SealedRxPin<T> + crate::gpio::Pin {}
896
897macro_rules! impl_usart_txd_pin {
898 ($pin:ident, $instance:ident, $func: ident) => {
899 impl crate::usart::SealedTxPin<crate::peripherals::$instance> for crate::peripherals::$pin {
900 fn pin_func(&self) -> crate::pac::iocon::vals::PioFunc {
901 use crate::pac::iocon::vals::PioFunc;
902 PioFunc::$func
903 }
904 }
879 905
880macro_rules! impl_pin { 906 impl crate::usart::TxPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
881 ($pin:ident, $instance:ident, Tx) => {
882 impl TxPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
883 }; 907 };
884 ($pin:ident, $instance:ident, Rx) => { 908}
885 impl RxPin<crate::peripherals::$instance> for crate::peripherals::$pin {} 909
910macro_rules! impl_usart_rxd_pin {
911 ($pin:ident, $instance:ident, $func: ident) => {
912 impl crate::usart::SealedRxPin<crate::peripherals::$instance> for crate::peripherals::$pin {
913 fn pin_func(&self) -> crate::pac::iocon::vals::PioFunc {
914 use crate::pac::iocon::vals::PioFunc;
915 PioFunc::$func
916 }
917 }
918
919 impl crate::usart::RxPin<crate::peripherals::$instance> for crate::peripherals::$pin {}
886 }; 920 };
887} 921}
888 922
889impl_pin!(PIO1_6, USART0, Tx); 923/// Marker trait indicating a DMA channel may be used for USART transmit.
890impl_pin!(PIO1_5, USART0, Rx);
891impl_pin!(PIO1_11, USART1, Tx);
892impl_pin!(PIO1_10, USART1, Rx);
893impl_pin!(PIO0_27, USART2, Tx);
894impl_pin!(PIO1_24, USART2, Rx);
895impl_pin!(PIO0_2, USART3, Tx);
896impl_pin!(PIO0_3, USART3, Rx);
897impl_pin!(PIO0_16, USART4, Tx);
898impl_pin!(PIO0_5, USART4, Rx);
899impl_pin!(PIO0_9, USART5, Tx);
900impl_pin!(PIO0_8, USART5, Rx);
901impl_pin!(PIO1_16, USART6, Tx);
902impl_pin!(PIO1_13, USART6, Rx);
903impl_pin!(PIO0_19, USART7, Tx);
904impl_pin!(PIO0_20, USART7, Rx);
905
906/// Trait for TX DMA channels.
907pub trait TxChannel<T: Instance>: crate::dma::Channel {} 924pub trait TxChannel<T: Instance>: crate::dma::Channel {}
908/// Trait for RX DMA channels. 925
926/// Marker trait indicating a DMA channel may be used for USART recieve.
909pub trait RxChannel<T: Instance>: crate::dma::Channel {} 927pub trait RxChannel<T: Instance>: crate::dma::Channel {}
910 928
911macro_rules! impl_channel { 929macro_rules! impl_usart_tx_channel {
912 ($dma:ident, $instance:ident, Tx) => { 930 ($instance: ident, $channel: ident) => {
913 impl TxChannel<crate::peripherals::$instance> for crate::peripherals::$dma {} 931 impl crate::usart::TxChannel<crate::peripherals::$instance> for crate::peripherals::$channel {}
914 };
915 ($dma:ident, $instance:ident, Rx) => {
916 impl RxChannel<crate::peripherals::$instance> for crate::peripherals::$dma {}
917 }; 932 };
918} 933}
919 934
920impl_channel!(DMA_CH4, USART0, Rx); 935macro_rules! impl_usart_rx_channel {
921impl_channel!(DMA_CH5, USART0, Tx); 936 ($instance: ident, $channel: ident) => {
922impl_channel!(DMA_CH6, USART1, Rx); 937 impl crate::usart::RxChannel<crate::peripherals::$instance> for crate::peripherals::$channel {}
923impl_channel!(DMA_CH7, USART1, Tx); 938 };
924impl_channel!(DMA_CH10, USART2, Rx); 939}
925impl_channel!(DMA_CH11, USART2, Tx);
926impl_channel!(DMA_CH8, USART3, Rx);
927impl_channel!(DMA_CH9, USART3, Tx);
928impl_channel!(DMA_CH12, USART4, Rx);
929impl_channel!(DMA_CH13, USART4, Tx);
930impl_channel!(DMA_CH14, USART5, Rx);
931impl_channel!(DMA_CH15, USART5, Tx);
932impl_channel!(DMA_CH16, USART6, Rx);
933impl_channel!(DMA_CH17, USART6, Tx);
934impl_channel!(DMA_CH18, USART7, Rx);
935impl_channel!(DMA_CH19, USART7, Tx);