1
0
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:
Maurice Ribble 2018-03-08 10:16:14 -05:00 committed by Develo
parent 61cd8d8385
commit 7f0b9d1be9

View File

@ -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);