diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-02-05 23:36:42 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-05 23:36:42 +0000 |
| commit | ad7d4494fad12f98c7e8e2b776bc12453a66be9a (patch) | |
| tree | 1219ae0fbef953c26e00a7afda6c7925b89b3e44 | |
| parent | f9cba604a51b81209efa1a81123928bb876f2033 (diff) | |
| parent | 2575f597cc3aafeb9925511b12adf30f6a67bccb (diff) | |
Merge pull request #2502 from jbeaurivage/nrf-uarte-errors
NRF: handle `uarte` RX errors
| -rw-r--r-- | embassy-nrf/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 128 |
2 files changed, 110 insertions, 19 deletions
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index a682e1227..7e161df9b 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -138,6 +138,7 @@ embedded-io = { version = "0.6.0" } | |||
| 138 | embedded-io-async = { version = "0.6.1" } | 138 | embedded-io-async = { version = "0.6.1" } |
| 139 | 139 | ||
| 140 | defmt = { version = "0.3", optional = true } | 140 | defmt = { version = "0.3", optional = true } |
| 141 | bitflags = "2.4.2" | ||
| 141 | log = { version = "0.4.14", optional = true } | 142 | log = { version = "0.4.14", optional = true } |
| 142 | cortex-m-rt = ">=0.6.15,<0.8" | 143 | cortex-m-rt = ">=0.6.15,<0.8" |
| 143 | cortex-m = "0.7.6" | 144 | cortex-m = "0.7.6" |
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 95434e7a7..de2966ba5 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -52,6 +52,37 @@ impl Default for Config { | |||
| 52 | } | 52 | } |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | bitflags::bitflags! { | ||
| 56 | /// Error source flags | ||
| 57 | pub struct ErrorSource: u32 { | ||
| 58 | /// Buffer overrun | ||
| 59 | const OVERRUN = 0x01; | ||
| 60 | /// Parity error | ||
| 61 | const PARITY = 0x02; | ||
| 62 | /// Framing error | ||
| 63 | const FRAMING = 0x04; | ||
| 64 | /// Break condition | ||
| 65 | const BREAK = 0x08; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | impl ErrorSource { | ||
| 70 | #[inline] | ||
| 71 | fn check(self) -> Result<(), Error> { | ||
| 72 | if self.contains(ErrorSource::OVERRUN) { | ||
| 73 | Err(Error::Overrun) | ||
| 74 | } else if self.contains(ErrorSource::PARITY) { | ||
| 75 | Err(Error::Parity) | ||
| 76 | } else if self.contains(ErrorSource::FRAMING) { | ||
| 77 | Err(Error::Framing) | ||
| 78 | } else if self.contains(ErrorSource::BREAK) { | ||
| 79 | Err(Error::Break) | ||
| 80 | } else { | ||
| 81 | Ok(()) | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 55 | /// UART error. | 86 | /// UART error. |
| 56 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 87 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 57 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 88 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -61,6 +92,14 @@ pub enum Error { | |||
| 61 | BufferTooLong, | 92 | BufferTooLong, |
| 62 | /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash. | 93 | /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash. |
| 63 | BufferNotInRAM, | 94 | BufferNotInRAM, |
| 95 | /// Framing Error | ||
| 96 | Framing, | ||
| 97 | /// Parity Error | ||
| 98 | Parity, | ||
| 99 | /// Buffer Overrun | ||
| 100 | Overrun, | ||
| 101 | /// Break condition | ||
| 102 | Break, | ||
| 64 | } | 103 | } |
| 65 | 104 | ||
| 66 | /// Interrupt handler. | 105 | /// Interrupt handler. |
| @@ -73,9 +112,16 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 73 | let r = T::regs(); | 112 | let r = T::regs(); |
| 74 | let s = T::state(); | 113 | let s = T::state(); |
| 75 | 114 | ||
| 76 | if r.events_endrx.read().bits() != 0 { | 115 | let endrx = r.events_endrx.read().bits(); |
| 116 | let error = r.events_error.read().bits(); | ||
| 117 | if endrx != 0 || error != 0 { | ||
| 77 | s.endrx_waker.wake(); | 118 | s.endrx_waker.wake(); |
| 78 | r.intenclr.write(|w| w.endrx().clear()); | 119 | if endrx != 0 { |
| 120 | r.intenclr.write(|w| w.endrx().clear()); | ||
| 121 | } | ||
| 122 | if error != 0 { | ||
| 123 | r.intenclr.write(|w| w.error().clear()); | ||
| 124 | } | ||
| 79 | } | 125 | } |
| 80 | if r.events_endtx.read().bits() != 0 { | 126 | if r.events_endtx.read().bits() != 0 { |
| 81 | s.endtx_waker.wake(); | 127 | s.endtx_waker.wake(); |
| @@ -486,6 +532,14 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 486 | Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config) | 532 | Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config) |
| 487 | } | 533 | } |
| 488 | 534 | ||
| 535 | /// Check for errors and clear the error register if an error occured. | ||
| 536 | fn check_and_clear_errors(&mut self) -> Result<(), Error> { | ||
| 537 | let r = T::regs(); | ||
| 538 | let err_bits = r.errorsrc.read().bits(); | ||
| 539 | r.errorsrc.write(|w| unsafe { w.bits(err_bits) }); | ||
| 540 | ErrorSource::from_bits_truncate(err_bits).check() | ||
| 541 | } | ||
| 542 | |||
| 489 | fn new_inner( | 543 | fn new_inner( |
| 490 | uarte: impl Peripheral<P = T> + 'd, | 544 | uarte: impl Peripheral<P = T> + 'd, |
| 491 | rxd: PeripheralRef<'d, AnyPin>, | 545 | rxd: PeripheralRef<'d, AnyPin>, |
| @@ -572,7 +626,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 572 | 626 | ||
| 573 | /// Read bytes until the buffer is filled. | 627 | /// Read bytes until the buffer is filled. |
| 574 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | 628 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 575 | if buffer.len() == 0 { | 629 | if buffer.is_empty() { |
| 576 | return Ok(()); | 630 | return Ok(()); |
| 577 | } | 631 | } |
| 578 | if buffer.len() > EASY_DMA_SIZE { | 632 | if buffer.len() > EASY_DMA_SIZE { |
| @@ -588,8 +642,13 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 588 | let drop = OnDrop::new(move || { | 642 | let drop = OnDrop::new(move || { |
| 589 | trace!("read drop: stopping"); | 643 | trace!("read drop: stopping"); |
| 590 | 644 | ||
| 591 | r.intenclr.write(|w| w.endrx().clear()); | 645 | r.intenclr.write(|w| { |
| 646 | w.endrx().clear(); | ||
| 647 | w.error().clear() | ||
| 648 | }); | ||
| 592 | r.events_rxto.reset(); | 649 | r.events_rxto.reset(); |
| 650 | r.events_error.reset(); | ||
| 651 | r.errorsrc.reset(); | ||
| 593 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 652 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| 594 | 653 | ||
| 595 | while r.events_endrx.read().bits() == 0 {} | 654 | while r.events_endrx.read().bits() == 0 {} |
| @@ -601,17 +660,26 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 601 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 660 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 602 | 661 | ||
| 603 | r.events_endrx.reset(); | 662 | r.events_endrx.reset(); |
| 604 | r.intenset.write(|w| w.endrx().set()); | 663 | r.events_error.reset(); |
| 664 | r.intenset.write(|w| { | ||
| 665 | w.endrx().set(); | ||
| 666 | w.error().set() | ||
| 667 | }); | ||
| 605 | 668 | ||
| 606 | compiler_fence(Ordering::SeqCst); | 669 | compiler_fence(Ordering::SeqCst); |
| 607 | 670 | ||
| 608 | trace!("startrx"); | 671 | trace!("startrx"); |
| 609 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 672 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 610 | 673 | ||
| 611 | poll_fn(|cx| { | 674 | let result = poll_fn(|cx| { |
| 612 | s.endrx_waker.register(cx.waker()); | 675 | s.endrx_waker.register(cx.waker()); |
| 676 | |||
| 677 | if let Err(e) = self.check_and_clear_errors() { | ||
| 678 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 679 | return Poll::Ready(Err(e)); | ||
| 680 | } | ||
| 613 | if r.events_endrx.read().bits() != 0 { | 681 | if r.events_endrx.read().bits() != 0 { |
| 614 | return Poll::Ready(()); | 682 | return Poll::Ready(Ok(())); |
| 615 | } | 683 | } |
| 616 | Poll::Pending | 684 | Poll::Pending |
| 617 | }) | 685 | }) |
| @@ -621,7 +689,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 621 | r.events_rxstarted.reset(); | 689 | r.events_rxstarted.reset(); |
| 622 | drop.defuse(); | 690 | drop.defuse(); |
| 623 | 691 | ||
| 624 | Ok(()) | 692 | result |
| 625 | } | 693 | } |
| 626 | 694 | ||
| 627 | /// Read bytes until the buffer is filled. | 695 | /// Read bytes until the buffer is filled. |
| @@ -642,19 +710,23 @@ impl<'d, T: Instance> UarteRx<'d, T> { | |||
| 642 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 710 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 643 | 711 | ||
| 644 | r.events_endrx.reset(); | 712 | r.events_endrx.reset(); |
| 645 | r.intenclr.write(|w| w.endrx().clear()); | 713 | r.events_error.reset(); |
| 714 | r.intenclr.write(|w| { | ||
| 715 | w.endrx().clear(); | ||
| 716 | w.error().clear() | ||
| 717 | }); | ||
| 646 | 718 | ||
| 647 | compiler_fence(Ordering::SeqCst); | 719 | compiler_fence(Ordering::SeqCst); |
| 648 | 720 | ||
| 649 | trace!("startrx"); | 721 | trace!("startrx"); |
| 650 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 722 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 651 | 723 | ||
| 652 | while r.events_endrx.read().bits() == 0 {} | 724 | while r.events_endrx.read().bits() == 0 && r.events_error.read().bits() == 0 {} |
| 653 | 725 | ||
| 654 | compiler_fence(Ordering::SeqCst); | 726 | compiler_fence(Ordering::SeqCst); |
| 655 | r.events_rxstarted.reset(); | 727 | r.events_rxstarted.reset(); |
| 656 | 728 | ||
| 657 | Ok(()) | 729 | self.check_and_clear_errors() |
| 658 | } | 730 | } |
| 659 | } | 731 | } |
| 660 | 732 | ||
| @@ -721,8 +793,12 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { | |||
| 721 | let drop = OnDrop::new(|| { | 793 | let drop = OnDrop::new(|| { |
| 722 | self.timer.stop(); | 794 | self.timer.stop(); |
| 723 | 795 | ||
| 724 | r.intenclr.write(|w| w.endrx().clear()); | 796 | r.intenclr.write(|w| { |
| 797 | w.endrx().clear(); | ||
| 798 | w.error().clear() | ||
| 799 | }); | ||
| 725 | r.events_rxto.reset(); | 800 | r.events_rxto.reset(); |
| 801 | r.events_error.reset(); | ||
| 726 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 802 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| 727 | 803 | ||
| 728 | while r.events_endrx.read().bits() == 0 {} | 804 | while r.events_endrx.read().bits() == 0 {} |
| @@ -732,17 +808,27 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { | |||
| 732 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 808 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 733 | 809 | ||
| 734 | r.events_endrx.reset(); | 810 | r.events_endrx.reset(); |
| 735 | r.intenset.write(|w| w.endrx().set()); | 811 | r.events_error.reset(); |
| 812 | r.intenset.write(|w| { | ||
| 813 | w.endrx().set(); | ||
| 814 | w.error().set() | ||
| 815 | }); | ||
| 736 | 816 | ||
| 737 | compiler_fence(Ordering::SeqCst); | 817 | compiler_fence(Ordering::SeqCst); |
| 738 | 818 | ||
| 739 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 819 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 740 | 820 | ||
| 741 | poll_fn(|cx| { | 821 | let result = poll_fn(|cx| { |
| 742 | s.endrx_waker.register(cx.waker()); | 822 | s.endrx_waker.register(cx.waker()); |
| 823 | |||
| 824 | if let Err(e) = self.rx.check_and_clear_errors() { | ||
| 825 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | ||
| 826 | return Poll::Ready(Err(e)); | ||
| 827 | } | ||
| 743 | if r.events_endrx.read().bits() != 0 { | 828 | if r.events_endrx.read().bits() != 0 { |
| 744 | return Poll::Ready(()); | 829 | return Poll::Ready(Ok(())); |
| 745 | } | 830 | } |
| 831 | |||
| 746 | Poll::Pending | 832 | Poll::Pending |
| 747 | }) | 833 | }) |
| 748 | .await; | 834 | .await; |
| @@ -755,7 +841,7 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { | |||
| 755 | 841 | ||
| 756 | drop.defuse(); | 842 | drop.defuse(); |
| 757 | 843 | ||
| 758 | Ok(n) | 844 | result.map(|_| n) |
| 759 | } | 845 | } |
| 760 | 846 | ||
| 761 | /// Read bytes until the buffer is filled, or the line becomes idle. | 847 | /// Read bytes until the buffer is filled, or the line becomes idle. |
| @@ -780,13 +866,17 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { | |||
| 780 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | 866 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 781 | 867 | ||
| 782 | r.events_endrx.reset(); | 868 | r.events_endrx.reset(); |
| 783 | r.intenclr.write(|w| w.endrx().clear()); | 869 | r.events_error.reset(); |
| 870 | r.intenclr.write(|w| { | ||
| 871 | w.endrx().clear(); | ||
| 872 | w.error().clear() | ||
| 873 | }); | ||
| 784 | 874 | ||
| 785 | compiler_fence(Ordering::SeqCst); | 875 | compiler_fence(Ordering::SeqCst); |
| 786 | 876 | ||
| 787 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 877 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 788 | 878 | ||
| 789 | while r.events_endrx.read().bits() == 0 {} | 879 | while r.events_endrx.read().bits() == 0 && r.events_error.read().bits() == 0 {} |
| 790 | 880 | ||
| 791 | compiler_fence(Ordering::SeqCst); | 881 | compiler_fence(Ordering::SeqCst); |
| 792 | let n = r.rxd.amount.read().amount().bits() as usize; | 882 | let n = r.rxd.amount.read().amount().bits() as usize; |
| @@ -794,7 +884,7 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { | |||
| 794 | self.timer.stop(); | 884 | self.timer.stop(); |
| 795 | r.events_rxstarted.reset(); | 885 | r.events_rxstarted.reset(); |
| 796 | 886 | ||
| 797 | Ok(n) | 887 | self.rx.check_and_clear_errors().map(|_| n) |
| 798 | } | 888 | } |
| 799 | } | 889 | } |
| 800 | 890 | ||
