Skip to content

Commit c1821a0

Browse files
committed
Split uart wakers into separate tx and rx wakers
1 parent a8a2424 commit c1821a0

File tree

1 file changed

+50
-57
lines changed

1 file changed

+50
-57
lines changed

src/uart.rs

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ impl<'a> UartTx<'a, Async> {
578578
let res = select(
579579
transfer,
580580
poll_fn(|cx| {
581-
self.info.waker.register(cx.waker());
581+
self.info.tx_waker.register(cx.waker());
582582

583583
self.info.regs.fifointenset().write(|w| w.txerr().set_bit());
584584

@@ -606,38 +606,23 @@ impl<'a> UartTx<'a, Async> {
606606

607607
/// Flush UART TX asynchronously.
608608
pub fn flush(&mut self) -> impl Future<Output = Result<()>> + use<'_, 'a> {
609-
self.wait_on(
610-
|me| {
611-
if me.info.regs.stat().read().txidle().bit_is_set() {
612-
Poll::Ready(Ok(()))
613-
} else {
614-
Poll::Pending
615-
}
616-
},
617-
|me| {
618-
me.info.regs.intenset().write(|w| w.txidleen().set_bit());
619-
},
620-
)
621-
}
622-
623-
/// Calls `f` to check if we are ready or not.
624-
/// If not, `g` is called once the waker is set (to eg enable the required interrupts).
625-
fn wait_on<F, U, G>(&mut self, mut f: F, mut g: G) -> impl Future<Output = U> + use<'_, 'a, F, U, G>
626-
where
627-
F: FnMut(&mut Self) -> Poll<U>,
628-
G: FnMut(&mut Self),
629-
{
630-
poll_fn(move |cx| {
631-
// Register waker before checking condition, to ensure that wakes/interrupts
632-
// aren't lost between f() and g()
633-
self.info.waker.register(cx.waker());
634-
let r = f(self);
635-
636-
if r.is_pending() {
637-
g(self);
638-
}
609+
poll_fn(|cx| {
610+
self.info.tx_waker.register(cx.waker());
611+
612+
self.info.regs.intenset().write(|w| w.txidleen().set_bit());
613+
self.info.regs.fifointenset().write(|w| w.txerr().set_bit());
614+
615+
let fifointstat = self.info.regs.fifointstat().read();
639616

640-
r
617+
self.info.regs.fifostat().write(|w| w.txerr().set_bit());
618+
619+
if self.info.regs.stat().read().txidle().bit_is_set() {
620+
Poll::Ready(Ok(()))
621+
} else if fifointstat.txerr().bit_is_set() {
622+
Poll::Ready(Err(Error::Overrun))
623+
} else {
624+
Poll::Pending
625+
}
641626
})
642627
}
643628
}
@@ -685,7 +670,7 @@ impl<'a> UartRx<'a, Async> {
685670
let res = select(
686671
transfer,
687672
poll_fn(|cx| {
688-
self.info.waker.register(cx.waker());
673+
self.info.rx_waker.register(cx.waker());
689674

690675
self.info
691676
.regs
@@ -1065,7 +1050,8 @@ impl embedded_io_async::Write for Uart<'_, Async> {
10651050

10661051
struct Info {
10671052
regs: &'static crate::pac::usart0::RegisterBlock,
1068-
waker: &'static AtomicWaker,
1053+
tx_waker: &'static AtomicWaker,
1054+
rx_waker: &'static AtomicWaker,
10691055
}
10701056

10711057
// SAFETY: safety for Send here is the same as the other accessors to unsafe blocks: it must be done from a single executor context.
@@ -1075,7 +1061,8 @@ unsafe impl Send for Info {}
10751061

10761062
trait SealedInstance {
10771063
fn info() -> Info;
1078-
fn waker() -> &'static AtomicWaker;
1064+
fn tx_waker() -> &'static AtomicWaker;
1065+
fn rx_waker() -> &'static AtomicWaker;
10791066
}
10801067

10811068
/// UART interrupt handler.
@@ -1088,29 +1075,29 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
10881075
let regs = T::info().regs;
10891076
let stat = regs.intstat().read();
10901077

1091-
if stat.txidle().bit_is_set()
1092-
|| stat.framerrint().bit_is_set()
1093-
|| stat.parityerrint().bit_is_set()
1094-
|| stat.rxnoiseint().bit_is_set()
1095-
{
1096-
regs.intenclr().write(|w| {
1097-
w.txidleclr()
1098-
.set_bit()
1099-
.framerrclr()
1100-
.set_bit()
1101-
.parityerrclr()
1102-
.set_bit()
1103-
.rxnoiseclr()
1104-
.set_bit()
1105-
});
1078+
if stat.txidle().bit_is_set() {
1079+
regs.intenclr().write(|w| w.txidleclr().set_bit());
1080+
T::tx_waker().wake();
1081+
}
1082+
1083+
if stat.framerrint().bit_is_set() || stat.parityerrint().bit_is_set() || stat.rxnoiseint().bit_is_set() {
1084+
regs.intenclr()
1085+
.write(|w| w.framerrclr().set_bit().parityerrclr().set_bit().rxnoiseclr().set_bit());
1086+
1087+
T::rx_waker().wake();
11061088
}
11071089

11081090
let fifointstat = regs.fifointstat().read();
1109-
if fifointstat.txerr().bit_is_set() || fifointstat.rxerr().bit_is_set() {
1110-
regs.fifointenclr().write(|w| w.txerr().set_bit().rxerr().set_bit());
1091+
if fifointstat.txerr().bit_is_set() {
1092+
regs.fifointenclr().write(|w| w.txerr().set_bit());
1093+
1094+
T::tx_waker().wake();
11111095
}
11121096

1113-
T::waker().wake();
1097+
if fifointstat.rxerr().bit_is_set() {
1098+
regs.fifointenclr().write(|w| w.txerr().set_bit().rxerr().set_bit());
1099+
T::rx_waker().wake();
1100+
}
11141101
}
11151102
}
11161103

@@ -1129,13 +1116,19 @@ macro_rules! impl_instance {
11291116
fn info() -> Info {
11301117
Info {
11311118
regs: unsafe { &*crate::pac::[<Usart $n>]::ptr() },
1132-
waker: Self::waker(),
1119+
tx_waker: Self::tx_waker(),
1120+
rx_waker: Self::rx_waker(),
11331121
}
11341122
}
11351123

1136-
fn waker() -> &'static AtomicWaker {
1137-
static WAKER: AtomicWaker = AtomicWaker::new();
1138-
&WAKER
1124+
fn tx_waker() -> &'static AtomicWaker {
1125+
static TX_WAKER: AtomicWaker = AtomicWaker::new();
1126+
&TX_WAKER
1127+
}
1128+
1129+
fn rx_waker() -> &'static AtomicWaker {
1130+
static RX_WAKER: AtomicWaker = AtomicWaker::new();
1131+
&RX_WAKER
11391132
}
11401133
}
11411134

0 commit comments

Comments
 (0)