mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
Rx fifo latency fix (#4328)
* Flush the rx fifo when checking available bytes in fifo. This gives a more correct result rather than waiting until either the fifo is full or until a serial rx timeout occurs. * When rx_avaiable is checked return rx_buffer plus rx_fifo. Then during rx_read and rx_peek functions copy over the data in the fifo as needed. * Clean up early out case. * Set the rx full fifo ISR to trigger a little sooner. This makes the uart rx isr more robust in cases where the ISR can't trigger very fast
This commit is contained in:
parent
61cd8d8385
commit
7f0b9d1be9
@ -91,6 +91,31 @@ size_t uart_resize_rx_buffer(uart_t* uart, size_t new_size)
|
||||
return uart->rx_buffer->size;
|
||||
}
|
||||
|
||||
inline size_t uart_rx_buffer_available(uart_t* uart) {
|
||||
if(uart->rx_buffer->wpos < uart->rx_buffer->rpos) {
|
||||
return (uart->rx_buffer->wpos + uart->rx_buffer->size) - uart->rx_buffer->rpos;
|
||||
}
|
||||
return uart->rx_buffer->wpos - uart->rx_buffer->rpos;
|
||||
}
|
||||
|
||||
inline size_t uart_rx_fifo_available(uart_t* uart) {
|
||||
return (USS(uart->uart_nr) >> USRXC) & 0x7F;
|
||||
}
|
||||
|
||||
// Copy all the rx fifo bytes that fit into the rx buffer
|
||||
inline void uart_rx_copy_fifo_to_buffer(uart_t* uart) {
|
||||
while(uart_rx_fifo_available(uart)){
|
||||
size_t nextPos = (uart->rx_buffer->wpos + 1) % uart->rx_buffer->size;
|
||||
if(nextPos == uart->rx_buffer->rpos) {
|
||||
// Stop copying if rx buffer is full
|
||||
break;
|
||||
}
|
||||
uint8_t data = USF(uart->uart_nr);
|
||||
uart->rx_buffer->buffer[uart->rx_buffer->wpos] = data;
|
||||
uart->rx_buffer->wpos = nextPos;
|
||||
}
|
||||
}
|
||||
|
||||
int uart_peek_char(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL || !uart->rx_enabled) {
|
||||
@ -99,6 +124,11 @@ int uart_peek_char(uart_t* uart)
|
||||
if (!uart_rx_available(uart)) {
|
||||
return -1;
|
||||
}
|
||||
if (uart_rx_buffer_available(uart) == 0) {
|
||||
ETS_UART_INTR_DISABLE();
|
||||
uart_rx_copy_fifo_to_buffer(uart);
|
||||
ETS_UART_INTR_ENABLE();
|
||||
}
|
||||
return uart->rx_buffer->buffer[uart->rx_buffer->rpos];
|
||||
}
|
||||
|
||||
@ -119,10 +149,7 @@ size_t uart_rx_available(uart_t* uart)
|
||||
if(uart == NULL || !uart->rx_enabled) {
|
||||
return 0;
|
||||
}
|
||||
if(uart->rx_buffer->wpos < uart->rx_buffer->rpos) {
|
||||
return (uart->rx_buffer->wpos + uart->rx_buffer->size) - uart->rx_buffer->rpos;
|
||||
}
|
||||
return uart->rx_buffer->wpos - uart->rx_buffer->rpos;
|
||||
return uart_rx_buffer_available(uart) + uart_rx_fifo_available(uart);
|
||||
}
|
||||
|
||||
|
||||
@ -135,14 +162,7 @@ void ICACHE_RAM_ATTR uart_isr(void * arg)
|
||||
return;
|
||||
}
|
||||
if(USIS(uart->uart_nr) & ((1 << UIFF) | (1 << UITO))){
|
||||
while((USS(uart->uart_nr) >> USRXC) & 0x7F){
|
||||
uint8_t data = USF(uart->uart_nr);
|
||||
size_t nextPos = (uart->rx_buffer->wpos + 1) % uart->rx_buffer->size;
|
||||
if(nextPos != uart->rx_buffer->rpos) {
|
||||
uart->rx_buffer->buffer[uart->rx_buffer->wpos] = data;
|
||||
uart->rx_buffer->wpos = nextPos;
|
||||
}
|
||||
}
|
||||
uart_rx_copy_fifo_to_buffer(uart);
|
||||
}
|
||||
USIC(uart->uart_nr) = USIS(uart->uart_nr);
|
||||
}
|
||||
@ -152,7 +172,11 @@ void uart_start_isr(uart_t* uart)
|
||||
if(uart == NULL || !uart->rx_enabled) {
|
||||
return;
|
||||
}
|
||||
USC1(uart->uart_nr) = (127 << UCFFT) | (0x02 << UCTOT) | (1 <<UCTOE );
|
||||
// UCFFT value is when the RX fifo full interrupt triggers. A value of 1
|
||||
// triggers the IRS very often. A value of 127 would not leave much time
|
||||
// for ISR to clear fifo before the next byte is dropped. So pick a value
|
||||
// in the middle.
|
||||
USC1(uart->uart_nr) = (100 << UCFFT) | (0x02 << UCTOT) | (1 <<UCTOE );
|
||||
USIC(uart->uart_nr) = 0xffff;
|
||||
USIE(uart->uart_nr) = (1 << UIFF) | (1 << UIFR) | (1 << UITO);
|
||||
ETS_UART_INTR_ATTACH(uart_isr, (void *)uart);
|
||||
|
Loading…
x
Reference in New Issue
Block a user