[Solved] Design pattern: how to cleanly exit from a task that is waiting on a UART queue
Posted: Mon Feb 11, 2019 11:48 am
I have a component which creates a dynamic task that waits on a UART queue for received characters, like so:
I would like the component to delete that dynamic task cleanly when it exits. A simple way would be to write an unusual value to the UART queue myself, in other words make the dynamic task something like this:
...then from my tidy-up code I can do something like this:
However, when I implement this and my tidy-up code runs I get a panic in the ESP32 UART interrupt handler (just where it exits a critical section):
My questions are:
Code: Select all
static void rx_task(void *pvParameters)
{
uart_event_t uart_event;
while (1) {
if (xQueueReceive(_queue_uart, (void *) &uart_event,
(portTickType) portMAX_DELAY)) {
if (uart_event.size > 0) {
//... do stuff with the received data
}
}
}
}
Code: Select all
static void rx_task(void *pvParameters)
{
uart_event_t uart_event;
xSemaphoreTake(_mtx_rx_task_running, (portTickType) portMAX_DELAY);
uart_event.type = UART_DATA;
while (uart_event.type < UART_EVENT_MAX) {
if (xQueueReceive(_queue_uart, (void *) &uart_event,
(portTickType) portMAX_DELAY)) {
if ((uart_event.type == UART_DATA) && (uart_event.size > 0)) {
//... do stuff with the received data
}
}
}
xSemaphoreGive(_mtx_rx_task_running);
}
Code: Select all
uart_event_t uart_event;
uart_event.type = UART_EVENT_MAX;
uart_event.size = 0;
xQueueSend(_queue_uart, (void *) &uart_event, (portTickType) portMAX_DELAY);
xSemaphoreTake(_mtx_rx_task_running, (portTickType) portMAX_DELAY);
xSemaphoreGive(_mtx_rx_task_running);
vTaskDelete(_task_handle_rx);
Code: Select all
Guru Meditation Error: Core 0 panic'ed (IllegalInstruction). Exception was unhandled.
Core 0 register dump:
PC : 0x400e30fa PS : 0x00060630 A0 : 0x00000000 A1 : 0x3ffb3f60
0x400e30fa: uart_rx_intr_handler_default at C:/msys32/home/rob/esp/esp-idf/components/driver/uart.c:1241
- should what I'm suggesting work, if so can anyone spot my deliberate mistake?
- if what I am suggesting is not going to work (e.g. FreeRTOS has some concept of queue ownership which I'm violating, etc.) is there an alternative accepted design pattern for this (e.g. do I have to use queue sets?)?