Page 1 of 1

uart_read_bytes timeout problem

Posted: Thu Oct 15, 2020 5:25 pm
by bonadio
Hello

I found a strange behavior on uart_read_bytes. I am using IDF 3.3.2 but tried on the IDF 4.1 and got the same result.

When I pass the timeout as 0 if thereis anything on the receiver buffer it reads it and immediately returns (0.040ms) what is correct, but when I pass any other timeout if there is anything on the receiver buffer it takes almost 9ms to return.
If there is nothing on the receiver buffer the timeout works correctly.

Am I missing something?

The following code demonstrate that

Code: Select all

#include <esp_log.h>
#include <string>
#include "sdkconfig.h"
#include "driver/uart.h"

#define RX_PIN 19
#define TX_PIN 18
#define BUF_SIZE (1024)

static char TAG_MAIN[]="uart_readbytes";

extern "C" {
	void app_main(void);
}

unsigned long IRAM_ATTR mmillis()
{
    //return (unsigned long) (esp_timer_get_time() / 1000LL);
	return (unsigned long) (esp_timer_get_time() );
}
uint8_t timeout = 30;

void app_main(void)
{
	ESP_LOGD(TAG_MAIN,"Serial Startup\n");

    uart_config_t uart_config = {
        .baud_rate = 10400,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    uart_param_config(UART_NUM_1, &uart_config);
    ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, BUF_SIZE*2, 0, 0, NULL, 0));
    ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, TX_PIN, RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
	
	while (true)
	{
		uint8_t nbuff[1]={0};
		unsigned long ini =  mmillis();
		uint8_t c = 0x55;
		esp_err_t ret = uart_write_bytes(UART_NUM_1, (const char*) &c , 1);
		int read_len = uart_read_bytes(UART_NUM_1, nbuff, 1, timeout / portTICK_RATE_MS);;
		ESP_LOGD(TAG_MAIN,"bytes received: %d  time: %lu\n",read_len,  mmillis()-ini);
		vTaskDelay(1000 / portTICK_RATE_MS);
	}
	
}

Re: uart_read_bytes timeout problem

Posted: Thu Oct 15, 2020 8:35 pm
by PeterR
When I pass the timeout as 0 if thereis anything on the receiver buffer it reads it and immediately returns (0.040ms) what is correct, but when I pass any other timeout if there is anything on the receiver buffer it takes almost 9ms to return.
when I pass any other timeout
Are you sure? Do you mean that when timeout =1 you get a delay of around 9mS?
I would imagine that a timeout of 100mS would give you something between 90mS and 100mS + other high priority task demands.
Its a question of tick quantisation. You might be 0.000000000000000000001 mS (or less) from the next timer tick & so a delay of 1 tick interval might be no time at all.
Typically the scheduler clock period is 10mS so a delay of 1 (tick) might be (next too) none or 10mS + other higher priority task demand + bus contension etc, etc.
Run a loop, maybe add a min/max class (every serious engineer should have one) and take a statistical view. The (infrequent) deviations will help form a view.

Re: uart_read_bytes timeout problem

Posted: Thu Oct 15, 2020 9:07 pm
by bonadio
Hi @PeterR

I tested a little further and when the timeout >= 20 and have receiver buffer I get the response in
D (2675) uart_readbytes: bytes received: 1 time: 7995
D (3675) uart_readbytes: bytes received: 1 time: 7955
D (4675) uart_readbytes: bytes received: 1 time: 7915
D (5675) uart_readbytes: bytes received: 1 time: 8644

When timeout < 20 and have receiver buffer I get instant response

D (2675) uart_readbytes: bytes received: 1 time: 75
D (3675) uart_readbytes: bytes received: 1 time: 33
D (4675) uart_readbytes: bytes received: 1 time: 33
D (5675) uart_readbytes: bytes received: 1 time: 33

Seems the anything greater them 1 tick (10ms) for timeout fires the problem.

Re: uart_read_bytes timeout problem

Posted: Thu Oct 15, 2020 10:12 pm
by WiFive

Re: uart_read_bytes timeout problem

Posted: Fri Oct 16, 2020 1:52 am
by bonadio
Hi @WiFive

I tried that patch but did not work

[]s