Search code examples
taskdelayinterruptfreertos

How to handle timeout in FreeRTOS - wake up task from interrupt before vTaskDelay expires?


Can I wake up task before vTaskDelay expires?

I have code like this:

In the task (hnd_uart_task) code:

transmit_frame();
vTaskDelay(100);  // task should wait 100 ticks or be woken up by uart ISR
parse_response();

UART Interrupt:

// if byte was received
BaseType_t xYieldRequired = xTaskResumeFromISR(hnd_uart_task);
portYIELD_FROM_ISR(xYieldRequired);

Solution

  • Instead of using vTaskDelay(), you can use task notifications with timeout.

    USART Interrupt:

    // if byte was received
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(hnd_uart_task, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    

    Task Code:

    transmit_frame();
    ulTaskNotifyTake(pdTRUE, 100);
    parse_response();
    

    ulTaskNotifyTake(pdTRUE, 100) returns when a task notification is received from the ISR, or when 100 tick timeout period elapses.

    But as @Jacek Ślimok pointed out, a byte-by-byte parsing may not be good idea. The exact method depends on the protocol used. But in general, you set up your DMA or interrupts to fill a reception buffer with incoming bytes. For example, when parsing Modbus frames, you can use idle line detection hardware interrupt and give notification to a task which parses the RX buffer.