-
Notifications
You must be signed in to change notification settings - Fork 173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UartDriver as embedded_io::Read
blocks until buffer is full
#475
Comments
UPDATED: You might be right to request the semantics you request as I polled the "Embedded Rust" Matrix channel, and it seems the consensus is it should operate as you intuitively expect. Though - I must say and the other folks agreed - this is not explicitly documented on the ( With that said, I just pushed a potential fix to The reason why I did not accept your proposal from above ^^^ verbatim is because it has several problems. For completeness, let me comment on these (look for the comments marked with "(Ivan)"): /// Read multiple bytes into a slice; block until specified timeout
pub fn read(&self, buf: &mut [u8], delay: TickType_t) -> Result<usize, EspError> {
// uart_read_bytes() returns error (-1) or how many bytes were read out
// 0 means timeout and nothing is yet read out
// (Ivan) -1 also might mean a timeout. -1 is returned when `uart_read_bytes` cannot lock the internal semaphore, which
// might happen if multiple threads try to call this `read` method
let available = self.count()?;
if (available > buf.len()) {
// should we throw? or only read as many as the buffer has space for
// (Ivan) We should only read as many bytes as the buffer has space for
}
// (Ivan) The problem with this code is when available = 0
// In this case, the call below will return immediately (as that's how `uart_read_bytes` is implemented)
// - yet - you want it to block until at least one byte becomes available, or until the `delay` expires
let len = unsafe {
uart_read_bytes(
self.port(),
buf.as_mut_ptr().cast(),
available as u32,
delay,
)
};
if len >= 0 {
Ok(len as usize)
} else {
Err(EspError::from_infallible::<ESP_ERR_INVALID_STATE>())
}
} |
@DaneSlattery ^^^ |
That fixes it, thank you! Happy with the solution you came to. |
In the below code snippet, modified from the uart loopback.
We know that the uart TX has written 1 byte.
The receive buffer is
[0;10]
, which is typical when we don't know how large the receive buffer is.In this case, the read blocks forever, instead of popping 1 byte from the UART buffer (into
buf
) and returning1
. If the buffer is[0;1]
, the read returns instantly.This means that the
embedded_io::Read
contract is not being upheld:The approach in
UartRxDriver
is to calluart_read_bytes
withlength=buffer.len()
.I propose the following:
The text was updated successfully, but these errors were encountered: