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.
0
0
ISR-to-task notification pattern in FreeRTOS
Introduction
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.