diff options
Diffstat (limited to 'embassy-nrf/src/uarte.rs')
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 88 |
1 files changed, 44 insertions, 44 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 9e5b85dea..cbd5dccbc 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -115,7 +115,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 115 | let endrx = r.events_endrx.read().bits(); | 115 | let endrx = r.events_endrx.read().bits(); |
| 116 | let error = r.events_error.read().bits(); | 116 | let error = r.events_error.read().bits(); |
| 117 | if endrx != 0 || error != 0 { | 117 | if endrx != 0 || error != 0 { |
| 118 | s.endrx_waker.wake(); | 118 | s.rx_waker.wake(); |
| 119 | if endrx != 0 { | 119 | if endrx != 0 { |
| 120 | r.intenclr.write(|w| w.endrx().clear()); | 120 | r.intenclr.write(|w| w.endrx().clear()); |
| 121 | } | 121 | } |
| @@ -124,7 +124,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 124 | } | 124 | } |
| 125 | } | 125 | } |
| 126 | if r.events_endtx.read().bits() != 0 { | 126 | if r.events_endtx.read().bits() != 0 { |
| 127 | s.endtx_waker.wake(); | 127 | s.tx_waker.wake(); |
| 128 | r.intenclr.write(|w| w.endtx().clear()); | 128 | r.intenclr.write(|w| w.endtx().clear()); |
| 129 | } | 129 | } |
| 130 | } | 130 | } |
| @@ -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 | ||
| @@ -242,6 +240,14 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 242 | (self.tx, self.rx) | 240 | (self.tx, self.rx) |
| 243 | } | 241 | } |
| 244 | 242 | ||
| 243 | /// Split the UART in reader and writer parts, by reference. | ||
| 244 | /// | ||
| 245 | /// The returned halves borrow from `self`, so you can drop them and go back to using | ||
| 246 | /// the "un-split" `self`. This allows temporarily splitting the UART. | ||
| 247 | pub fn split_by_ref(&mut self) -> (&mut UarteTx<'d, T>, &mut UarteRx<'d, T>) { | ||
| 248 | (&mut self.tx, &mut self.rx) | ||
| 249 | } | ||
| 250 | |||
| 245 | /// Split the Uarte into the transmitter and receiver with idle support parts. | 251 | /// Split the Uarte into the transmitter and receiver with idle support parts. |
| 246 | /// | 252 | /// |
| 247 | /// This is useful to concurrently transmit and receive from independent tasks. | 253 | /// This is useful to concurrently transmit and receive from independent tasks. |
| @@ -291,7 +297,7 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 291 | } | 297 | } |
| 292 | } | 298 | } |
| 293 | 299 | ||
| 294 | fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) { | 300 | pub(crate) fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) { |
| 295 | r.config.write(|w| { | 301 | r.config.write(|w| { |
| 296 | w.hwfc().bit(hardware_flow_control); | 302 | w.hwfc().bit(hardware_flow_control); |
| 297 | w.parity().variant(config.parity); | 303 | w.parity().variant(config.parity); |
| @@ -307,6 +313,12 @@ fn configure(r: &RegisterBlock, config: Config, hardware_flow_control: bool) { | |||
| 307 | r.events_rxstarted.reset(); | 313 | r.events_rxstarted.reset(); |
| 308 | r.events_txstarted.reset(); | 314 | r.events_txstarted.reset(); |
| 309 | 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 | |||
| 310 | // Enable | 322 | // Enable |
| 311 | apply_workaround_for_enable_anomaly(r); | 323 | apply_workaround_for_enable_anomaly(r); |
| 312 | r.enable.write(|w| w.enable().enabled()); | 324 | r.enable.write(|w| w.enable().enabled()); |
| @@ -320,7 +332,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 320 | txd: impl Peripheral<P = impl GpioPin> + 'd, | 332 | txd: impl Peripheral<P = impl GpioPin> + 'd, |
| 321 | config: Config, | 333 | config: Config, |
| 322 | ) -> Self { | 334 | ) -> Self { |
| 323 | into_ref!(txd); | 335 | into_ref!(uarte, txd); |
| 324 | Self::new_inner(uarte, txd.map_into(), None, config) | 336 | Self::new_inner(uarte, txd.map_into(), None, config) |
| 325 | } | 337 | } |
| 326 | 338 | ||
| @@ -332,20 +344,20 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 332 | cts: impl Peripheral<P = impl GpioPin> + 'd, | 344 | cts: impl Peripheral<P = impl GpioPin> + 'd, |
| 333 | config: Config, | 345 | config: Config, |
| 334 | ) -> Self { | 346 | ) -> Self { |
| 335 | into_ref!(txd, cts); | 347 | into_ref!(uarte, txd, cts); |
| 336 | 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) |
| 337 | } | 349 | } |
| 338 | 350 | ||
| 339 | fn new_inner( | 351 | fn new_inner( |
| 340 | uarte: impl Peripheral<P = T> + 'd, | 352 | uarte: PeripheralRef<'d, T>, |
| 341 | txd: PeripheralRef<'d, AnyPin>, | 353 | txd: PeripheralRef<'d, AnyPin>, |
| 342 | cts: Option<PeripheralRef<'d, AnyPin>>, | 354 | cts: Option<PeripheralRef<'d, AnyPin>>, |
| 343 | config: Config, | 355 | config: Config, |
| 344 | ) -> Self { | 356 | ) -> Self { |
| 345 | into_ref!(uarte); | ||
| 346 | |||
| 347 | let r = T::regs(); | 357 | let r = T::regs(); |
| 348 | 358 | ||
| 359 | configure(r, config, cts.is_some()); | ||
| 360 | |||
| 349 | txd.set_high(); | 361 | txd.set_high(); |
| 350 | txd.conf().write(|w| w.dir().output().drive().s0s1()); | 362 | txd.conf().write(|w| w.dir().output().drive().s0s1()); |
| 351 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); | 363 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); |
| @@ -355,12 +367,6 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 355 | } | 367 | } |
| 356 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | 368 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); |
| 357 | 369 | ||
| 358 | r.psel.rxd.write(|w| w.connect().disconnected()); | ||
| 359 | r.psel.rts.write(|w| w.connect().disconnected()); | ||
| 360 | |||
| 361 | let hardware_flow_control = cts.is_some(); | ||
| 362 | configure(r, config, hardware_flow_control); | ||
| 363 | |||
| 364 | T::Interrupt::unpend(); | 370 | T::Interrupt::unpend(); |
| 365 | unsafe { T::Interrupt::enable() }; | 371 | unsafe { T::Interrupt::enable() }; |
| 366 | 372 | ||
| @@ -425,7 +431,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { | |||
| 425 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | 431 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); |
| 426 | 432 | ||
| 427 | poll_fn(|cx| { | 433 | poll_fn(|cx| { |
| 428 | s.endtx_waker.register(cx.waker()); | 434 | s.tx_waker.register(cx.waker()); |
| 429 | if r.events_endtx.read().bits() != 0 { | 435 | if r.events_endtx.read().bits() != 0 { |
| 430 | return Poll::Ready(()); | 436 | return Poll::Ready(()); |
| 431 | } | 437 | } |
| @@ -516,7 +522,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 516 | rxd: impl Peripheral<P = impl GpioPin> + 'd, | 522 | rxd: impl Peripheral<P = impl GpioPin> + 'd, |
| 517 | config: Config, | 523 | config: Config, |
| 518 | ) -> Self { | 524 | ) -> Self { |
| 519 | into_ref!(rxd); | 525 | into_ref!(uarte, rxd); |
| 520 | Self::new_inner(uarte, rxd.map_into(), None, config) | 526 | Self::new_inner(uarte, rxd.map_into(), None, config) |
| 521 | } | 527 | } |
| 522 | 528 | ||
| @@ -528,7 +534,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 528 | rts: impl Peripheral<P = impl GpioPin> + 'd, | 534 | rts: impl Peripheral<P = impl GpioPin> + 'd, |
| 529 | config: Config, | 535 | config: Config, |
| 530 | ) -> Self { | 536 | ) -> Self { |
| 531 | into_ref!(rxd, rts); | 537 | into_ref!(uarte, rxd, rts); |
| 532 | 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) |
| 533 | } | 539 | } |
| 534 | 540 | ||
| @@ -541,15 +547,15 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 541 | } | 547 | } |
| 542 | 548 | ||
| 543 | fn new_inner( | 549 | fn new_inner( |
| 544 | uarte: impl Peripheral<P = T> + 'd, | 550 | uarte: PeripheralRef<'d, T>, |
| 545 | rxd: PeripheralRef<'d, AnyPin>, | 551 | rxd: PeripheralRef<'d, AnyPin>, |
| 546 | rts: Option<PeripheralRef<'d, AnyPin>>, | 552 | rts: Option<PeripheralRef<'d, AnyPin>>, |
| 547 | config: Config, | 553 | config: Config, |
| 548 | ) -> Self { | 554 | ) -> Self { |
| 549 | into_ref!(uarte); | ||
| 550 | |||
| 551 | let r = T::regs(); | 555 | let r = T::regs(); |
| 552 | 556 | ||
| 557 | configure(r, config, rts.is_some()); | ||
| 558 | |||
| 553 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); | 559 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); |
| 554 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); | 560 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); |
| 555 | 561 | ||
| @@ -559,15 +565,9 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 559 | } | 565 | } |
| 560 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); | 566 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); |
| 561 | 567 | ||
| 562 | r.psel.txd.write(|w| w.connect().disconnected()); | ||
| 563 | r.psel.cts.write(|w| w.connect().disconnected()); | ||
| 564 | |||
| 565 | T::Interrupt::unpend(); | 568 | T::Interrupt::unpend(); |
| 566 | unsafe { T::Interrupt::enable() }; | 569 | unsafe { T::Interrupt::enable() }; |
| 567 | 570 | ||
| 568 | let hardware_flow_control = rts.is_some(); | ||
| 569 | configure(r, config, hardware_flow_control); | ||
| 570 | |||
| 571 | let s = T::state(); | 571 | let s = T::state(); |
| 572 | s.tx_rx_refcount.store(1, Ordering::Relaxed); | 572 | s.tx_rx_refcount.store(1, Ordering::Relaxed); |
| 573 | 573 | ||
| @@ -672,7 +672,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 672 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 672 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 673 | 673 | ||
| 674 | let result = poll_fn(|cx| { | 674 | let result = poll_fn(|cx| { |
| 675 | s.endrx_waker.register(cx.waker()); | 675 | s.rx_waker.register(cx.waker()); |
| 676 | 676 | ||
| 677 | if let Err(e) = self.check_and_clear_errors() { | 677 | if let Err(e) = self.check_and_clear_errors() { |
| 678 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 678 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| @@ -819,7 +819,7 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { | |||
| 819 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 819 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 820 | 820 | ||
| 821 | let result = poll_fn(|cx| { | 821 | let result = poll_fn(|cx| { |
| 822 | s.endrx_waker.register(cx.waker()); | 822 | s.rx_waker.register(cx.waker()); |
| 823 | 823 | ||
| 824 | if let Err(e) = self.rx.check_and_clear_errors() { | 824 | if let Err(e) = self.rx.check_and_clear_errors() { |
| 825 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 825 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| @@ -962,15 +962,15 @@ pub(crate) mod sealed { | |||
| 962 | use super::*; | 962 | use super::*; |
| 963 | 963 | ||
| 964 | pub struct State { | 964 | pub struct State { |
| 965 | pub endrx_waker: AtomicWaker, | 965 | pub rx_waker: AtomicWaker, |
| 966 | pub endtx_waker: AtomicWaker, | 966 | pub tx_waker: AtomicWaker, |
| 967 | pub tx_rx_refcount: AtomicU8, | 967 | pub tx_rx_refcount: AtomicU8, |
| 968 | } | 968 | } |
| 969 | impl State { | 969 | impl State { |
| 970 | pub const fn new() -> Self { | 970 | pub const fn new() -> Self { |
| 971 | Self { | 971 | Self { |
| 972 | endrx_waker: AtomicWaker::new(), | 972 | rx_waker: AtomicWaker::new(), |
| 973 | endtx_waker: AtomicWaker::new(), | 973 | tx_waker: AtomicWaker::new(), |
| 974 | tx_rx_refcount: AtomicU8::new(0), | 974 | tx_rx_refcount: AtomicU8::new(0), |
| 975 | } | 975 | } |
| 976 | } | 976 | } |
