diff options
| author | JanKomarekNXP <[email protected]> | 2025-12-01 18:07:58 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-01 18:07:58 +0100 |
| commit | 717346f21a4cf4993c2a1f046e26b6bf647d89cb (patch) | |
| tree | 81dcbf726769eac5726796b340542d661debe407 /src/lpuart/mod.rs | |
| parent | 3b239cb6de22b7bb8c2d87defb3205294653be7a (diff) | |
Refactor LPUART driver constructors (#51)
* Refactor LPUART driver constructors
- Add new_with_rtscts(), new_with_rts(), new_with_cts() methods
- Store RTS/CTS pins in TX/RX structs
- Remove enable_tx, enable_rx, enable_rx_rts, enable_tx_cts config fields
- Fix typo: msb_firs -> msb_first
- Fix write_byte() return type to Result<()>
* Update hello example for LPUART driver changes
* Refactor buffered LPUART initialization logic
- Split new_inner() into init_common() and separate helpers for full-duplex, TX-only, and RX-only
- Replace assert!() with proper Error::InvalidArgument returns for empty buffers
- Simplify constructor implementations by removing expect() calls
Diffstat (limited to 'src/lpuart/mod.rs')
| -rw-r--r-- | src/lpuart/mod.rs | 141 |
1 files changed, 96 insertions, 45 deletions
diff --git a/src/lpuart/mod.rs b/src/lpuart/mod.rs index 317274a79..2d8308ec8 100644 --- a/src/lpuart/mod.rs +++ b/src/lpuart/mod.rs | |||
| @@ -203,8 +203,8 @@ pub fn clear_all_status_flags(regs: Regs) { | |||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | /// Configure hardware flow control if enabled | 205 | /// Configure hardware flow control if enabled |
| 206 | pub fn configure_flow_control(regs: Regs, config: &Config) { | 206 | pub fn configure_flow_control(regs: Regs, enable_tx_cts: bool, enable_rx_rts: bool, config: &Config) { |
| 207 | if config.enable_rx_rts || config.enable_tx_cts { | 207 | if enable_rx_rts || enable_tx_cts { |
| 208 | regs.modir().modify(|_, w| { | 208 | regs.modir().modify(|_, w| { |
| 209 | let mut w = w; | 209 | let mut w = w; |
| 210 | 210 | ||
| @@ -212,13 +212,13 @@ pub fn configure_flow_control(regs: Regs, config: &Config) { | |||
| 212 | w = w.txctsc().variant(config.tx_cts_config); | 212 | w = w.txctsc().variant(config.tx_cts_config); |
| 213 | w = w.txctssrc().variant(config.tx_cts_source); | 213 | w = w.txctssrc().variant(config.tx_cts_source); |
| 214 | 214 | ||
| 215 | if config.enable_rx_rts { | 215 | if enable_rx_rts { |
| 216 | w = w.rxrtse().enabled(); | 216 | w = w.rxrtse().enabled(); |
| 217 | } else { | 217 | } else { |
| 218 | w = w.rxrtse().disabled(); | 218 | w = w.rxrtse().disabled(); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | if config.enable_tx_cts { | 221 | if enable_tx_cts { |
| 222 | w = w.txctse().enabled(); | 222 | w = w.txctse().enabled(); |
| 223 | } else { | 223 | } else { |
| 224 | w = w.txctse().disabled(); | 224 | w = w.txctse().disabled(); |
| @@ -586,17 +586,13 @@ pub struct Config { | |||
| 586 | /// Number of data bits | 586 | /// Number of data bits |
| 587 | pub data_bits_count: DataBits, | 587 | pub data_bits_count: DataBits, |
| 588 | /// MSB First or LSB First configuration | 588 | /// MSB First or LSB First configuration |
| 589 | pub msb_firs: MsbFirst, | 589 | pub msb_first: MsbFirst, |
| 590 | /// Number of stop bits | 590 | /// Number of stop bits |
| 591 | pub stop_bits_count: StopBits, | 591 | pub stop_bits_count: StopBits, |
| 592 | /// TX FIFO watermark | 592 | /// TX FIFO watermark |
| 593 | pub tx_fifo_watermark: u8, | 593 | pub tx_fifo_watermark: u8, |
| 594 | /// RX FIFO watermark | 594 | /// RX FIFO watermark |
| 595 | pub rx_fifo_watermark: u8, | 595 | pub rx_fifo_watermark: u8, |
| 596 | /// RX RTS enable | ||
| 597 | pub enable_rx_rts: bool, | ||
| 598 | /// TX CTS enable | ||
| 599 | pub enable_tx_cts: bool, | ||
| 600 | /// TX CTS source | 596 | /// TX CTS source |
| 601 | pub tx_cts_source: TxCtsSource, | 597 | pub tx_cts_source: TxCtsSource, |
| 602 | /// TX CTS configure | 598 | /// TX CTS configure |
| @@ -605,10 +601,6 @@ pub struct Config { | |||
| 605 | pub rx_idle_type: IdleType, | 601 | pub rx_idle_type: IdleType, |
| 606 | /// RX IDLE configuration | 602 | /// RX IDLE configuration |
| 607 | pub rx_idle_config: IdleConfig, | 603 | pub rx_idle_config: IdleConfig, |
| 608 | /// Enable transmitter | ||
| 609 | pub enable_tx: bool, | ||
| 610 | /// Enable receiver | ||
| 611 | pub enable_rx: bool, | ||
| 612 | /// Swap TXD and RXD pins | 604 | /// Swap TXD and RXD pins |
| 613 | pub swap_txd_rxd: bool, | 605 | pub swap_txd_rxd: bool, |
| 614 | } | 606 | } |
| @@ -619,18 +611,14 @@ impl Default for Config { | |||
| 619 | baudrate_bps: 115_200u32, | 611 | baudrate_bps: 115_200u32, |
| 620 | parity_mode: None, | 612 | parity_mode: None, |
| 621 | data_bits_count: DataBits::Data8, | 613 | data_bits_count: DataBits::Data8, |
| 622 | msb_firs: MsbFirst::LsbFirst, | 614 | msb_first: MsbFirst::LsbFirst, |
| 623 | stop_bits_count: StopBits::One, | 615 | stop_bits_count: StopBits::One, |
| 624 | tx_fifo_watermark: 0, | 616 | tx_fifo_watermark: 0, |
| 625 | rx_fifo_watermark: 1, | 617 | rx_fifo_watermark: 1, |
| 626 | enable_rx_rts: false, | ||
| 627 | enable_tx_cts: false, | ||
| 628 | tx_cts_source: TxCtsSource::Cts, | 618 | tx_cts_source: TxCtsSource::Cts, |
| 629 | tx_cts_config: TxCtsConfig::Start, | 619 | tx_cts_config: TxCtsConfig::Start, |
| 630 | rx_idle_type: IdleType::FromStart, | 620 | rx_idle_type: IdleType::FromStart, |
| 631 | rx_idle_config: IdleConfig::Idle1, | 621 | rx_idle_config: IdleConfig::Idle1, |
| 632 | enable_tx: false, | ||
| 633 | enable_rx: false, | ||
| 634 | swap_txd_rxd: false, | 622 | swap_txd_rxd: false, |
| 635 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | 623 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 636 | source: LpuartClockSel::FroLfDiv, | 624 | source: LpuartClockSel::FroLfDiv, |
| @@ -694,6 +682,7 @@ pub struct Lpuart<'a, M: Mode> { | |||
| 694 | pub struct LpuartTx<'a, M: Mode> { | 682 | pub struct LpuartTx<'a, M: Mode> { |
| 695 | info: Info, | 683 | info: Info, |
| 696 | _tx_pin: Peri<'a, AnyPin>, | 684 | _tx_pin: Peri<'a, AnyPin>, |
| 685 | _cts_pin: Option<Peri<'a, AnyPin>>, | ||
| 697 | _tx_dma: Option<Channel<'a>>, | 686 | _tx_dma: Option<Channel<'a>>, |
| 698 | mode: PhantomData<(&'a (), M)>, | 687 | mode: PhantomData<(&'a (), M)>, |
| 699 | } | 688 | } |
| @@ -702,6 +691,7 @@ pub struct LpuartTx<'a, M: Mode> { | |||
| 702 | pub struct LpuartRx<'a, M: Mode> { | 691 | pub struct LpuartRx<'a, M: Mode> { |
| 703 | info: Info, | 692 | info: Info, |
| 704 | _rx_pin: Peri<'a, AnyPin>, | 693 | _rx_pin: Peri<'a, AnyPin>, |
| 694 | _rts_pin: Option<Peri<'a, AnyPin>>, | ||
| 705 | _rx_dma: Option<Channel<'a>>, | 695 | _rx_dma: Option<Channel<'a>>, |
| 706 | mode: PhantomData<(&'a (), M)>, | 696 | mode: PhantomData<(&'a (), M)>, |
| 707 | } | 697 | } |
| @@ -712,10 +702,10 @@ pub struct LpuartRx<'a, M: Mode> { | |||
| 712 | 702 | ||
| 713 | impl<'a, M: Mode> Lpuart<'a, M> { | 703 | impl<'a, M: Mode> Lpuart<'a, M> { |
| 714 | fn init<T: Instance>( | 704 | fn init<T: Instance>( |
| 715 | _tx: Option<&Peri<'a, AnyPin>>, | 705 | enable_tx: bool, |
| 716 | _rx: Option<&Peri<'a, AnyPin>>, | 706 | enable_rx: bool, |
| 717 | _rts: Option<&Peri<'a, AnyPin>>, | 707 | enable_tx_cts: bool, |
| 718 | _cts: Option<&Peri<'a, AnyPin>>, | 708 | enable_rx_rts: bool, |
| 719 | config: Config, | 709 | config: Config, |
| 720 | ) -> Result<()> { | 710 | ) -> Result<()> { |
| 721 | let regs = T::info().regs; | 711 | let regs = T::info().regs; |
| @@ -737,9 +727,9 @@ impl<'a, M: Mode> Lpuart<'a, M> { | |||
| 737 | configure_control_settings(regs, &config); | 727 | configure_control_settings(regs, &config); |
| 738 | configure_fifo(regs, &config); | 728 | configure_fifo(regs, &config); |
| 739 | clear_all_status_flags(regs); | 729 | clear_all_status_flags(regs); |
| 740 | configure_flow_control(regs, &config); | 730 | configure_flow_control(regs, enable_tx_cts, enable_rx_rts, &config); |
| 741 | configure_bit_order(regs, config.msb_firs); | 731 | configure_bit_order(regs, config.msb_first); |
| 742 | enable_transceiver(regs, config.enable_tx, config.enable_rx); | 732 | enable_transceiver(regs, enable_rx, enable_tx); |
| 743 | 733 | ||
| 744 | Ok(()) | 734 | Ok(()) |
| 745 | } | 735 | } |
| @@ -776,7 +766,7 @@ impl<'a, M: Mode> Lpuart<'a, M> { | |||
| 776 | // ============================================================================ | 766 | // ============================================================================ |
| 777 | 767 | ||
| 778 | impl<'a> Lpuart<'a, Blocking> { | 768 | impl<'a> Lpuart<'a, Blocking> { |
| 779 | /// Create a new blocking LPUART instance with TX and RX pins. | 769 | /// Create a new blocking LPUART instance with RX/TX pins. |
| 780 | pub fn new_blocking<T: Instance>( | 770 | pub fn new_blocking<T: Instance>( |
| 781 | _inner: Peri<'a, T>, | 771 | _inner: Peri<'a, T>, |
| 782 | tx_pin: Peri<'a, impl TxPin<T>>, | 772 | tx_pin: Peri<'a, impl TxPin<T>>, |
| @@ -787,17 +777,38 @@ impl<'a> Lpuart<'a, Blocking> { | |||
| 787 | tx_pin.as_tx(); | 777 | tx_pin.as_tx(); |
| 788 | rx_pin.as_rx(); | 778 | rx_pin.as_rx(); |
| 789 | 779 | ||
| 790 | // Convert pins to AnyPin | ||
| 791 | let tx_pin: Peri<'a, AnyPin> = tx_pin.into(); | ||
| 792 | let rx_pin: Peri<'a, AnyPin> = rx_pin.into(); | ||
| 793 | |||
| 794 | // Initialize the peripheral | 780 | // Initialize the peripheral |
| 795 | Self::init::<T>(Some(&tx_pin), Some(&rx_pin), None, None, config)?; | 781 | Self::init::<T>(true, true, false, false, config)?; |
| 796 | 782 | ||
| 797 | Ok(Self { | 783 | Ok(Self { |
| 798 | info: T::info(), | 784 | info: T::info(), |
| 799 | tx: LpuartTx::new_inner(T::info(), tx_pin, None), | 785 | tx: LpuartTx::new_inner(T::info(), tx_pin.into(), None, None), |
| 800 | rx: LpuartRx::new_inner(T::info(), rx_pin, None), | 786 | rx: LpuartRx::new_inner(T::info(), rx_pin.into(), None, None), |
| 787 | }) | ||
| 788 | } | ||
| 789 | |||
| 790 | /// Create a new blocking LPUART instance with RX, TX and RTS/CTS flow control pins | ||
| 791 | pub fn new_blocking_with_rtscts<T: Instance>( | ||
| 792 | _inner: Peri<'a, T>, | ||
| 793 | tx_pin: Peri<'a, impl TxPin<T>>, | ||
| 794 | rx_pin: Peri<'a, impl RxPin<T>>, | ||
| 795 | cts_pin: Peri<'a, impl CtsPin<T>>, | ||
| 796 | rts_pin: Peri<'a, impl RtsPin<T>>, | ||
| 797 | config: Config, | ||
| 798 | ) -> Result<Self> { | ||
| 799 | // Configure the pins for LPUART usage | ||
| 800 | rx_pin.as_rx(); | ||
| 801 | tx_pin.as_tx(); | ||
| 802 | rts_pin.as_rts(); | ||
| 803 | cts_pin.as_cts(); | ||
| 804 | |||
| 805 | // Initialize the peripheral with flow control | ||
| 806 | Self::init::<T>(true, true, true, true, config)?; | ||
| 807 | |||
| 808 | Ok(Self { | ||
| 809 | info: T::info(), | ||
| 810 | rx: LpuartRx::new_inner(T::info(), rx_pin.into(), Some(rts_pin.into()), None), | ||
| 811 | tx: LpuartTx::new_inner(T::info(), tx_pin.into(), Some(cts_pin.into()), None), | ||
| 801 | }) | 812 | }) |
| 802 | } | 813 | } |
| 803 | } | 814 | } |
| @@ -807,10 +818,16 @@ impl<'a> Lpuart<'a, Blocking> { | |||
| 807 | // ---------------------------------------------------------------------------- | 818 | // ---------------------------------------------------------------------------- |
| 808 | 819 | ||
| 809 | impl<'a, M: Mode> LpuartTx<'a, M> { | 820 | impl<'a, M: Mode> LpuartTx<'a, M> { |
| 810 | fn new_inner(info: Info, tx_pin: Peri<'a, AnyPin>, tx_dma: Option<Channel<'a>>) -> Self { | 821 | fn new_inner( |
| 822 | info: Info, | ||
| 823 | tx_pin: Peri<'a, AnyPin>, | ||
| 824 | cts_pin: Option<Peri<'a, AnyPin>>, | ||
| 825 | tx_dma: Option<Channel<'a>>, | ||
| 826 | ) -> Self { | ||
| 811 | Self { | 827 | Self { |
| 812 | info, | 828 | info, |
| 813 | _tx_pin: tx_pin, | 829 | _tx_pin: tx_pin, |
| 830 | _cts_pin: cts_pin, | ||
| 814 | _tx_dma: tx_dma, | 831 | _tx_dma: tx_dma, |
| 815 | mode: PhantomData, | 832 | mode: PhantomData, |
| 816 | } | 833 | } |
| @@ -818,19 +835,34 @@ impl<'a, M: Mode> LpuartTx<'a, M> { | |||
| 818 | } | 835 | } |
| 819 | 836 | ||
| 820 | impl<'a> LpuartTx<'a, Blocking> { | 837 | impl<'a> LpuartTx<'a, Blocking> { |
| 821 | /// Create a new blocking LPUART which can only send data. | 838 | /// Create a new blocking LPUART transmitter instance |
| 822 | pub fn new_blocking<T: Instance>( | 839 | pub fn new_blocking<T: Instance>( |
| 823 | _inner: Peri<'a, T>, | 840 | _inner: Peri<'a, T>, |
| 824 | tx_pin: Peri<'a, impl TxPin<T>>, | 841 | tx_pin: Peri<'a, impl TxPin<T>>, |
| 825 | config: Config, | 842 | config: Config, |
| 826 | ) -> Result<Self> { | 843 | ) -> Result<Self> { |
| 844 | // Configure the pins for LPUART usage | ||
| 827 | tx_pin.as_tx(); | 845 | tx_pin.as_tx(); |
| 828 | 846 | ||
| 829 | let tx_pin: Peri<'a, AnyPin> = tx_pin.into(); | 847 | // Initialize the peripheral |
| 848 | Lpuart::<Blocking>::init::<T>(true, false, false, false, config)?; | ||
| 849 | |||
| 850 | Ok(Self::new_inner(T::info(), tx_pin.into(), None, None)) | ||
| 851 | } | ||
| 852 | |||
| 853 | /// Create a new blocking LPUART transmitter instance with CTS flow control | ||
| 854 | pub fn new_blocking_with_cts<T: Instance>( | ||
| 855 | _inner: Peri<'a, T>, | ||
| 856 | tx_pin: Peri<'a, impl TxPin<T>>, | ||
| 857 | cts_pin: Peri<'a, impl CtsPin<T>>, | ||
| 858 | config: Config, | ||
| 859 | ) -> Result<Self> { | ||
| 860 | tx_pin.as_tx(); | ||
| 861 | cts_pin.as_cts(); | ||
| 830 | 862 | ||
| 831 | Lpuart::<Blocking>::init::<T>(Some(&tx_pin), None, None, None, config)?; | 863 | Lpuart::<Blocking>::init::<T>(true, false, true, false, config)?; |
| 832 | 864 | ||
| 833 | Ok(Self::new_inner(T::info(), tx_pin, None)) | 865 | Ok(Self::new_inner(T::info(), tx_pin.into(), Some(cts_pin.into()), None)) |
| 834 | } | 866 | } |
| 835 | 867 | ||
| 836 | fn write_byte_internal(&mut self, byte: u8) -> Result<()> { | 868 | fn write_byte_internal(&mut self, byte: u8) -> Result<()> { |
| @@ -909,10 +941,16 @@ impl<'a> LpuartTx<'a, Blocking> { | |||
| 909 | // ---------------------------------------------------------------------------- | 941 | // ---------------------------------------------------------------------------- |
| 910 | 942 | ||
| 911 | impl<'a, M: Mode> LpuartRx<'a, M> { | 943 | impl<'a, M: Mode> LpuartRx<'a, M> { |
| 912 | fn new_inner(info: Info, rx_pin: Peri<'a, AnyPin>, rx_dma: Option<Channel<'a>>) -> Self { | 944 | fn new_inner( |
| 945 | info: Info, | ||
| 946 | rx_pin: Peri<'a, AnyPin>, | ||
| 947 | rts_pin: Option<Peri<'a, AnyPin>>, | ||
| 948 | rx_dma: Option<Channel<'a>>, | ||
| 949 | ) -> Self { | ||
| 913 | Self { | 950 | Self { |
| 914 | info, | 951 | info, |
| 915 | _rx_pin: rx_pin, | 952 | _rx_pin: rx_pin, |
| 953 | _rts_pin: rts_pin, | ||
| 916 | _rx_dma: rx_dma, | 954 | _rx_dma: rx_dma, |
| 917 | mode: PhantomData, | 955 | mode: PhantomData, |
| 918 | } | 956 | } |
| @@ -920,7 +958,7 @@ impl<'a, M: Mode> LpuartRx<'a, M> { | |||
| 920 | } | 958 | } |
| 921 | 959 | ||
| 922 | impl<'a> LpuartRx<'a, Blocking> { | 960 | impl<'a> LpuartRx<'a, Blocking> { |
| 923 | /// Create a new blocking LPUART which can only receive data. | 961 | /// Create a new blocking LPUART Receiver instance |
| 924 | pub fn new_blocking<T: Instance>( | 962 | pub fn new_blocking<T: Instance>( |
| 925 | _inner: Peri<'a, T>, | 963 | _inner: Peri<'a, T>, |
| 926 | rx_pin: Peri<'a, impl RxPin<T>>, | 964 | rx_pin: Peri<'a, impl RxPin<T>>, |
| @@ -928,11 +966,24 @@ impl<'a> LpuartRx<'a, Blocking> { | |||
| 928 | ) -> Result<Self> { | 966 | ) -> Result<Self> { |
| 929 | rx_pin.as_rx(); | 967 | rx_pin.as_rx(); |
| 930 | 968 | ||
| 931 | let rx_pin: Peri<'a, AnyPin> = rx_pin.into(); | 969 | Lpuart::<Blocking>::init::<T>(false, true, false, false, config)?; |
| 970 | |||
| 971 | Ok(Self::new_inner(T::info(), rx_pin.into(), None, None)) | ||
| 972 | } | ||
| 973 | |||
| 974 | /// Create a new blocking LPUART Receiver instance with RTS flow control | ||
| 975 | pub fn new_blocking_with_rts<T: Instance>( | ||
| 976 | _inner: Peri<'a, T>, | ||
| 977 | rx_pin: Peri<'a, impl RxPin<T>>, | ||
| 978 | rts_pin: Peri<'a, impl RtsPin<T>>, | ||
| 979 | config: Config, | ||
| 980 | ) -> Result<Self> { | ||
| 981 | rx_pin.as_rx(); | ||
| 982 | rts_pin.as_rts(); | ||
| 932 | 983 | ||
| 933 | Lpuart::<Blocking>::init::<T>(None, Some(&rx_pin), None, None, config)?; | 984 | Lpuart::<Blocking>::init::<T>(false, true, false, true, config)?; |
| 934 | 985 | ||
| 935 | Ok(Self::new_inner(T::info(), rx_pin, None)) | 986 | Ok(Self::new_inner(T::info(), rx_pin.into(), Some(rts_pin.into()), None)) |
| 936 | } | 987 | } |
| 937 | 988 | ||
| 938 | fn read_byte_internal(&mut self) -> Result<u8> { | 989 | fn read_byte_internal(&mut self) -> Result<u8> { |
| @@ -994,8 +1045,8 @@ impl<'a> Lpuart<'a, Blocking> { | |||
| 994 | self.tx.blocking_write(buf) | 1045 | self.tx.blocking_write(buf) |
| 995 | } | 1046 | } |
| 996 | 1047 | ||
| 997 | pub fn write_byte(&mut self, byte: u8) { | 1048 | pub fn write_byte(&mut self, byte: u8) -> Result<()> { |
| 998 | _ = self.tx.write_byte(byte); | 1049 | self.tx.write_byte(byte) |
| 999 | } | 1050 | } |
| 1000 | 1051 | ||
| 1001 | pub fn read_byte_blocking(&mut self) -> u8 { | 1052 | pub fn read_byte_blocking(&mut self) -> u8 { |
