aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-02-22 00:07:09 +0100
committerDario Nieuwenhuis <[email protected]>2024-02-22 00:07:09 +0100
commit6a977d2ae937c835401c46aad9f5cbe79962266f (patch)
tree83eae9b70a2fc97f9312a2cdc11b524bfcb3ef02
parent036f703a4a42ae67d2b0fdc6b5268ac04d5066f7 (diff)
nrf/uarte: prevent accidentally driving tx pin on rxonly uart if it was left in PSEL.
-rw-r--r--embassy-nrf/src/uarte.rs60
1 files changed, 26 insertions, 34 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 7fd34453a..cbd5dccbc 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -159,7 +159,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
159 txd: impl Peripheral<P = impl GpioPin> + 'd, 159 txd: impl Peripheral<P = impl GpioPin> + 'd,
160 config: Config, 160 config: Config,
161 ) -> Self { 161 ) -> Self {
162 into_ref!(rxd, txd); 162 into_ref!(uarte, rxd, txd);
163 Self::new_inner(uarte, rxd.map_into(), txd.map_into(), None, None, config) 163 Self::new_inner(uarte, rxd.map_into(), txd.map_into(), None, None, config)
164 } 164 }
165 165
@@ -173,7 +173,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
173 rts: impl Peripheral<P = impl GpioPin> + 'd, 173 rts: impl Peripheral<P = impl GpioPin> + 'd,
174 config: Config, 174 config: Config,
175 ) -> Self { 175 ) -> Self {
176 into_ref!(rxd, txd, cts, rts); 176 into_ref!(uarte, rxd, txd, cts, rts);
177 Self::new_inner( 177 Self::new_inner(
178 uarte, 178 uarte,
179 rxd.map_into(), 179 rxd.map_into(),
@@ -185,17 +185,22 @@ impl<'d, T: Instance> Uarte<'d, T> {
185 } 185 }
186 186
187 fn new_inner( 187 fn new_inner(
188 uarte: impl Peripheral<P = T> + 'd, 188 uarte: PeripheralRef<'d, T>,
189 rxd: PeripheralRef<'d, AnyPin>, 189 rxd: PeripheralRef<'d, AnyPin>,
190 txd: PeripheralRef<'d, AnyPin>, 190 txd: PeripheralRef<'d, AnyPin>,
191 cts: Option<PeripheralRef<'d, AnyPin>>, 191 cts: Option<PeripheralRef<'d, AnyPin>>,
192 rts: Option<PeripheralRef<'d, AnyPin>>, 192 rts: Option<PeripheralRef<'d, AnyPin>>,
193 config: Config, 193 config: Config,
194 ) -> Self { 194 ) -> Self {
195 into_ref!(uarte);
196
197 let r = T::regs(); 195 let r = T::regs();
198 196
197 let hardware_flow_control = match (rts.is_some(), cts.is_some()) {
198 (false, false) => false,
199 (true, true) => true,
200 _ => panic!("RTS and CTS pins must be either both set or none set."),
201 };
202 configure(r, config, hardware_flow_control);
203
199 rxd.conf().write(|w| w.input().connect().drive().h0h1()); 204 rxd.conf().write(|w| w.input().connect().drive().h0h1());
200 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); 205 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
201 206
@@ -217,13 +222,6 @@ impl<'d, T: Instance> Uarte<'d, T> {
217 T::Interrupt::unpend(); 222 T::Interrupt::unpend();
218 unsafe { T::Interrupt::enable() }; 223 unsafe { T::Interrupt::enable() };
219 224
220 let hardware_flow_control = match (rts.is_some(), cts.is_some()) {
221 (false, false) => false,
222 (true, true) => true,
223 _ => panic!("RTS and CTS pins must be either both set or none set."),
224 };
225 configure(r, config, hardware_flow_control);
226
227 let s = T::state(); 225 let s = T::state();
228 s.tx_rx_refcount.store(2, Ordering::Relaxed); 226 s.tx_rx_refcount.store(2, Ordering::Relaxed);
229 227
@@ -315,6 +313,12 @@ pub(crate) fn configure(r: &RegisterBlock, config: Config, hardware_flow_control
315 r.events_rxstarted.reset(); 313 r.events_rxstarted.reset();
316 r.events_txstarted.reset(); 314 r.events_txstarted.reset();
317 315
316 // reset all pins
317 r.psel.txd.write(|w| w.connect().disconnected());
318 r.psel.rxd.write(|w| w.connect().disconnected());
319 r.psel.cts.write(|w| w.connect().disconnected());
320 r.psel.rts.write(|w| w.connect().disconnected());
321
318 // Enable 322 // Enable
319 apply_workaround_for_enable_anomaly(r); 323 apply_workaround_for_enable_anomaly(r);
320 r.enable.write(|w| w.enable().enabled()); 324 r.enable.write(|w| w.enable().enabled());
@@ -328,7 +332,7 @@ impl<'d, T: Instance> UarteTx<'d, T> {
328 txd: impl Peripheral<P = impl GpioPin> + 'd, 332 txd: impl Peripheral<P = impl GpioPin> + 'd,
329 config: Config, 333 config: Config,
330 ) -> Self { 334 ) -> Self {
331 into_ref!(txd); 335 into_ref!(uarte, txd);
332 Self::new_inner(uarte, txd.map_into(), None, config) 336 Self::new_inner(uarte, txd.map_into(), None, config)
333 } 337 }
334 338
@@ -340,20 +344,20 @@ impl<'d, T: Instance> UarteTx<'d, T> {
340 cts: impl Peripheral<P = impl GpioPin> + 'd, 344 cts: impl Peripheral<P = impl GpioPin> + 'd,
341 config: Config, 345 config: Config,
342 ) -> Self { 346 ) -> Self {
343 into_ref!(txd, cts); 347 into_ref!(uarte, txd, cts);
344 Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config) 348 Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config)
345 } 349 }
346 350
347 fn new_inner( 351 fn new_inner(
348 uarte: impl Peripheral<P = T> + 'd, 352 uarte: PeripheralRef<'d, T>,
349 txd: PeripheralRef<'d, AnyPin>, 353 txd: PeripheralRef<'d, AnyPin>,
350 cts: Option<PeripheralRef<'d, AnyPin>>, 354 cts: Option<PeripheralRef<'d, AnyPin>>,
351 config: Config, 355 config: Config,
352 ) -> Self { 356 ) -> Self {
353 into_ref!(uarte);
354
355 let r = T::regs(); 357 let r = T::regs();
356 358
359 configure(r, config, cts.is_some());
360
357 txd.set_high(); 361 txd.set_high();
358 txd.conf().write(|w| w.dir().output().drive().s0s1()); 362 txd.conf().write(|w| w.dir().output().drive().s0s1());
359 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); 363 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) });
@@ -363,12 +367,6 @@ impl<'d, T: Instance> UarteTx<'d, T> {
363 } 367 }
364 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); 368 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) });
365 369
366 r.psel.rxd.write(|w| w.connect().disconnected());
367 r.psel.rts.write(|w| w.connect().disconnected());
368
369 let hardware_flow_control = cts.is_some();
370 configure(r, config, hardware_flow_control);
371
372 T::Interrupt::unpend(); 370 T::Interrupt::unpend();
373 unsafe { T::Interrupt::enable() }; 371 unsafe { T::Interrupt::enable() };
374 372
@@ -524,7 +522,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
524 rxd: impl Peripheral<P = impl GpioPin> + 'd, 522 rxd: impl Peripheral<P = impl GpioPin> + 'd,
525 config: Config, 523 config: Config,
526 ) -> Self { 524 ) -> Self {
527 into_ref!(rxd); 525 into_ref!(uarte, rxd);
528 Self::new_inner(uarte, rxd.map_into(), None, config) 526 Self::new_inner(uarte, rxd.map_into(), None, config)
529 } 527 }
530 528
@@ -536,7 +534,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
536 rts: impl Peripheral<P = impl GpioPin> + 'd, 534 rts: impl Peripheral<P = impl GpioPin> + 'd,
537 config: Config, 535 config: Config,
538 ) -> Self { 536 ) -> Self {
539 into_ref!(rxd, rts); 537 into_ref!(uarte, rxd, rts);
540 Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config) 538 Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config)
541 } 539 }
542 540
@@ -549,15 +547,15 @@ impl<'d, T: Instance> UarteRx<'d, T> {
549 } 547 }
550 548
551 fn new_inner( 549 fn new_inner(
552 uarte: impl Peripheral<P = T> + 'd, 550 uarte: PeripheralRef<'d, T>,
553 rxd: PeripheralRef<'d, AnyPin>, 551 rxd: PeripheralRef<'d, AnyPin>,
554 rts: Option<PeripheralRef<'d, AnyPin>>, 552 rts: Option<PeripheralRef<'d, AnyPin>>,
555 config: Config, 553 config: Config,
556 ) -> Self { 554 ) -> Self {
557 into_ref!(uarte);
558
559 let r = T::regs(); 555 let r = T::regs();
560 556
557 configure(r, config, rts.is_some());
558
561 rxd.conf().write(|w| w.input().connect().drive().h0h1()); 559 rxd.conf().write(|w| w.input().connect().drive().h0h1());
562 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); 560 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
563 561
@@ -567,15 +565,9 @@ impl<'d, T: Instance> UarteRx<'d, T> {
567 } 565 }
568 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); 566 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
569 567
570 r.psel.txd.write(|w| w.connect().disconnected());
571 r.psel.cts.write(|w| w.connect().disconnected());
572
573 T::Interrupt::unpend(); 568 T::Interrupt::unpend();
574 unsafe { T::Interrupt::enable() }; 569 unsafe { T::Interrupt::enable() };
575 570
576 let hardware_flow_control = rts.is_some();
577 configure(r, config, hardware_flow_control);
578
579 let s = T::state(); 571 let s = T::state();
580 s.tx_rx_refcount.store(1, Ordering::Relaxed); 572 s.tx_rx_refcount.store(1, Ordering::Relaxed);
581 573