aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJanKomarekNXP <[email protected]>2025-12-01 18:07:58 +0100
committerGitHub <[email protected]>2025-12-01 18:07:58 +0100
commit717346f21a4cf4993c2a1f046e26b6bf647d89cb (patch)
tree81dcbf726769eac5726796b340542d661debe407 /src
parent3b239cb6de22b7bb8c2d87defb3205294653be7a (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')
-rw-r--r--src/lpuart/buffered.rs505
-rw-r--r--src/lpuart/mod.rs141
2 files changed, 396 insertions, 250 deletions
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
18pub struct State { 18pub 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
74impl<'a> BufferedLpuart<'a> { 76impl<'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
274impl<'a> BufferedLpuartTx<'a> { 346impl<'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
402impl<'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
403impl<'a> BufferedLpuartRx<'a> { 486impl<'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
543impl<'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
206pub fn configure_flow_control(regs: Regs, config: &Config) { 206pub 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> {
694pub struct LpuartTx<'a, M: Mode> { 682pub 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> {
702pub struct LpuartRx<'a, M: Mode> { 691pub 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
713impl<'a, M: Mode> Lpuart<'a, M> { 703impl<'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
778impl<'a> Lpuart<'a, Blocking> { 768impl<'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
809impl<'a, M: Mode> LpuartTx<'a, M> { 820impl<'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
820impl<'a> LpuartTx<'a, Blocking> { 837impl<'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
911impl<'a, M: Mode> LpuartRx<'a, M> { 943impl<'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
922impl<'a> LpuartRx<'a, Blocking> { 960impl<'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 {