0
0
FreeRTOSprogramming~5 mins

ISR-to-task notification pattern in FreeRTOS

Choose your learning style9 modes available
Introduction

This pattern helps a program quickly tell a task that something important happened in an interrupt. It avoids waiting and keeps the program fast and responsive.

When a hardware event like a button press or sensor signal happens and a task needs to respond.
When an interrupt finishes reading data and a task should process that data.
When you want to wake up a task from sleep as soon as an interrupt occurs.
When you want to avoid using slow or complex communication methods between interrupts and tasks.
Syntax
FreeRTOS
void ISR_Handler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(TaskHandle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void Task(void *pvParameters) {
    for(;;) {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        // Handle event
    }
}

vTaskNotifyGiveFromISR() sends a notification from the interrupt to the task.

ulTaskNotifyTake() waits in the task until the notification arrives.

Examples
This is the interrupt code that notifies the task and requests a context switch if needed.
FreeRTOS
void ISR_Handler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(TaskHandle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
This task waits forever until it gets a notification from the ISR, then runs its code.
FreeRTOS
void Task(void *pvParameters) {
    for(;;) {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        // Process event here
    }
}
Sample Program

This program creates a task that waits for notifications from an ISR. When the ISR runs, it notifies the task, which then prints a message.

FreeRTOS
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include <stdio.h>

TaskHandle_t TaskHandle = NULL;

void ISR_Handler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(TaskHandle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void Task(void *pvParameters) {
    for(;;) {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        // Simulate handling event
        printf("Task notified by ISR\n");
    }
}

int main(void) {
    xTaskCreate(Task, "Task", configMINIMAL_STACK_SIZE, NULL, 1, &TaskHandle);
    vTaskStartScheduler();
    return 0;
}
OutputSuccess
Important Notes

Always use portYIELD_FROM_ISR() to switch to the task immediately if it has higher priority.

Make sure the task handle is valid before using it in the ISR.

Notifications are faster and use less memory than semaphores or queues for simple signaling.

Summary

The ISR-to-task notification pattern lets interrupts quickly tell tasks to run.

Use vTaskNotifyGiveFromISR() in the ISR and ulTaskNotifyTake() in the task.

This method is efficient and keeps your program responsive.