undocumented UART Hardware problem?
Posted: Mon May 04, 2020 11:43 pm
We ran into a problem with the UART hardware that doesn't seem documented. In our testing this problem only appears when we also use wifi, but we think it might just be triggered by multitasking in general, not necessarily wifi specifically.
The problem is that sometimes when we read the FIFO, its hardware read index does not automatically increment as normal, even though it still automatically decrements its hardware FIFO counter. As a result, the next time we read the FIFO we get the same byte read last time, and this pattern continues with every byte being shifted. Here is an example sequence of what might be received in the UART and how it might be read:
Byte Received Counter (before read) Read Index (before read) Byte Read Counter (after read) Read Index (after read)
1 1 50 1 0 51
2 1 51 2 0 51
3 1 51 2 0 52
4 1 52 3 0 53
5 1 53 4 0 54
The read index shown in yellow is the one that failed to update after the read, causing perpetual FIFO delay/misalignment in bytes read. If the malfunction happens again the shift becomes 2, and so on.
Here is example code that could observe the malfunction above:
A solution is not to simply do extra reads of the FIFO when the counter is zero, because this messes up the read index as well. In looking through the source code we found the following function that seems to work around this hardware malfunction by continually reading the FIFO until it is really empty, based on either its counter or read index?
However the “hardware issue” referenced in the manual says nothing about the possibility of the read index failing to increment, but rather describes a failure of the hardware FIFO reset function on UARTs 1 or 2 (which is a separate problem). Yet the code itself appears to successfully reset our malfunction and did so when we tested it. This isn’t really a solution though because you can unknowingly end up with any number of bad reads until you finally call this code to reset the FIFO.
Is there any reference to this particular failure to increment the UART index anywhere in the documentation? What would be the best recommended software fix so the FIFO can be read correctly without incident?
The problem is that sometimes when we read the FIFO, its hardware read index does not automatically increment as normal, even though it still automatically decrements its hardware FIFO counter. As a result, the next time we read the FIFO we get the same byte read last time, and this pattern continues with every byte being shifted. Here is an example sequence of what might be received in the UART and how it might be read:
Byte Received Counter (before read) Read Index (before read) Byte Read Counter (after read) Read Index (after read)
1 1 50 1 0 51
2 1 51 2 0 51
3 1 51 2 0 52
4 1 52 3 0 53
5 1 53 4 0 54
The read index shown in yellow is the one that failed to update after the read, causing perpetual FIFO delay/misalignment in bytes read. If the malfunction happens again the shift becomes 2, and so on.
Here is example code that could observe the malfunction above:
Code: Select all
while (1)
{
if (UART [1]->status.rxfifo_cnt)
{
printf ("Counter (before read): %d, Read Index (before read): %d\n", UART [1]->status.rxfifo_cnt, UART [1]->mem_rx_status.rd_addr);
printf ("Byte Read: %d\n", READ_PERI_REG (UART_FIFO_AHB_REG (1)));
printf ("Counter (after read): %d, Read Index (after read): %d\n", UART [1]->status.rxfifo_cnt, UART [1]->mem_rx_status.rd_addr);
}
}
Code: Select all
static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
//Due to hardware issue, we can not use fifo_rst to reset uart fifo.
//See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.
// we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
while(UART[uart_num]->status.rxfifo_cnt != 0 || (UART[uart_num]->mem_rx_status.wr_addr != UART[uart_num]->mem_rx_status.rd_addr)) {
READ_PERI_REG(UART_FIFO_REG(uart_num));
}
return ESP_OK;
}
Is there any reference to this particular failure to increment the UART index anywhere in the documentation? What would be the best recommended software fix so the FIFO can be read correctly without incident?