Skip to content

Commit 01f0e0f

Browse files
committed
Optimize UART buffered read with active detection
Replace fixed polling with interrupt-driven approach: enable START and RXLVL interrupts to wake when data arrives, check rxidle/start status, then poll. Reduces CPU usage while maintaining responsiveness.
1 parent b5f7c51 commit 01f0e0f

File tree

1 file changed

+69
-45
lines changed

1 file changed

+69
-45
lines changed

src/uart.rs

Lines changed: 69 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -912,52 +912,61 @@ impl<'a> UartRx<'a, Async> {
912912
};
913913
}
914914
} else {
915-
// No data available, wait for new data to arrive or error condition
916-
let res = select(
917-
embassy_time::Timer::after_micros(buffer_config.polling_rate),
918-
// detect bus errors
919-
poll_fn(|cx| {
920-
self.info.rx_waker.register(cx.waker());
921-
922-
self.info
923-
.regs
924-
.intenset()
925-
.write(|w| w.framerren().set_bit().parityerren().set_bit().rxnoiseen().set_bit());
926-
self.info.regs.fifointenset().write(|w| w.rxerr().set_bit());
927-
928-
let stat = self.info.regs.stat().read();
929-
let fifointstat = self.info.regs.fifointstat().read();
930-
931-
self.info.regs.stat().write(|w| {
932-
w.framerrint()
933-
.clear_bit_by_one()
934-
.parityerrint()
935-
.clear_bit_by_one()
936-
.rxnoiseint()
937-
.clear_bit_by_one()
938-
});
939-
940-
self.info.regs.fifostat().write(|w| w.rxerr().set_bit());
941-
942-
if stat.framerrint().bit_is_set() {
943-
Poll::Ready(Err(Error::Framing))
944-
} else if stat.parityerrint().bit_is_set() {
945-
Poll::Ready(Err(Error::Parity))
946-
} else if stat.rxnoiseint().bit_is_set() {
947-
Poll::Ready(Err(Error::Noise))
948-
} else if fifointstat.rxerr().bit_is_set() {
949-
Poll::Ready(Err(Error::Overrun))
950-
} else {
951-
Poll::Pending
952-
}
953-
}),
954-
)
955-
.await;
915+
poll_fn(|cx| {
916+
self.info.rx_waker.register(cx.waker());
956917

957-
match res {
958-
Either::First(()) | Either::Second(Ok(())) => (),
959-
Either::Second(Err(e)) => return Err(e),
960-
}
918+
self.info.regs.intenset().write(|w| {
919+
w.framerren()
920+
.set_bit()
921+
.parityerren()
922+
.set_bit()
923+
.rxnoiseen()
924+
.set_bit()
925+
.starten()
926+
.set_bit()
927+
});
928+
929+
self.info.regs.fifointenset().write(|w| w.rxerr().set_bit());
930+
931+
let stat = self.info.regs.stat().read();
932+
let fifointstat = self.info.regs.fifointstat().read();
933+
934+
self.info.regs.stat().write(|w| {
935+
w.framerrint()
936+
.clear_bit_by_one()
937+
.parityerrint()
938+
.clear_bit_by_one()
939+
.rxnoiseint()
940+
.clear_bit_by_one()
941+
.start()
942+
.clear_bit_by_one()
943+
});
944+
945+
self.info
946+
.regs
947+
.fifotrig()
948+
.modify(|_, w| unsafe { w.rxlvlena().set_bit().rxlvl().bits(0) });
949+
self.info.regs.fifointenset().write(|w| w.rxlvl().set_bit());
950+
951+
if stat.framerrint().bit_is_set() {
952+
Poll::Ready(Err(Error::Framing))
953+
} else if stat.parityerrint().bit_is_set() {
954+
Poll::Ready(Err(Error::Parity))
955+
} else if stat.rxnoiseint().bit_is_set() {
956+
Poll::Ready(Err(Error::Noise))
957+
} else if fifointstat.rxerr().bit_is_set() {
958+
Poll::Ready(Err(Error::Overrun))
959+
} else if stat.rxidle().bit_is_clear() {
960+
Poll::Ready(Ok(()))
961+
} else if stat.start().bit_is_set() {
962+
Poll::Ready(Ok(()))
963+
} else {
964+
Poll::Pending
965+
}
966+
})
967+
.await?;
968+
969+
embassy_time::Timer::after_micros(buffer_config.polling_rate).await;
961970
}
962971
}
963972
Ok(bytes_read)
@@ -1477,16 +1486,31 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
14771486
T::rx_waker().wake();
14781487
}
14791488

1489+
if stat.start().bit_is_set() {
1490+
regs.intenclr().write(|w| w.startclr().set_bit());
1491+
T::rx_waker().wake();
1492+
}
1493+
14801494
let fifointstat = regs.fifointstat().read();
14811495
if fifointstat.txerr().bit_is_set() {
14821496
regs.fifointenclr().write(|w| w.txerr().set_bit());
14831497
T::tx_waker().wake();
14841498
}
14851499

1500+
if fifointstat.txlvl().bit_is_set() {
1501+
regs.fifointenclr().write(|w| w.txlvl().set_bit());
1502+
T::tx_waker().wake();
1503+
}
1504+
14861505
if fifointstat.rxerr().bit_is_set() {
14871506
regs.fifointenclr().write(|w| w.rxerr().set_bit());
14881507
T::rx_waker().wake();
14891508
}
1509+
1510+
if fifointstat.rxlvl().bit_is_set() {
1511+
regs.fifointenclr().write(|w| w.rxlvl().set_bit());
1512+
T::rx_waker().wake();
1513+
}
14901514
}
14911515
}
14921516

0 commit comments

Comments
 (0)