embassy
embassy copied to clipboard
Add efficient polling functions to BufferedUart (add them to traits too?)
It might be useful to read only the data that the BufferedUart accumulated, without waiting for any data to come in.
I have found the following way to do this:
let mut b_fut = uart.read_byte();
let waker = futures::task::noop_waker();
let mut context = Context::from_waker(&waker);
if let core::task::Poll::Ready(r) = b_fut.poll_unpin(&mut context) {
let read = unwrap!(r);
// read something!
} else {
// nope, nothing available
}
It basically creates a no-op waker, polls the read_byte future one time and drops it afterwards, canceling the async operation. It works, but requires quite a lot of boilerplate and executor-agnostic feature of embassy, which ¿might? produce less efficient code.
It would be nice to have a function purposed for reading the buffer without actually touching the uart hardware
If you're in async context, you can reuse the "current" waker.
let buf: &[u8] = poll_fn(|cx| {
Poll::Ready(match uart.poll_fill_buf(cx) {
Poll::Ready(x) => x,
Poll::Pending => &[],
}
}).await;
If you're not in an async context yep, you have to "invent" a waker which requires executor-agnostic (which does increase code size a bit).
A fill_buf fn that's equivalent to poll_fill_buf but doesn't use wakers could be a nice addition, yes! Not sure if it should be a new method in embassy::io::AsyncBufRead, or a separate trait, or just inherent methods in the BufferedUart...
I kinda lean towards separate trait, but maybe adding it to AsyncBufRead might be better. Not sure here