diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-02-22 00:07:09 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-02-22 00:07:09 +0100 |
| commit | 6a977d2ae937c835401c46aad9f5cbe79962266f (patch) | |
| tree | 83eae9b70a2fc97f9312a2cdc11b524bfcb3ef02 /embassy-nrf/src/uarte.rs | |
| parent | 036f703a4a42ae67d2b0fdc6b5268ac04d5066f7 (diff) | |
nrf/uarte: prevent accidentally driving tx pin on rxonly uart if it was left in PSEL.
Diffstat (limited to 'embassy-nrf/src/uarte.rs')
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 60 |
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 | ||
