I am working on a project using ESP32-S with ESP-IDF 4.3.1, the device receives UART data with 2000000 Baud rate, rx fifo full threshold is 120 bytes, uart isr is in IRAM. The problem is that the UART rx fifo gets overflowed when a large amount of data is received at once without having delays between the incoming data bytes which leads to data loss.
I analyzed the problem and found that the default uart_isr execution time is relatively long (about 60 us in my case) and the 128 bytes rx fifo ovelflows during the execution of the isr.
I have tried three solutions but couldn't get it working:
- Reducing the rx fifo threshold to 60 bytes instead of 120, so there is more time between the isr is triggered and the fifo overflow. This solution enhanced the uart performance but it resulted in doubling the rate of triggering the isr which I can't afford
- Trying to make a modified lighter ISR with a lower execution time. I found that the most time consuming parts of the default isr are:
- uart_hal_read_rxfifo(&(uart_context[uart_num].hal), p_uart->rx_data_buf, &rx_fifo_len);
- xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)
- Increasing the size of the UART RX FIFO, since I am using only one UART and according to the reference manual, The RX FIFO size can be increased from 128 to 256 or 512 bytes. I tried:
- WRITE_PERI_REG(UART_MEM_CONF_REG(uart_port),0x110); so both the TX and RX FIFOs sizes are set to 256 bytes
- Changed the FIFO full threshold to 200 bytes
- Changed SOC_UART_FIFO_LEN in soc_caps.h file from 128 to 256