Time-Critical function with "taskENTER_CRITICAL()" ?
Posted: Thu May 03, 2018 8:31 pm
Hello there,
I am working on a application that uses uart for communication via a rs485 bus and wifi.
The rs485 host requires precise timing in means of not pausing the transmission in-between the data-packet and to disable the transmitter immediately after the last byte has been sent. Without running wifi this is no problem. But as soon as wifi is active it causes occasional errors by interrupting the data transmission by ~1ms in-between the packet or prior disabling the transmitter.
During research, I came across that topic: https://esp32.com/viewtopic.php?t=1703 describing the use of taskENTER_CRITICAL()/ taskEXIT_CRITICAL(). Since it seems to cover my problem I modified my code as follows:
But it did not solve the issue.
Now the core panics printing this:
This crash maybe is caused by uart.c using freeRTOS APIs. Using these in a critical section is not allowed according to https://www.freertos.org/taskENTER_CRIT ... TICAL.html .
I also tried to assign the highest priority to the task calling the rs485_send function prior experimenting with critical section but this did not change anything.
Does somebody have a idea how to deal with that timing issue.
The data packets are around 300Bytes in size and are transmitted in less than 6ms. 'Basically' I need to pause everything that could interfere with the transmission for that short timespan.
Kind regards
I am working on a application that uses uart for communication via a rs485 bus and wifi.
The rs485 host requires precise timing in means of not pausing the transmission in-between the data-packet and to disable the transmitter immediately after the last byte has been sent. Without running wifi this is no problem. But as soon as wifi is active it causes occasional errors by interrupting the data transmission by ~1ms in-between the packet or prior disabling the transmitter.
During research, I came across that topic: https://esp32.com/viewtopic.php?t=1703 describing the use of taskENTER_CRITICAL()/ taskEXIT_CRITICAL(). Since it seems to cover my problem I modified my code as follows:
Code: Select all
uint16_t rs485_send(uint8_t *data, uint16_t len){
static const char *TAG = "send_rs485";
uint16_t sent_bytes = 0;
portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;
gpio_set_level(RS485_TXEN_PIN,1); //select rs485 comm type: transmitter
taskENTER_CRITICAL(&myMutex);
sent_bytes = uart_write_bytes(RS485_UART, (char*) data, len);
if(uart_wait_tx_done(RS485_UART, 2) == ESP_ERR_TIMEOUT) ESP_LOGE(TAG,"timeout occurred during rs485 tx");
gpio_set_level(RS485_TXEN_PIN,0); //select rs485 comm type: receiver
taskEXIT_CRITICAL(&myMutex);
return sent_bytes;
}
Now the core panics printing this:
Code: Select all
Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0)
[...]
0x40087a46: vListInsert at C:/esp/esp-idf/components/freertos/list.c:188 (discriminator 1)
0x4008581f: vTaskPlaceOnEventList at C:/esp/esp-idf/components/freertos/tasks.c:3529
0x40086780: xQueueGenericReceive at C:/esp/esp-idf/components/freertos/queue.c:2037
0x40127d8d: uart_wait_tx_done at C:/esp/esp-idf/components/driver/uart.c:1153
I also tried to assign the highest priority to the task calling the rs485_send function prior experimenting with critical section but this did not change anything.
Does somebody have a idea how to deal with that timing issue.
The data packets are around 300Bytes in size and are transmitted in less than 6ms. 'Basically' I need to pause everything that could interfere with the transmission for that short timespan.
Kind regards