Bird
Raised Fist0
FreeRTOSprogramming~10 mins

ISR-safe API functions (FromISR suffix) in FreeRTOS - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - ISR-safe API functions (FromISR suffix)
Interrupt Occurs
↓
Call FromISR API
↓
Check ISR Context
↓
Perform Safe Operation
↓
Return from ISR
↓
Scheduler Decision
↓
No Switch
↓
Continue
When an interrupt happens, ISR-safe APIs with FromISR suffix are called to safely interact with FreeRTOS from interrupt context, possibly triggering a context switch.
Execution Sample
FreeRTOS
void ISR_Handler() {
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  xQueueSendFromISR(queue, &data, &xHigherPriorityTaskWoken);
  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
This code sends data to a queue safely from an ISR and requests a context switch if needed.
Execution Table
StepActionVariable ValuesResultNotes
1Interrupt occursxHigherPriorityTaskWoken = pdFALSEEnter ISR contextISR starts
2Call xQueueSendFromISRqueue, &data, &xHigherPriorityTaskWokenData queued, xHigherPriorityTaskWoken updatedSafe queue send from ISR
3Check xHigherPriorityTaskWokenxHigherPriorityTaskWoken = pdTRUE or pdFALSEIf pdTRUE, request context switchDetermines if higher priority task was woken
4Call portYIELD_FROM_ISRxHigherPriorityTaskWokenContext switch triggered if pdTRUEYield from ISR to scheduler
5Return from ISR-ISR ends, possibly switches taskISR completes execution
💡 ISR completes and returns; if a higher priority task was woken, context switch occurs immediately.
Variable Tracker
VariableStartAfter Step 2After Step 3Final
xHigherPriorityTaskWokenpdFALSEpdTRUE or pdFALSEpdTRUE or pdFALSEpdTRUE or pdFALSE
Key Moments - 3 Insights
Why do we use xHigherPriorityTaskWoken in FromISR functions?
It tells if a higher priority task was woken by the ISR operation, so the scheduler knows if it should switch tasks immediately (see execution_table step 3).
Can we call normal FreeRTOS API functions inside an ISR?
No, normal APIs are not safe in ISR context. FromISR versions are designed to be safe and avoid blocking or unsafe operations (see concept_flow).
What happens if portYIELD_FROM_ISR is not called when xHigherPriorityTaskWoken is true?
The higher priority task will not run immediately after ISR, delaying its execution until the next normal context switch (see execution_table step 4).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the value of xHigherPriorityTaskWoken after step 2?
AAlways pdTRUE
BpdFALSE
CpdTRUE or pdFALSE
DUndefined
💡 Hint
Check the 'Variable Values' column in step 2 of execution_table.
At which step does the ISR request a context switch if needed?
AStep 4
BStep 1
CStep 3
DStep 5
💡 Hint
Look at the 'Result' column for step 4 in execution_table.
If we forget to call portYIELD_FROM_ISR, what changes in the execution flow?
AISR will not complete
BNo context switch happens immediately after ISR
CxHigherPriorityTaskWoken will be reset
DQueue operation fails
💡 Hint
Refer to key_moments explanation about portYIELD_FROM_ISR importance.
Concept Snapshot
ISR-safe API functions end with FromISR.
They are designed to be called inside interrupts.
Use xHigherPriorityTaskWoken to detect if a higher priority task was woken.
Call portYIELD_FROM_ISR to request immediate context switch.
Normal FreeRTOS APIs are NOT safe inside ISRs.
Full Transcript
When an interrupt occurs, you must use special FreeRTOS API functions that are safe to call from interrupt context. These functions have the suffix FromISR. Inside the ISR, you declare a variable xHigherPriorityTaskWoken initialized to pdFALSE. When calling a FromISR function like xQueueSendFromISR, this variable may be set to pdTRUE if the operation wakes a higher priority task. After the call, you check xHigherPriorityTaskWoken and call portYIELD_FROM_ISR if it is true. This causes the scheduler to switch to the higher priority task immediately after the ISR finishes. If you do not call portYIELD_FROM_ISR, the higher priority task will wait until the next normal context switch. Normal FreeRTOS API functions are not safe to call inside ISRs because they may block or cause unsafe operations. Using FromISR APIs ensures safe and efficient interrupt handling in FreeRTOS.

Practice

(1/5)
1.

What is the main reason to use FreeRTOS API functions with the FromISR suffix inside an interrupt service routine (ISR)?

easy
A. They disable all interrupts during execution.
B. They are safe to call from ISRs and handle interrupt context correctly.
C. They run tasks faster than normal API functions.
D. They automatically create new tasks inside the ISR.

Solution

  1. Step 1: Understand ISR context constraints

    Inside an ISR, normal FreeRTOS API functions are unsafe because they may block or cause race conditions.
  2. Step 2: Role of FromISR functions

    Functions with the FromISR suffix are designed to be safe in interrupt context by avoiding blocking and managing critical sections properly.
  3. Final Answer:

    They are safe to call from ISRs and handle interrupt context correctly. -> Option B
  4. Quick Check:

    FromISR functions = ISR safe calls [OK]
Hint: Use FromISR functions only inside interrupts for safety [OK]
Common Mistakes:
  • Calling normal API functions inside ISR causing crashes
  • Assuming FromISR functions disable interrupts
  • Thinking FromISR creates tasks automatically
2.

Which of the following is the correct way to declare a variable to track if a higher priority task was woken inside an ISR?

?
easy
A. int higherPriorityTaskWoken = 0;
B. bool higherPriorityTaskWoken = false;
C. BaseType_t higherPriorityTaskWoken = pdFALSE;
D. volatile int higherPriorityTaskWoken = 1;

Solution

  1. Step 1: Identify FreeRTOS type for ISR task wake flag

    FreeRTOS uses BaseType_t for portability and defines pdFALSE and pdTRUE for boolean values.
  2. Step 2: Correct initialization

    The variable must start as pdFALSE to indicate no task was woken yet.
  3. Final Answer:

    BaseType_t higherPriorityTaskWoken = pdFALSE; -> Option C
  4. Quick Check:

    Use BaseType_t and pdFALSE for ISR flags [OK]
Hint: Use BaseType_t and pdFALSE to track task wake in ISR [OK]
Common Mistakes:
  • Using plain int instead of BaseType_t
  • Initializing flag to 1 instead of pdFALSE
  • Using bool which may not be portable
3.

Consider this ISR code snippet:

BaseType_t higherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(queue, &data, &higherPriorityTaskWoken);
if (higherPriorityTaskWoken) {
    portYIELD_FROM_ISR();
}

What happens if higherPriorityTaskWoken is set to pdTRUE after xQueueSendFromISR?

medium
A. The ISR requests a context switch to the higher priority task immediately after ISR.
B. The ISR disables all interrupts until the higher priority task runs.
C. The queue send operation fails silently.
D. The higher priority task is blocked until the ISR finishes.

Solution

  1. Step 1: Understand higherPriorityTaskWoken flag

    This flag indicates if a task with higher priority than the current one was made ready by the ISR.
  2. Step 2: Role of portYIELD_FROM_ISR()

    If the flag is true, calling portYIELD_FROM_ISR() requests a context switch to that higher priority task immediately after ISR exit.
  3. Final Answer:

    The ISR requests a context switch to the higher priority task immediately after ISR. -> Option A
  4. Quick Check:

    higherPriorityTaskWoken true triggers context switch [OK]
Hint: If higherPriorityTaskWoken true, call portYIELD_FROM_ISR() [OK]
Common Mistakes:
  • Thinking interrupts are disabled by portYIELD_FROM_ISR()
  • Assuming queue send fails if flag is true
  • Believing higher priority task waits for ISR to finish
4.

Identify the error in this ISR code snippet:

void ISR_Handler(void) {
    BaseType_t higherPriorityTaskWoken = pdFALSE;
    xSemaphoreGive(semaphore);
    if (higherPriorityTaskWoken) {
        portYIELD_FROM_ISR();
    }
}

What is the problem here?

medium
A. The variable higherPriorityTaskWoken should be global.
B. The semaphore is given twice causing overflow.
C. The portYIELD_FROM_ISR() call is outside the ISR.
D. The higherPriorityTaskWoken variable is not passed to xSemaphoreGiveFromISR.

Solution

  1. Step 1: Check function used for semaphore give

    The code uses xSemaphoreGive, which is not safe inside ISR context.
  2. Step 2: Correct ISR-safe function usage

    Inside ISR, xSemaphoreGiveFromISR must be used with higherPriorityTaskWoken passed by reference to track task wake.
  3. Final Answer:

    The higherPriorityTaskWoken variable is not passed to xSemaphoreGiveFromISR. -> Option D
  4. Quick Check:

    Use FromISR functions with higherPriorityTaskWoken [OK]
Hint: Always pass higherPriorityTaskWoken to FromISR functions [OK]
Common Mistakes:
  • Using normal API functions inside ISR
  • Not passing higherPriorityTaskWoken pointer
  • Declaring higherPriorityTaskWoken as global unnecessarily
5.

You want to send data from an ISR to a task using a queue. Which sequence correctly uses FreeRTOS ISR-safe API functions to do this and ensure the higher priority task runs immediately if woken?

?
hard
A. BaseType_t higherPriorityTaskWoken = pdFALSE; xQueueSendFromISR(queue, &data, &higherPriorityTaskWoken); if (higherPriorityTaskWoken) portYIELD_FROM_ISR();
B. xQueueSend(queue, &data, 0); BaseType_t higherPriorityTaskWoken = pdFALSE; if (higherPriorityTaskWoken) portYIELD_FROM_ISR();
C. BaseType_t higherPriorityTaskWoken = pdTRUE; xQueueSendFromISR(queue, &data, NULL); portYIELD_FROM_ISR();
D. BaseType_t higherPriorityTaskWoken = pdFALSE; xQueueSend(queue, &data, 0); portYIELD_FROM_ISR();

Solution

  1. Step 1: Use ISR-safe queue send function

    Inside ISR, xQueueSendFromISR must be used with a pointer to higherPriorityTaskWoken.
  2. Step 2: Check higherPriorityTaskWoken and yield

    If higherPriorityTaskWoken is set to pdTRUE, call portYIELD_FROM_ISR() to request immediate context switch.
  3. Final Answer:

    BaseType_t higherPriorityTaskWoken = pdFALSE; xQueueSendFromISR(queue, &data, &higherPriorityTaskWoken); if (higherPriorityTaskWoken) portYIELD_FROM_ISR(); -> Option A
  4. Quick Check:

    Use FromISR + check flag + yield [OK]
Hint: Use xQueueSendFromISR with flag and yield if true [OK]
Common Mistakes:
  • Using normal xQueueSend inside ISR
  • Not passing higherPriorityTaskWoken pointer
  • Calling portYIELD_FROM_ISR unconditionally
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