diff options
| -rw-r--r-- | examples/src/bin/hello.rs | 14 | ||||
| -rw-r--r-- | examples/src/bin/lpuart_buffered.rs | 2 | ||||
| -rw-r--r-- | examples/src/bin/lpuart_polling.rs | 2 | ||||
| -rw-r--r-- | src/lpuart/buffered.rs | 505 | ||||
| -rw-r--r-- | src/lpuart/mod.rs | 141 |
5 files changed, 404 insertions, 260 deletions
diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs index f426d1898..e371d9413 100644 --- a/examples/src/bin/hello.rs +++ b/examples/src/bin/hello.rs | |||
| @@ -2,27 +2,29 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa::clocks::config::Div8; | ||
| 5 | use hal::lpuart::{Blocking, Config, Lpuart}; | 6 | use hal::lpuart::{Blocking, Config, Lpuart}; |
| 6 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 7 | 8 | ||
| 8 | /// Simple helper to write a byte as hex to UART | 9 | /// Simple helper to write a byte as hex to UART |
| 9 | fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { | 10 | fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { |
| 10 | const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; | 11 | const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; |
| 11 | uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); | 12 | let _ = uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); |
| 12 | uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); | 13 | let _ = uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); |
| 13 | } | 14 | } |
| 14 | 15 | ||
| 15 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) { | 17 | async fn main(_spawner: Spawner) { |
| 17 | let p = hal::init(hal::config::Config::default()); | 18 | let mut cfg = hal::config::Config::default(); |
| 19 | cfg.clock_cfg.sirc.fro_12m_enabled = true; | ||
| 20 | cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); | ||
| 21 | let p = hal::init(cfg); | ||
| 18 | 22 | ||
| 19 | defmt::info!("boot"); | 23 | defmt::info!("boot"); |
| 20 | 24 | ||
| 21 | // Create UART configuration | 25 | // Create UART configuration |
| 22 | let config = Config { | 26 | let config = Config { |
| 23 | baudrate_bps: 115_200, | 27 | baudrate_bps: 115_200, |
| 24 | enable_tx: true, | ||
| 25 | enable_rx: true, | ||
| 26 | ..Default::default() | 28 | ..Default::default() |
| 27 | }; | 29 | }; |
| 28 | 30 | ||
| @@ -97,7 +99,7 @@ async fn main(_spawner: Spawner) { | |||
| 97 | // Regular character | 99 | // Regular character |
| 98 | buffer[buf_idx] = byte; | 100 | buffer[buf_idx] = byte; |
| 99 | buf_idx += 1; | 101 | buf_idx += 1; |
| 100 | uart.write_byte(byte); | 102 | let _ = uart.write_byte(byte); |
| 101 | } | 103 | } |
| 102 | } | 104 | } |
| 103 | } | 105 | } |
diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs index 7f77d557d..420589d00 100644 --- a/examples/src/bin/lpuart_buffered.rs +++ b/examples/src/bin/lpuart_buffered.rs | |||
| @@ -27,8 +27,6 @@ async fn main(_spawner: Spawner) { | |||
| 27 | // UART configuration (enable both TX and RX) | 27 | // UART configuration (enable both TX and RX) |
| 28 | let config = Config { | 28 | let config = Config { |
| 29 | baudrate_bps: 115_200, | 29 | baudrate_bps: 115_200, |
| 30 | enable_tx: true, | ||
| 31 | enable_rx: true, | ||
| 32 | rx_fifo_watermark: 0, | 30 | rx_fifo_watermark: 0, |
| 33 | tx_fifo_watermark: 0, | 31 | tx_fifo_watermark: 0, |
| 34 | ..Default::default() | 32 | ..Default::default() |
diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs index 9cea418cc..b80668834 100644 --- a/examples/src/bin/lpuart_polling.rs +++ b/examples/src/bin/lpuart_polling.rs | |||
| @@ -19,8 +19,6 @@ async fn main(_spawner: Spawner) { | |||
| 19 | // Create UART configuration | 19 | // Create UART configuration |
| 20 | let config = Config { | 20 | let config = Config { |
| 21 | baudrate_bps: 115_200, | 21 | baudrate_bps: 115_200, |
| 22 | enable_tx: true, | ||
| 23 | enable_rx: true, | ||
| 24 | ..Default::default() | 22 | ..Default::default() |
| 25 | }; | 23 | }; |
| 26 | 24 | ||
diff --git a/src/lpuart/buffered.rs b/src/lpuart/buffered.rs index 6f41c33c9..8eb443ca7 100644 --- a/src/lpuart/buffered.rs +++ b/src/lpuart/buffered.rs | |||
| @@ -16,11 +16,11 @@ use crate::interrupt; | |||
| 16 | 16 | ||
| 17 | /// State for buffered LPUART operations | 17 | /// State for buffered LPUART operations |
| 18 | pub struct State { | 18 | pub struct State { |
| 19 | rx_waker: AtomicWaker, | ||
| 20 | rx_buf: RingBuffer, | ||
| 21 | tx_waker: AtomicWaker, | 19 | tx_waker: AtomicWaker, |
| 22 | tx_buf: RingBuffer, | 20 | tx_buf: RingBuffer, |
| 23 | tx_done: AtomicBool, | 21 | tx_done: AtomicBool, |
| 22 | rx_waker: AtomicWaker, | ||
| 23 | rx_buf: RingBuffer, | ||
| 24 | initialized: AtomicBool, | 24 | initialized: AtomicBool, |
| 25 | } | 25 | } |
| 26 | 26 | ||
| @@ -34,11 +34,11 @@ impl State { | |||
| 34 | /// Create a new state instance | 34 | /// Create a new state instance |
| 35 | pub const fn new() -> Self { | 35 | pub const fn new() -> Self { |
| 36 | Self { | 36 | Self { |
| 37 | rx_waker: AtomicWaker::new(), | ||
| 38 | rx_buf: RingBuffer::new(), | ||
| 39 | tx_waker: AtomicWaker::new(), | 37 | tx_waker: AtomicWaker::new(), |
| 40 | tx_buf: RingBuffer::new(), | 38 | tx_buf: RingBuffer::new(), |
| 41 | tx_done: AtomicBool::new(true), | 39 | tx_done: AtomicBool::new(true), |
| 40 | rx_waker: AtomicWaker::new(), | ||
| 41 | rx_buf: RingBuffer::new(), | ||
| 42 | initialized: AtomicBool::new(false), | 42 | initialized: AtomicBool::new(false), |
| 43 | } | 43 | } |
| 44 | } | 44 | } |
| @@ -58,6 +58,7 @@ pub struct BufferedLpuartTx<'a> { | |||
| 58 | info: Info, | 58 | info: Info, |
| 59 | state: &'static State, | 59 | state: &'static State, |
| 60 | _tx_pin: Peri<'a, AnyPin>, | 60 | _tx_pin: Peri<'a, AnyPin>, |
| 61 | _cts_pin: Option<Peri<'a, AnyPin>>, | ||
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | /// Buffered LPUART RX driver | 64 | /// Buffered LPUART RX driver |
| @@ -65,6 +66,7 @@ pub struct BufferedLpuartRx<'a> { | |||
| 65 | info: Info, | 66 | info: Info, |
| 66 | state: &'static State, | 67 | state: &'static State, |
| 67 | _rx_pin: Peri<'a, AnyPin>, | 68 | _rx_pin: Peri<'a, AnyPin>, |
| 69 | _rts_pin: Option<Peri<'a, AnyPin>>, | ||
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | // ============================================================================ | 72 | // ============================================================================ |
| @@ -72,143 +74,41 @@ pub struct BufferedLpuartRx<'a> { | |||
| 72 | // ============================================================================ | 74 | // ============================================================================ |
| 73 | 75 | ||
| 74 | impl<'a> BufferedLpuart<'a> { | 76 | impl<'a> BufferedLpuart<'a> { |
| 75 | /// Create a new buffered LPUART instance | 77 | /// Common initialization logic |
| 76 | pub fn new<T: Instance>( | 78 | fn init_common<T: Instance>( |
| 77 | _inner: Peri<'a, T>, | 79 | _inner: &Peri<'a, T>, |
| 78 | tx_pin: Peri<'a, impl TxPin<T>>, | 80 | tx_buffer: Option<&'a mut [u8]>, |
| 79 | rx_pin: Peri<'a, impl RxPin<T>>, | 81 | rx_buffer: Option<&'a mut [u8]>, |
| 80 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | 82 | config: &Config, |
| 81 | tx_buffer: &'a mut [u8], | 83 | enable_tx: bool, |
| 82 | rx_buffer: &'a mut [u8], | 84 | enable_rx: bool, |
| 83 | config: Config, | 85 | enable_rts: bool, |
| 84 | ) -> Result<Self> { | 86 | enable_cts: bool, |
| 85 | // Configure pins | 87 | ) -> Result<&'static State> { |
| 86 | tx_pin.as_tx(); | ||
| 87 | rx_pin.as_rx(); | ||
| 88 | |||
| 89 | // Convert pins to AnyPin | ||
| 90 | let tx_pin: Peri<'a, AnyPin> = tx_pin.into(); | ||
| 91 | let rx_pin: Peri<'a, AnyPin> = rx_pin.into(); | ||
| 92 | |||
| 93 | let state = T::buffered_state(); | ||
| 94 | |||
| 95 | // Initialize the peripheral | ||
| 96 | Self::init::<T>(Some(&tx_pin), Some(&rx_pin), None, None, tx_buffer, rx_buffer, config)?; | ||
| 97 | |||
| 98 | Ok(Self { | ||
| 99 | tx: BufferedLpuartTx { | ||
| 100 | info: T::info(), | ||
| 101 | state, | ||
| 102 | _tx_pin: tx_pin, | ||
| 103 | }, | ||
| 104 | rx: BufferedLpuartRx { | ||
| 105 | info: T::info(), | ||
| 106 | state, | ||
| 107 | _rx_pin: rx_pin, | ||
| 108 | }, | ||
| 109 | }) | ||
| 110 | } | ||
| 111 | |||
| 112 | /// Create a new buffered LPUART with flexible pin configuration | ||
| 113 | #[allow(clippy::too_many_arguments)] | ||
| 114 | pub fn new_with_pins<T: Instance>( | ||
| 115 | _inner: Peri<'a, T>, | ||
| 116 | tx_pin: Option<Peri<'a, impl TxPin<T>>>, | ||
| 117 | rx_pin: Option<Peri<'a, impl RxPin<T>>>, | ||
| 118 | rts_pin: Option<Peri<'a, impl RtsPin<T>>>, | ||
| 119 | cts_pin: Option<Peri<'a, impl CtsPin<T>>>, | ||
| 120 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | ||
| 121 | tx_buffer: &'a mut [u8], | ||
| 122 | rx_buffer: &'a mut [u8], | ||
| 123 | config: Config, | ||
| 124 | ) -> Result<Self> { | ||
| 125 | // Configure pins if provided | ||
| 126 | let tx_pin: Option<Peri<'a, AnyPin>> = tx_pin.map(|pin| { | ||
| 127 | pin.as_tx(); | ||
| 128 | pin.into() | ||
| 129 | }); | ||
| 130 | |||
| 131 | let rx_pin: Option<Peri<'a, AnyPin>> = rx_pin.map(|pin| { | ||
| 132 | pin.as_rx(); | ||
| 133 | pin.into() | ||
| 134 | }); | ||
| 135 | |||
| 136 | let rts_pin: Option<Peri<'a, AnyPin>> = rts_pin.map(|pin| { | ||
| 137 | pin.as_rts(); | ||
| 138 | pin.into() | ||
| 139 | }); | ||
| 140 | |||
| 141 | let cts_pin: Option<Peri<'a, AnyPin>> = cts_pin.map(|pin| { | ||
| 142 | pin.as_cts(); | ||
| 143 | pin.into() | ||
| 144 | }); | ||
| 145 | |||
| 146 | let state = T::buffered_state(); | 88 | let state = T::buffered_state(); |
| 147 | 89 | ||
| 148 | // Initialize the peripheral | ||
| 149 | Self::init::<T>( | ||
| 150 | tx_pin.as_ref(), | ||
| 151 | rx_pin.as_ref(), | ||
| 152 | rts_pin.as_ref(), | ||
| 153 | cts_pin.as_ref(), | ||
| 154 | tx_buffer, | ||
| 155 | rx_buffer, | ||
| 156 | config, | ||
| 157 | )?; | ||
| 158 | |||
| 159 | // Create TX and RX instances | ||
| 160 | let (tx, rx) = if let (Some(tx_pin), Some(rx_pin)) = (tx_pin, rx_pin) { | ||
| 161 | ( | ||
| 162 | BufferedLpuartTx { | ||
| 163 | info: T::info(), | ||
| 164 | state, | ||
| 165 | _tx_pin: tx_pin, | ||
| 166 | }, | ||
| 167 | BufferedLpuartRx { | ||
| 168 | info: T::info(), | ||
| 169 | state, | ||
| 170 | _rx_pin: rx_pin, | ||
| 171 | }, | ||
| 172 | ) | ||
| 173 | } else { | ||
| 174 | return Err(Error::InvalidArgument); | ||
| 175 | }; | ||
| 176 | |||
| 177 | Ok(Self { tx, rx }) | ||
| 178 | } | ||
| 179 | |||
| 180 | fn init<T: Instance>( | ||
| 181 | _tx: Option<&Peri<'a, AnyPin>>, | ||
| 182 | _rx: Option<&Peri<'a, AnyPin>>, | ||
| 183 | _rts: Option<&Peri<'a, AnyPin>>, | ||
| 184 | _cts: Option<&Peri<'a, AnyPin>>, | ||
| 185 | tx_buffer: &'a mut [u8], | ||
| 186 | rx_buffer: &'a mut [u8], | ||
| 187 | mut config: Config, | ||
| 188 | ) -> Result<()> { | ||
| 189 | let regs = T::info().regs; | ||
| 190 | let state = T::buffered_state(); | ||
| 191 | |||
| 192 | // Check if already initialized | ||
| 193 | if state.initialized.load(Ordering::Relaxed) { | 90 | if state.initialized.load(Ordering::Relaxed) { |
| 194 | return Err(Error::InvalidArgument); | 91 | return Err(Error::InvalidArgument); |
| 195 | } | 92 | } |
| 196 | 93 | ||
| 197 | // Initialize ring buffers | 94 | // Initialize buffers |
| 198 | assert!(!tx_buffer.is_empty()); | 95 | if let Some(tx_buffer) = tx_buffer { |
| 199 | unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), tx_buffer.len()) } | 96 | if tx_buffer.is_empty() { |
| 97 | return Err(Error::InvalidArgument); | ||
| 98 | } | ||
| 99 | unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), tx_buffer.len()) }; | ||
| 100 | } | ||
| 200 | 101 | ||
| 201 | assert!(!rx_buffer.is_empty()); | 102 | if let Some(rx_buffer) = rx_buffer { |
| 202 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), rx_buffer.len()) } | 103 | if rx_buffer.is_empty() { |
| 104 | return Err(Error::InvalidArgument); | ||
| 105 | } | ||
| 106 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), rx_buffer.len()) }; | ||
| 107 | } | ||
| 203 | 108 | ||
| 204 | // Mark as initialized | ||
| 205 | state.initialized.store(true, Ordering::Relaxed); | 109 | state.initialized.store(true, Ordering::Relaxed); |
| 206 | 110 | ||
| 207 | // Enable TX and RX for buffered operation | 111 | // Enable clocks and initialize hardware |
| 208 | config.enable_tx = true; | ||
| 209 | config.enable_rx = true; | ||
| 210 | |||
| 211 | // Enable clocks | ||
| 212 | let conf = LpuartConfig { | 112 | let conf = LpuartConfig { |
| 213 | power: config.power, | 113 | power: config.power, |
| 214 | source: config.source, | 114 | source: config.source, |
| @@ -217,6 +117,68 @@ impl<'a> BufferedLpuart<'a> { | |||
| 217 | }; | 117 | }; |
| 218 | let clock_freq = unsafe { enable_and_reset::<T>(&conf).map_err(Error::ClockSetup)? }; | 118 | let clock_freq = unsafe { enable_and_reset::<T>(&conf).map_err(Error::ClockSetup)? }; |
| 219 | 119 | ||
| 120 | Self::init_hardware( | ||
| 121 | T::info().regs, | ||
| 122 | *config, | ||
| 123 | clock_freq, | ||
| 124 | enable_tx, | ||
| 125 | enable_rx, | ||
| 126 | enable_rts, | ||
| 127 | enable_cts, | ||
| 128 | )?; | ||
| 129 | |||
| 130 | Ok(state) | ||
| 131 | } | ||
| 132 | |||
| 133 | /// Helper for full-duplex initialization | ||
| 134 | fn new_inner<T: Instance>( | ||
| 135 | inner: Peri<'a, T>, | ||
| 136 | tx_pin: Peri<'a, AnyPin>, | ||
| 137 | rx_pin: Peri<'a, AnyPin>, | ||
| 138 | rts_pin: Option<Peri<'a, AnyPin>>, | ||
| 139 | cts_pin: Option<Peri<'a, AnyPin>>, | ||
| 140 | tx_buffer: &'a mut [u8], | ||
| 141 | rx_buffer: &'a mut [u8], | ||
| 142 | config: Config, | ||
| 143 | ) -> Result<(BufferedLpuartTx<'a>, BufferedLpuartRx<'a>)> { | ||
| 144 | let state = Self::init_common::<T>( | ||
| 145 | &inner, | ||
| 146 | Some(tx_buffer), | ||
| 147 | Some(rx_buffer), | ||
| 148 | &config, | ||
| 149 | true, | ||
| 150 | true, | ||
| 151 | rts_pin.is_some(), | ||
| 152 | cts_pin.is_some(), | ||
| 153 | )?; | ||
| 154 | |||
| 155 | let tx = BufferedLpuartTx { | ||
| 156 | info: T::info(), | ||
| 157 | state, | ||
| 158 | _tx_pin: tx_pin, | ||
| 159 | _cts_pin: cts_pin, | ||
| 160 | }; | ||
| 161 | |||
| 162 | let rx = BufferedLpuartRx { | ||
| 163 | info: T::info(), | ||
| 164 | state, | ||
| 165 | _rx_pin: rx_pin, | ||
| 166 | _rts_pin: rts_pin, | ||
| 167 | }; | ||
| 168 | |||
| 169 | Ok((tx, rx)) | ||
| 170 | } | ||
| 171 | |||
| 172 | /// Common hardware initialization logic | ||
| 173 | fn init_hardware( | ||
| 174 | regs: &'static mcxa_pac::lpuart0::RegisterBlock, | ||
| 175 | config: Config, | ||
| 176 | clock_freq: u32, | ||
| 177 | enable_tx: bool, | ||
| 178 | enable_rx: bool, | ||
| 179 | enable_rts: bool, | ||
| 180 | enable_cts: bool, | ||
| 181 | ) -> Result<()> { | ||
| 220 | // Perform standard initialization | 182 | // Perform standard initialization |
| 221 | perform_software_reset(regs); | 183 | perform_software_reset(regs); |
| 222 | disable_transceiver(regs); | 184 | disable_transceiver(regs); |
| @@ -225,8 +187,8 @@ impl<'a> BufferedLpuart<'a> { | |||
| 225 | configure_control_settings(regs, &config); | 187 | configure_control_settings(regs, &config); |
| 226 | configure_fifo(regs, &config); | 188 | configure_fifo(regs, &config); |
| 227 | clear_all_status_flags(regs); | 189 | clear_all_status_flags(regs); |
| 228 | configure_flow_control(regs, &config); | 190 | configure_flow_control(regs, enable_rts, enable_cts, &config); |
| 229 | configure_bit_order(regs, config.msb_firs); | 191 | configure_bit_order(regs, config.msb_first); |
| 230 | 192 | ||
| 231 | // Enable interrupts for buffered operation | 193 | // Enable interrupts for buffered operation |
| 232 | cortex_m::interrupt::free(|_| { | 194 | cortex_m::interrupt::free(|_| { |
| @@ -245,17 +207,127 @@ impl<'a> BufferedLpuart<'a> { | |||
| 245 | }); | 207 | }); |
| 246 | 208 | ||
| 247 | // Enable the transceiver | 209 | // Enable the transceiver |
| 248 | enable_transceiver(regs, config.enable_tx, config.enable_rx); | 210 | enable_transceiver(regs, enable_rx, enable_tx); |
| 249 | |||
| 250 | // Enable the interrupt | ||
| 251 | // unsafe { | ||
| 252 | // // TODO: Used the propper interrupt enable method for the specific LPUART instance | ||
| 253 | // // T::Interrupt::enable(); | ||
| 254 | // } | ||
| 255 | 211 | ||
| 256 | Ok(()) | 212 | Ok(()) |
| 257 | } | 213 | } |
| 258 | 214 | ||
| 215 | /// Create a new full duplex buffered LPUART | ||
| 216 | pub fn new<T: Instance>( | ||
| 217 | inner: Peri<'a, T>, | ||
| 218 | tx_pin: Peri<'a, impl TxPin<T>>, | ||
| 219 | rx_pin: Peri<'a, impl RxPin<T>>, | ||
| 220 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | ||
| 221 | tx_buffer: &'a mut [u8], | ||
| 222 | rx_buffer: &'a mut [u8], | ||
| 223 | config: Config, | ||
| 224 | ) -> Result<Self> { | ||
| 225 | tx_pin.as_tx(); | ||
| 226 | rx_pin.as_rx(); | ||
| 227 | |||
| 228 | let (tx, rx) = Self::new_inner::<T>( | ||
| 229 | inner, | ||
| 230 | tx_pin.into(), | ||
| 231 | rx_pin.into(), | ||
| 232 | None, | ||
| 233 | None, | ||
| 234 | tx_buffer, | ||
| 235 | rx_buffer, | ||
| 236 | config, | ||
| 237 | )?; | ||
| 238 | |||
| 239 | Ok(Self { tx, rx }) | ||
| 240 | } | ||
| 241 | |||
| 242 | /// Create a new buffered LPUART instance with RTS/CTS flow control | ||
| 243 | pub fn new_with_rtscts<T: Instance>( | ||
| 244 | inner: Peri<'a, T>, | ||
| 245 | tx_pin: Peri<'a, impl TxPin<T>>, | ||
| 246 | rx_pin: Peri<'a, impl RxPin<T>>, | ||
| 247 | rts_pin: Peri<'a, impl RtsPin<T>>, | ||
| 248 | cts_pin: Peri<'a, impl CtsPin<T>>, | ||
| 249 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | ||
| 250 | tx_buffer: &'a mut [u8], | ||
| 251 | rx_buffer: &'a mut [u8], | ||
| 252 | config: Config, | ||
| 253 | ) -> Result<Self> { | ||
| 254 | tx_pin.as_tx(); | ||
| 255 | rx_pin.as_rx(); | ||
| 256 | rts_pin.as_rts(); | ||
| 257 | cts_pin.as_cts(); | ||
| 258 | |||
| 259 | let (tx, rx) = Self::new_inner::<T>( | ||
| 260 | inner, | ||
| 261 | tx_pin.into(), | ||
| 262 | rx_pin.into(), | ||
| 263 | Some(rts_pin.into()), | ||
| 264 | Some(cts_pin.into()), | ||
| 265 | tx_buffer, | ||
| 266 | rx_buffer, | ||
| 267 | config, | ||
| 268 | )?; | ||
| 269 | |||
| 270 | Ok(Self { tx, rx }) | ||
| 271 | } | ||
| 272 | |||
| 273 | /// Create a new buffered LPUART with only RTS flow control (RX flow control) | ||
| 274 | pub fn new_with_rts<T: Instance>( | ||
| 275 | inner: Peri<'a, T>, | ||
| 276 | tx_pin: Peri<'a, impl TxPin<T>>, | ||
| 277 | rx_pin: Peri<'a, impl RxPin<T>>, | ||
| 278 | rts_pin: Peri<'a, impl RtsPin<T>>, | ||
| 279 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | ||
| 280 | tx_buffer: &'a mut [u8], | ||
| 281 | rx_buffer: &'a mut [u8], | ||
| 282 | config: Config, | ||
| 283 | ) -> Result<Self> { | ||
| 284 | tx_pin.as_tx(); | ||
| 285 | rx_pin.as_rx(); | ||
| 286 | rts_pin.as_rts(); | ||
| 287 | |||
| 288 | let (tx, rx) = Self::new_inner::<T>( | ||
| 289 | inner, | ||
| 290 | tx_pin.into(), | ||
| 291 | rx_pin.into(), | ||
| 292 | Some(rts_pin.into()), | ||
| 293 | None, | ||
| 294 | tx_buffer, | ||
| 295 | rx_buffer, | ||
| 296 | config, | ||
| 297 | )?; | ||
| 298 | |||
| 299 | Ok(Self { tx, rx }) | ||
| 300 | } | ||
| 301 | |||
| 302 | /// Create a new buffered LPUART with only CTS flow control (TX flow control) | ||
| 303 | pub fn new_with_cts<T: Instance>( | ||
| 304 | inner: Peri<'a, T>, | ||
| 305 | tx_pin: Peri<'a, impl TxPin<T>>, | ||
| 306 | rx_pin: Peri<'a, impl RxPin<T>>, | ||
| 307 | cts_pin: Peri<'a, impl CtsPin<T>>, | ||
| 308 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | ||
| 309 | tx_buffer: &'a mut [u8], | ||
| 310 | rx_buffer: &'a mut [u8], | ||
| 311 | config: Config, | ||
| 312 | ) -> Result<Self> { | ||
| 313 | tx_pin.as_tx(); | ||
| 314 | rx_pin.as_rx(); | ||
| 315 | cts_pin.as_cts(); | ||
| 316 | |||
| 317 | let (tx, rx) = Self::new_inner::<T>( | ||
| 318 | inner, | ||
| 319 | tx_pin.into(), | ||
| 320 | rx_pin.into(), | ||
| 321 | None, | ||
| 322 | Some(cts_pin.into()), | ||
| 323 | tx_buffer, | ||
| 324 | rx_buffer, | ||
| 325 | config, | ||
| 326 | )?; | ||
| 327 | |||
| 328 | Ok(Self { tx, rx }) | ||
| 329 | } | ||
| 330 | |||
| 259 | /// Split the buffered LPUART into separate TX and RX parts | 331 | /// Split the buffered LPUART into separate TX and RX parts |
| 260 | pub fn split(self) -> (BufferedLpuartTx<'a>, BufferedLpuartRx<'a>) { | 332 | pub fn split(self) -> (BufferedLpuartTx<'a>, BufferedLpuartRx<'a>) { |
| 261 | (self.tx, self.rx) | 333 | (self.tx, self.rx) |
| @@ -272,51 +344,62 @@ impl<'a> BufferedLpuart<'a> { | |||
| 272 | // ============================================================================ | 344 | // ============================================================================ |
| 273 | 345 | ||
| 274 | impl<'a> BufferedLpuartTx<'a> { | 346 | impl<'a> BufferedLpuartTx<'a> { |
| 275 | /// Create a new TX-only buffered LPUART | 347 | /// Helper for TX-only initialization |
| 348 | fn new_inner<T: Instance>( | ||
| 349 | inner: Peri<'a, T>, | ||
| 350 | tx_pin: Peri<'a, AnyPin>, | ||
| 351 | cts_pin: Option<Peri<'a, AnyPin>>, | ||
| 352 | tx_buffer: &'a mut [u8], | ||
| 353 | config: Config, | ||
| 354 | ) -> Result<BufferedLpuartTx<'a>> { | ||
| 355 | let state = BufferedLpuart::init_common::<T>( | ||
| 356 | &inner, | ||
| 357 | Some(tx_buffer), | ||
| 358 | None, | ||
| 359 | &config, | ||
| 360 | true, | ||
| 361 | false, | ||
| 362 | false, | ||
| 363 | cts_pin.is_some(), | ||
| 364 | )?; | ||
| 365 | |||
| 366 | Ok(BufferedLpuartTx { | ||
| 367 | info: T::info(), | ||
| 368 | state, | ||
| 369 | _tx_pin: tx_pin, | ||
| 370 | _cts_pin: cts_pin, | ||
| 371 | }) | ||
| 372 | } | ||
| 373 | |||
| 276 | pub fn new<T: Instance>( | 374 | pub fn new<T: Instance>( |
| 277 | _inner: Peri<'a, T>, | 375 | inner: Peri<'a, T>, |
| 278 | tx_pin: Peri<'a, impl TxPin<T>>, | 376 | tx_pin: Peri<'a, impl TxPin<T>>, |
| 279 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | 377 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, |
| 280 | tx_buffer: &'a mut [u8], | 378 | tx_buffer: &'a mut [u8], |
| 281 | config: Config, | 379 | config: Config, |
| 282 | ) -> Result<Self> { | 380 | ) -> Result<Self> { |
| 283 | tx_pin.as_tx(); | 381 | tx_pin.as_tx(); |
| 284 | let tx_pin: Peri<'a, AnyPin> = tx_pin.into(); | ||
| 285 | |||
| 286 | let info = T::info(); | ||
| 287 | let state = T::buffered_state(); | ||
| 288 | |||
| 289 | // Check if already initialized | ||
| 290 | if state.initialized.load(Ordering::Relaxed) { | ||
| 291 | return Err(Error::InvalidArgument); | ||
| 292 | } | ||
| 293 | 382 | ||
| 294 | // Initialize TX ring buffer only | 383 | Self::new_inner::<T>(inner, tx_pin.into(), None, tx_buffer, config) |
| 295 | unsafe { | 384 | } |
| 296 | let tx_buf = &state.tx_buf as *const _ as *mut RingBuffer; | ||
| 297 | (*tx_buf).init(tx_buffer.as_mut_ptr(), tx_buffer.len()); | ||
| 298 | } | ||
| 299 | |||
| 300 | state.initialized.store(true, Ordering::Relaxed); | ||
| 301 | 385 | ||
| 302 | // Initialize with TX only | 386 | /// Create a new TX-only buffered LPUART with CTS flow control |
| 303 | BufferedLpuart::init::<T>( | 387 | pub fn new_with_cts<T: Instance>( |
| 304 | Some(&tx_pin), | 388 | inner: Peri<'a, T>, |
| 305 | None, | 389 | tx_pin: Peri<'a, impl TxPin<T>>, |
| 306 | None, | 390 | cts_pin: Peri<'a, impl CtsPin<T>>, |
| 307 | None, | 391 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, |
| 308 | tx_buffer, | 392 | tx_buffer: &'a mut [u8], |
| 309 | &mut [], // Empty RX buffer | 393 | config: Config, |
| 310 | config, | 394 | ) -> Result<Self> { |
| 311 | )?; | 395 | tx_pin.as_tx(); |
| 396 | cts_pin.as_cts(); | ||
| 312 | 397 | ||
| 313 | Ok(Self { | 398 | Self::new_inner::<T>(inner, tx_pin.into(), Some(cts_pin.into()), tx_buffer, config) |
| 314 | info, | ||
| 315 | state, | ||
| 316 | _tx_pin: tx_pin, | ||
| 317 | }) | ||
| 318 | } | 399 | } |
| 400 | } | ||
| 319 | 401 | ||
| 402 | impl<'a> BufferedLpuartTx<'a> { | ||
| 320 | /// Write data asynchronously | 403 | /// Write data asynchronously |
| 321 | pub async fn write(&mut self, buf: &[u8]) -> Result<usize> { | 404 | pub async fn write(&mut self, buf: &[u8]) -> Result<usize> { |
| 322 | let mut written = 0; | 405 | let mut written = 0; |
| @@ -401,51 +484,63 @@ impl<'a> BufferedLpuartTx<'a> { | |||
| 401 | // ============================================================================ | 484 | // ============================================================================ |
| 402 | 485 | ||
| 403 | impl<'a> BufferedLpuartRx<'a> { | 486 | impl<'a> BufferedLpuartRx<'a> { |
| 487 | /// Helper for RX-only initialization | ||
| 488 | fn new_inner<T: Instance>( | ||
| 489 | inner: Peri<'a, T>, | ||
| 490 | rx_pin: Peri<'a, AnyPin>, | ||
| 491 | rts_pin: Option<Peri<'a, AnyPin>>, | ||
| 492 | rx_buffer: &'a mut [u8], | ||
| 493 | config: Config, | ||
| 494 | ) -> Result<BufferedLpuartRx<'a>> { | ||
| 495 | let state = BufferedLpuart::init_common::<T>( | ||
| 496 | &inner, | ||
| 497 | None, | ||
| 498 | Some(rx_buffer), | ||
| 499 | &config, | ||
| 500 | false, | ||
| 501 | true, | ||
| 502 | rts_pin.is_some(), | ||
| 503 | false, | ||
| 504 | )?; | ||
| 505 | |||
| 506 | Ok(BufferedLpuartRx { | ||
| 507 | info: T::info(), | ||
| 508 | state, | ||
| 509 | _rx_pin: rx_pin, | ||
| 510 | _rts_pin: rts_pin, | ||
| 511 | }) | ||
| 512 | } | ||
| 513 | |||
| 404 | /// Create a new RX-only buffered LPUART | 514 | /// Create a new RX-only buffered LPUART |
| 405 | pub fn new<T: Instance>( | 515 | pub fn new<T: Instance>( |
| 406 | _inner: Peri<'a, T>, | 516 | inner: Peri<'a, T>, |
| 407 | rx_pin: Peri<'a, impl RxPin<T>>, | 517 | rx_pin: Peri<'a, impl RxPin<T>>, |
| 408 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, | 518 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, |
| 409 | rx_buffer: &'a mut [u8], | 519 | rx_buffer: &'a mut [u8], |
| 410 | config: Config, | 520 | config: Config, |
| 411 | ) -> Result<Self> { | 521 | ) -> Result<Self> { |
| 412 | rx_pin.as_rx(); | 522 | rx_pin.as_rx(); |
| 413 | let rx_pin: Peri<'a, AnyPin> = rx_pin.into(); | ||
| 414 | |||
| 415 | let info = T::info(); | ||
| 416 | let state = T::buffered_state(); | ||
| 417 | |||
| 418 | // Check if already initialized | ||
| 419 | if state.initialized.load(Ordering::Relaxed) { | ||
| 420 | return Err(Error::InvalidArgument); | ||
| 421 | } | ||
| 422 | 523 | ||
| 423 | // Initialize RX ring buffer only | 524 | Self::new_inner::<T>(inner, rx_pin.into(), None, rx_buffer, config) |
| 424 | unsafe { | 525 | } |
| 425 | let rx_buf = &state.rx_buf as *const _ as *mut RingBuffer; | ||
| 426 | (*rx_buf).init(rx_buffer.as_mut_ptr(), rx_buffer.len()); | ||
| 427 | } | ||
| 428 | |||
| 429 | state.initialized.store(true, Ordering::Relaxed); | ||
| 430 | 526 | ||
| 431 | // Initialize with RX only | 527 | /// Create a new RX-only buffered LPUART with RTS flow control |
| 432 | BufferedLpuart::init::<T>( | 528 | pub fn new_with_rts<T: Instance>( |
| 433 | None, | 529 | inner: Peri<'a, T>, |
| 434 | Some(&rx_pin), | 530 | rx_pin: Peri<'a, impl RxPin<T>>, |
| 435 | None, | 531 | rts_pin: Peri<'a, impl RtsPin<T>>, |
| 436 | None, | 532 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, BufferedInterruptHandler<T>> + 'a, |
| 437 | &mut [], // Empty TX buffer | 533 | rx_buffer: &'a mut [u8], |
| 438 | rx_buffer, | 534 | config: Config, |
| 439 | config, | 535 | ) -> Result<Self> { |
| 440 | )?; | 536 | rx_pin.as_rx(); |
| 537 | rts_pin.as_rts(); | ||
| 441 | 538 | ||
| 442 | Ok(Self { | 539 | Self::new_inner::<T>(inner, rx_pin.into(), Some(rts_pin.into()), rx_buffer, config) |
| 443 | info, | ||
| 444 | state, | ||
| 445 | _rx_pin: rx_pin, | ||
| 446 | }) | ||
| 447 | } | 540 | } |
| 541 | } | ||
| 448 | 542 | ||
| 543 | impl<'a> BufferedLpuartRx<'a> { | ||
| 449 | /// Read data asynchronously | 544 | /// Read data asynchronously |
| 450 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize> { | 545 | pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize> { |
| 451 | if buf.is_empty() { | 546 | if buf.is_empty() { |
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 { |
