Bird
Raised Fist0
FreeRTOSprogramming~10 mins

ISR-to-task notification pattern in FreeRTOS - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - ISR-to-task notification pattern
Interrupt Occurs
↓
ISR Executes
↓
Send Notification to Task
↓
Task Receives Notification
↓
Task Processes Event
↓
Task Waits for Next Notification
When an interrupt happens, the ISR sends a notification to a task, which then wakes up and processes the event.
Execution Sample
FreeRTOS
void ISR_Handler() {
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  vTaskNotifyGiveFromISR(taskHandle, &xHigherPriorityTaskWoken);
  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void TaskFunction(void *params) {
  for(;;) {
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    // Process event
  }
}
ISR sends notification to a task; task waits for notification and processes event when notified.
Execution Table
StepContextActionNotification StateTask StateOutput/Result
1Interrupt OccursISR_Handler startsNotification = 0Task blocked waitingNo output
2ISRvTaskNotifyGiveFromISR calledNotification incremented to 1Task still blockedNo output
3ISRportYIELD_FROM_ISR checks xHigherPriorityTaskWokenNotification = 1Task unblocked if higher priorityContext switch if needed
4TaskulTaskNotifyTake calledNotification decremented to 0Task runningTask wakes and processes event
5TaskTask processes eventNotification = 0Task runningEvent handled
6TaskTask loops back to waitNotification = 0Task blocked waitingWaiting for next notification
7No new interruptNo notification sentNotification = 0Task blockedNo output
💡 Execution waits indefinitely at ulTaskNotifyTake until next ISR notification.
Variable Tracker
VariableStartAfter Step 2After Step 4After Step 6
Notification Count0100
Task StateBlockedBlockedRunningBlocked
Key Moments - 3 Insights
Why does the task unblock after the ISR sends a notification?
Because in step 3, portYIELD_FROM_ISR triggers a context switch if the task has higher priority and a notification was sent, unblocking the task as shown in the execution_table.
What happens if the task does not call ulTaskNotifyTake after notification?
The notification count remains at 1 (step 2), but the task stays blocked until it calls ulTaskNotifyTake to consume the notification, as seen in steps 2 and 4.
Can notifications be lost if multiple interrupts occur before the task processes them?
No, notifications accumulate as counts (step 2 increments notification), so multiple ISR calls increase the notification count until the task processes them.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 2, what is the notification count after vTaskNotifyGiveFromISR is called?
A1
B0
C2
DUndefined
💡 Hint
Check the 'Notification State' column at step 2 in the execution_table.
At which step does the task change from blocked to running?
AStep 1
BStep 3
CStep 4
DStep 6
💡 Hint
Look at the 'Task State' column in the execution_table to see when it changes to running.
If the ISR is called twice before the task runs, how would the notification count change after step 2?
ANotification count would be 1
BNotification count would be 2
CNotification count would be 0
DNotification count would reset to 0
💡 Hint
Refer to the variable_tracker and key moment about notification accumulation.
Concept Snapshot
ISR-to-task notification pattern in FreeRTOS:
- ISR sends notification using vTaskNotifyGiveFromISR.
- Task waits with ulTaskNotifyTake.
- Notification increments unblock the task.
- portYIELD_FROM_ISR triggers context switch if needed.
- Notifications accumulate if multiple ISRs occur before task runs.
Full Transcript
This visual execution trace shows how an interrupt service routine (ISR) communicates with a FreeRTOS task using the ISR-to-task notification pattern. When an interrupt occurs, the ISR runs and calls vTaskNotifyGiveFromISR to send a notification to the task. This increments the notification count. If the task has higher priority, portYIELD_FROM_ISR triggers a context switch to unblock the task. The task, which waits on ulTaskNotifyTake, then wakes up, consumes the notification (decrementing the count), and processes the event. After processing, the task waits again for the next notification. Notifications accumulate if multiple interrupts happen before the task processes them, ensuring no events are lost. The execution table and variable tracker show step-by-step changes in notification count and task state, helping beginners understand the flow and synchronization between ISR and task.

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