Skip to content

Rx fifo latency fix #4328

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

Merged
merged 17 commits into from
Mar 8, 2018
Merged
Changes from 10 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions cores/esp8266/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,33 @@ 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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use inverted logic. Instead, use direct logic to detect an early return or break, and leave the 3 lines of code free-standing after that.
E.g.:
if(nextPos == rpos)
return;
uint8_t data = ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the code would look like this:
'
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;
}
}
'

I agree that code looks better, but I do have a concern. The line that initizes data with a value from the fifo also drains the fifo by 1 byte. So that line of code really can't be executed in the case we want to execute the break. I'm not sure if the compiler is allowed to rearrange that line to be before the if. If it can do that with any optimization level then we'd have a bug. So while it isn't quite as clean I'd suggest putting that code in an else (I can keep the current order though so the break is first). However, if you are sure this is legal then I can make that change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind. It's late and I was overthinking this. Of course a compile can't reorder this if it might affect results. I'll test this change with my test case and if it passes will push the change.

uint8_t data = USF(uart->uart_nr);
uart->rx_buffer->buffer[uart->rx_buffer->wpos] = data;
uart->rx_buffer->wpos = nextPos;
}
else {
// Stop copying if rx buffer is full
break;
}
}
}

int uart_peek_char(uart_t* uart)
{
if(uart == NULL || !uart->rx_enabled) {
Expand All @@ -99,6 +126,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];
}

Expand All @@ -119,10 +151,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);
}


Expand All @@ -135,14 +164,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);
}
Expand Down