Deferred interrupt processing helps keep your system fast and responsive by quickly handling urgent tasks and delaying less urgent work.
Deferred interrupt processing architecture in FreeRTOS
void ISR_Handler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// Quick interrupt handling code here
xTaskNotifyFromISR(taskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void Task_Function(void *pvParameters) {
for(;;) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Deferred processing here
}
}The ISR (interrupt service routine) does only quick work and notifies a task.
The task does the longer processing outside the interrupt.
void ISR_Handler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// Read data quickly
xTaskNotifyFromISR(dataTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}void DataProcessingTask(void *pvParameters) {
for(;;) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Process data here
}
}This program creates a task that waits for an interrupt notification. The ISR quickly notifies the task, which then does the deferred processing and prints a message.
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include <stdio.h> TaskHandle_t dataTaskHandle = NULL; void ISR_Handler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Simulate quick interrupt work xTaskNotifyFromISR(dataTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } void DataProcessingTask(void *pvParameters) { for(;;) { ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // Deferred processing printf("Deferred interrupt processing done.\n"); } } int main(void) { xTaskCreate(DataProcessingTask, "DataTask", 1000, NULL, 2, &dataTaskHandle); vTaskStartScheduler(); return 0; }
Always keep ISR code short to avoid delaying other interrupts.
Use FreeRTOS functions ending with 'FromISR' inside ISRs.
Deferred processing helps keep your system stable and responsive.
Deferred interrupt processing splits work between a fast ISR and a slower task.
Use task notifications or queues to signal tasks from ISRs.
This approach improves system responsiveness and reliability.
Practice
Solution
Step 1: Understand ISR limitations
ISRs should be short to keep system responsive and avoid blocking other interrupts.Step 2: Role of deferred processing
Deferred processing moves longer work to a task, improving system reliability and responsiveness.Final Answer:
To split interrupt handling between a fast ISR and a slower task -> Option CQuick Check:
Deferred interrupt processing = splitting work [OK]
- Thinking all work should be done inside ISR
- Believing interrupts are disabled during task execution
- Ignoring the use of task notifications or queues
Solution
Step 1: Identify ISR-safe notification function
Only functions ending with 'FromISR' are safe to call inside ISRs.Step 2: Check options
xTaskNotifyGiveFromISR is designed for ISR context; others are not ISR-safe or unrelated.Final Answer:
xTaskNotifyGiveFromISR(taskHandle, &higherPriorityTaskWoken); -> Option AQuick Check:
ISR notification uses FromISR functions [OK]
- Using normal task notification functions inside ISR
- Calling blocking functions like vTaskDelay in ISR
- Using queue send with infinite block time inside ISR
void ISR_Handler() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyGiveFromISR(taskHandle, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void TaskFunction(void *pvParameters) {
for(;;) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
printf("Task notified\n");
}
}Solution
Step 1: Analyze ISR notification
ISR calls xTaskNotifyGiveFromISR which increments the task's notification count and may cause context switch.Step 2: Analyze task behavior
Task blocks on ulTaskNotifyTake until notified, then prints "Task notified" and loops back to wait again.Final Answer:
Task notified printed each time ISR runs -> Option DQuick Check:
ISR notifies task -> task prints [OK]
- Assuming task never wakes up
- Confusing notification count with binary flag
- Thinking task prints only once
void ISR_Handler() {
xQueueSend(queueHandle, &data, portMAX_DELAY);
}
void TaskFunction(void *pvParameters) {
for(;;) {
if(xQueueReceive(queueHandle, &receivedData, portMAX_DELAY) == pdPASS) {
process(receivedData);
}
}
}Solution
Step 1: Check ISR queue send parameters
portMAX_DELAY causes blocking; ISRs must never block or wait.Step 2: Correct usage in ISR
Use xQueueSendFromISR with zero block time to avoid blocking in ISR.Final Answer:
Using portMAX_DELAY in ISR causes a blocking call -> Option BQuick Check:
ISRs must not block = no portMAX_DELAY in ISR [OK]
- Using blocking calls inside ISR
- Calling task functions from ISR
- Confusing ISR and task context functions
Solution
Step 1: Understand notification limitations
xTaskNotifyGiveFromISR increments a count but cannot carry event data, risking lost info if multiple events occur quickly.Step 2: Use queue for event data
Queues can hold multiple event messages safely, ensuring the task processes all events without loss.Final Answer:
Use a queue to send event data from each ISR to the task -> Option AQuick Check:
Queues hold multiple events safely [OK]
- Relying on notifications without event data
- Using global flags causing race conditions
- Disabling interrupts too long hurting responsiveness
Ready to prove it?
Pass the test and this pattern moves unknown
