ESP32 UART receive ring buffer

egoncalves
Posts: 22
Joined: Thu Jan 23, 2020 9:31 am

ESP32 UART receive ring buffer

Postby egoncalves » Thu Mar 19, 2020 2:16 pm

Hi

I'm experiencing an abnormal behaviour regarding receiving a message on UART1 .
The ESP32 is connected through a UART to another processor, an Cortex-M3, that acts as a specialised measuring system.
The ESP32 sends a message to the Cortex-M3 specifying what measurement should be made and its parameters.
When the measurement is done the Cortex-M3 sends a message back to the ESP32 with the measurement results.
It is here that the problem resides. The ESP32 does not seem to cope with the speed of the Cortex-M3.
I'm using a baudrate of 57600. I have tried with 19200 and the problem persists.
The problem is solved when on the Cortex-M3 I put a delay of about 1ms between consecutive message bytes.
Somehow the FIFO or ring buffer mechanisms on the ESP32 do not seem to be working properly...

This is the code to initialise the UART:

Code: Select all

esp_err_t UART_Initialise (uart_port_t port, gpio_num_t pinTXD, gpio_num_t pinRXD, unsigned int bufferSize, uint32_t baudrate)
{
    esp_err_t err = ESP_OK;

    if ( UART_Initialised )
        return ESP_OK;
    UART_port = port;

    /// ESP IDF compatible UART configuration struct
    uart_config_t uartConfig;
    uartConfig.baud_rate = baudrate;
    uartConfig.data_bits = UART_DATA_8_BITS;
    uartConfig.parity    = UART_PARITY_DISABLE;
    uartConfig.stop_bits = UART_STOP_BITS_1;
    uartConfig.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
    uartConfig.rx_flow_ctrl_thresh = 0;
    uartConfig.use_ref_tick = false;

    err = uart_param_config (UART_port, &uartConfig);
	while(err != ESP_OK);
    if ( err != ESP_OK)
        return ESP_FAIL;
    err = uart_set_pin (UART_port, pinTXD, pinRXD, UART_PIN_NO_CHANGE/*pinRTS*/, UART_PIN_NO_CHANGE/*pinCTS*/);
    if ( err != ESP_OK)
        return ESP_FAIL;
    err = uart_driver_install (UART_port, bufferSize, 0, 0, NULL, 0);
    if ( err != ESP_OK)
        return ESP_FAIL;

    UART_Initialised = true;

    return ESP_OK;
}
which is called as:

Code: Select all

    res = UART_Initialise ( UART_NUM_1, UART_TX_PIN, UART_RX_PIN, 1000/*buffer size*/, 57600/*baudrate*/ );
The code for receiving a frame is:

Code: Select all

        uint8_t frame_byte;

        while (true)
        {
            uint16_t ticks_to_wait = 10;
            rd = uart_read_bytes (UART_port, &frame_byte, 1/*length*/, ticks_to_wait);
            if ( rd == -1 )                         return ESP_FAIL;
            if ( rd ==  1 )                         break;
            time_waited += ticks_to_wait;
            if ( time_waited >= timeout_ticks )     return ESP_FAIL;
        }
When receiving the first 2 bytes of the message are received, but the remaining don't seem to show up and a timeout is generated.

Any ideas how to diagnose this?
Are there any examples that use this type of protocol communication?

thanks

ESP_Sprite
Posts: 9759
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32 UART receive ring buffer

Postby ESP_Sprite » Sun Mar 22, 2020 12:09 pm

Not sure if it helps, but atm UartConfig contains crap for all the fields (current or future) you don't initialize. Suggest doing

Code: Select all

uart_config_t uartConfig={};
instead.

samc77
Posts: 7
Joined: Sun Feb 16, 2020 8:08 pm

Re: ESP32 UART receive ring buffer

Postby samc77 » Sun Mar 22, 2020 9:12 pm

Hi,

well i can't offer a better solution, but can confirm that I am seeing the same issue:
Sending data from Windows through the UART0; tried different eval PCBs, most promiment is the ESP32-WROVER-KIT.
Different data-rates tried, up to 2Mbit. Nothing changes.
When sending longer packets (2048 bytes) there are very often errors in the received packet, frame errors.
(The frame errors can only be seen as such after adding debug output to the ISR.)

Also my only solution after trying a lot of things is to add a delay between each two bytes on Windows side. Not a very good solution.

At higher data-rates there is a 2nd issue, the UART RX FIFO threshold is set to 120 of 128 bytes which gives only 8 bytes headroom.
Setting this to 64 fixed that 2nd issue.

uart.c
#define UART_FULL_THRESH_DEFAULT (64)


Would be very interesting to hear how this issue can be solved!

Thanks

justbarran
Posts: 1
Joined: Tue Mar 09, 2021 1:35 am

Re: ESP32 UART receive ring buffer

Postby justbarran » Tue Mar 09, 2021 1:39 am

Might be good to read the data from the buffer and store it in your own "buffer" so the FIFO buffer doesn't get fulled.

[Codebox]
l_count = 0;
l_length = 0;
get_us = esp_timer_get_time();
stop_us = INTERBYTE_MS*1000;
while((l_count==0) && (l_size < reply_limit))
{
l_length = uart_read_bytes(s_port,l_temp,MESSAGE_MAX_LEN,1/portTICK_RATE_MS);
if(l_length>0)
{
for(int i = 0;i<l_length;i++)
{
output[l_size]=l_temp;
l_size++;
}
l_length = 0;
l_count = 0;
get_us = esp_timer_get_time();
}
if((esp_timer_get_time()-get_us)>stop_us)
{
l_count=1;
}
}
[/Codebox]

Who is online

Users browsing this forum: Google [Bot] and 171 guests