Bird
Raised Fist0
FreeRTOSprogramming~5 mins

ISR-to-task notification pattern in FreeRTOS

Choose your learning style10 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.

Practice

(1/5)
1. What is the main purpose of the ISR-to-task notification pattern in FreeRTOS?
easy
A. To allow an interrupt to quickly notify a task to run
B. To create a new task from an ISR
C. To pause a task until an interrupt finishes
D. To disable interrupts during task execution

Solution

  1. Step 1: Understand ISR and task roles

    ISRs handle hardware events quickly, tasks do longer processing.
  2. Step 2: Identify notification purpose

    The pattern lets ISR tell a task to run without delay.
  3. Final Answer:

    To allow an interrupt to quickly notify a task to run -> Option A
  4. Quick Check:

    ISR notifies task [OK]
Hint: ISR signals task to run fast using notifications [OK]
Common Mistakes:
  • Thinking ISR creates tasks
  • Believing tasks pause interrupts
  • Confusing disabling interrupts with notifications
2. Which function is correctly used inside an ISR to notify a task in FreeRTOS?
easy
A. vTaskNotifyGiveFromISR()
B. ulTaskNotifyTake()
C. xTaskCreate()
D. vTaskDelay()

Solution

  1. Step 1: Identify ISR notification function

    Inside ISR, use vTaskNotifyGiveFromISR() to notify tasks.
  2. Step 2: Differentiate task functions

    ulTaskNotifyTake() is used in tasks, not ISRs.
  3. Final Answer:

    vTaskNotifyGiveFromISR() -> Option A
  4. Quick Check:

    Notify from ISR = vTaskNotifyGiveFromISR() [OK]
Hint: Use vTaskNotifyGiveFromISR() inside ISR only [OK]
Common Mistakes:
  • Using ulTaskNotifyTake() inside ISR
  • Calling xTaskCreate() in ISR
  • Using vTaskDelay() inside ISR
3. Given this code snippet, what will be the output printed by the task?
void ISR_Handler() {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(taskHandle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void TaskFunction(void *pvParameters) {
    for(;;) {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        printf("Task notified!\n");
    }
}
medium
A. No output, task never notified
B. Task notified! (printed each time ISR runs)
C. Compilation error due to missing parameters
D. Task notified! printed once then stops

Solution

  1. Step 1: Analyze ISR notification call

    ISR calls vTaskNotifyGiveFromISR() to notify the task each time it runs.
  2. Step 2: Check task notification wait

    Task waits indefinitely with ulTaskNotifyTake(), then prints on notification.
  3. Final Answer:

    Task notified! (printed each time ISR runs) -> Option B
  4. Quick Check:

    ISR notifies task -> prints each time [OK]
Hint: Task prints after each ISR notification [OK]
Common Mistakes:
  • Assuming task never wakes
  • Confusing function parameters
  • Thinking output prints only once
4. Identify the error in this ISR-to-task notification code snippet:
void ISR_Handler() {
    vTaskNotifyGive(taskHandle);
}

void TaskFunction(void *pvParameters) {
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    printf("Notified\n");
}
medium
A. printf() cannot be used in tasks
B. Missing infinite loop in TaskFunction
C. Incorrect parameter in ulTaskNotifyTake()
D. Using vTaskNotifyGive() inside ISR instead of vTaskNotifyGiveFromISR()

Solution

  1. Step 1: Check ISR notification function

    vTaskNotifyGive() is not safe inside ISR; must use vTaskNotifyGiveFromISR().
  2. Step 2: Verify task code correctness

    TaskFunction can have single call; infinite loop is common but not error here.
  3. Final Answer:

    Using vTaskNotifyGive() inside ISR instead of vTaskNotifyGiveFromISR() -> Option D
  4. Quick Check:

    ISR notification function must end with FromISR [OK]
Hint: Use FromISR suffix functions inside ISRs [OK]
Common Mistakes:
  • Calling task functions inside ISR
  • Ignoring FromISR suffix importance
  • Assuming printf() is disallowed in tasks
5. You want to notify a task from multiple ISRs using ISR-to-task notifications. Which approach ensures the task processes all notifications without missing any?
hard
A. Use vTaskNotifyGiveFromISR() once and ulTaskNotifyTake() once; task processes only one notification
B. Use xTaskNotifyGive() in ISRs and ulTaskNotifyTake() in task with zero timeout
C. Use ulTaskNotifyTake() with clear count and call vTaskNotifyGiveFromISR() in each ISR; task loops to process all notifications
D. Use a global variable incremented in ISRs and checked in task without notifications

Solution

  1. Step 1: Understand multiple ISR notifications

    Each ISR calls vTaskNotifyGiveFromISR() to increment notification count.
  2. Step 2: Task processes all notifications

    Task uses ulTaskNotifyTake(pdTRUE, portMAX_DELAY) in a loop to clear all counts and process each notification.
  3. Final Answer:

    Use ulTaskNotifyTake() with clear count and call vTaskNotifyGiveFromISR() in each ISR; task loops to process all notifications -> Option C
  4. Quick Check:

    Multiple ISR notifications require counting and looping [OK]
Hint: Loop ulTaskNotifyTake() to handle multiple ISR signals [OK]
Common Mistakes:
  • Assuming one notification covers all ISR events
  • Using non-FromISR functions in ISR
  • Ignoring notification count clearing
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard