Page 1 of 1

UART Timeout doesn't work

Posted: Fri Jul 21, 2017 7:43 pm
by kilobyte_ch
I want to interface with another MCU via UART AT Commands. Sending those commands works perfectly, but I'm always stuck in the receive function. Any idea? My code:

Code: Select all

#define BUF_SIZE (1024)

static void at_task()
{
    const int uart_num = UART_NUM_1;
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .rx_flow_ctrl_thresh = 122,
    };
    //Configure UART1 parameters
    uart_param_config(uart_num, &uart_config);
    //Set UART1 pins(TX: IO4, RX: I05, RTS: IO18, CTS: IO19)
    uart_set_pin(uart_num, 4, 5, 18, 19);
    //Install UART driver (we don't need an event queue here)
    //In this example we don't even use a buffer for sending data.
    uart_driver_install(uart_num, 2048, 0, 0, NULL, 0);

    uint8_t* data = (uint8_t*) malloc(BUF_SIZE);
    uint8_t mystring[] = "at+version\r\n";
    while(1) {
        printf("Sending data to at \n");
        //Write data back to UART
        uart_write_bytes(uart_num, (const char*)mystring, strlen((const char*)mystring));
        printf("Finished writing \n");
        //Read data from UART
        printf("Starting reading \n");
        int len = uart_read_bytes(uart_num, data, 1024, 5 / portTICK_RATE_MS);
        printf("Finished reading, %d bytes \n", len);
        
        if(len > 0) {
            printf("Got data: %s \n", data);
        }

        vTaskDelay(500 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    printf("ESP32 alive \n");
    //A uart read/write example without event queue;
    xTaskCreate(at_task, "at_task", 1024, NULL, 10, NULL);
}

Re: UART Timeout doesn't work

Posted: Sat Jul 22, 2017 5:20 am
by WiFive
5 / portTICK_RATE_MS = 0

Re: UART Timeout doesn't work

Posted: Mon Jul 31, 2017 9:27 am
by kilobyte_ch
hmm, but it doesn't work either with 50, 500, 500 / tickrate.

Re: UART Timeout doesn't work

Posted: Mon Jul 31, 2017 6:35 pm
by RobinC
I had the same issue and found (though experimentation) that 100 / portTICK_RATE_MS was the shortest timeout that worked consistently for me.

This implementation is somewhat broken for the way I've normally processed uart data in embedded apps. The call to uart_read_bytes() returns when either the length provided or the timeout is met. The only near real-time way to process the uart data stream is to make the call with a length of 1 (or in the event handler as shown below). 100ms is way too long of a timeout when you consider that, at 230400 bps, you get a new character roughly every 50us (20 char per 1ms or 2000 char per 100ms, the minimum timeout).

I ended up processing the uart buf in the handle_uart_event() handler with:

Code: Select all

        case UART_DATA:
            uart_get_buffered_data_len(uart_ndx, &buffered_size);
            len = 0;
            if (buffered_size > 0) {
                data = (uint8_t*) malloc(BUF_SIZE);
                len = uart_read_bytes(uart_ndx, data, buffered_size, 100 / portTICK_RATE_MS);
                if (len > 0) {
                    if (dvair_uart_data_received_callback != NULL) {
                        dvair_uart_data_received_callback(uart_ndx, (const char *)data, len);
                    }
                }
                free(data);
            }
            ESP_LOGD(TAG, "data[%d], event len: %d; buffered len: %d; read len: %d", uart_ndx, event->size, buffered_size, len);
            break;
Robin