-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
RP2/machine_uart.c: Fix poll ioctl. #7552
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
Conversation
- The RX IRQ does not trigger if the FIFO is less than the trigger level.
- Use machine_uart_any to check for readability to drain the RX FIFO.
* The RX IRQ does not trigger if the FIFO is less than the trigger level. * Use machine_uart_any to check for readability to drain the RX FIFO.
90f0aa6
to
19e16d9
Compare
Ok, so I now understand what is going on. Maybe the solution is to then change the FIFO level to 1 byte (so 1 byte in the FIFO triggers the RX IRQ)? @robert-hh what do you suggest here? At the moment it seems that (Is it true that the RX FIFO is enabled and the trigger level is above 1?) |
Edit: Just checking for readable in machine_uart_ioctl() is indeed better that uart_drain_rx_fifo(), since the latter discards data when the ring buffer is full. |
Where does it drain the FIFO if no chars are in the buffer? Inspecting the code, I see: STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000; <-- t=time_us_64() if timeout==0
uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000;
uint8_t *dest = buf_in;
for (size_t i = 0; i < size; i++) {
// Wait for the first/next character
while (ringbuf_avail(&self->read_buffer) == 0) { <-- assume nothing on ringbuf
if (time_us_64() > t) { // timed out <-- condition will pass if timeout==0
if (i <= 0) { <-- no characters read, condition passes
*errcode = MP_EAGAIN; <-- EAGAIN but possible bytes in FIFO
return MP_STREAM_ERROR;
} else {
return i;
}
}
... |
A few line down the road within the while loop, if timeout did not expire.
|
But if timeout==0 it can return EAGAIN while there are bytes waiting in the hardware FIFO. |
Indeed. So I could add a single drain upfront the reading loop, of check for timeout being at least one char time, like timeout_char. |
Or change the |
Just to add that as a second condition into the while statement would not work, because the data would not get to the ring buffer. Adding drain ahead is more robust. |
True.
But couldn't that possibly lead to data loss, if the ringbuf overruns at that point? So maybe only drain at the start if the ringbuf is empty? |
It could. But in a situation where the data is sent faster than consumed there will be most likely anyhow data loss. But I can change that. |
Merged in 2e62e13 |
add support for array.extend(iterable) - fixes micropython#3913