A semaphore helps a task know when an interrupt has happened. It lets the interrupt tell the task to start working.
Semaphore for ISR-to-task signaling in FreeRTOS
SemaphoreHandle_t xSemaphore;
// In task:
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
// Process after ISR signals
}
// In ISR:
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);xSemaphoreTake() waits for the semaphore in the task.
xSemaphoreGiveFromISR() signals the semaphore from the interrupt safely.
xSemaphore = xSemaphoreCreateBinary(); // Task waits for ISR signal if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { // Do work after ISR }
void ISR_Handler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}This program creates a semaphore, a task waits for the semaphore, and an ISR signals it. The task prints a message when the ISR signals.
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include <stdio.h> SemaphoreHandle_t xSemaphore; void vTaskFunction(void *pvParameters) { while (1) { if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { printf("Task: ISR signaled, processing now.\n"); } } } void ISR_Handler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } int main(void) { xSemaphore = xSemaphoreCreateBinary(); if (xSemaphore == NULL) { printf("Failed to create semaphore.\n"); return 1; } xTaskCreate(vTaskFunction, "Task", 1000, NULL, 1, NULL); // Start scheduler (in real FreeRTOS) // vTaskStartScheduler(); // Simulate ISR call for demo ISR_Handler(); // Simulate task running once vTaskFunction(NULL); return 0; }
Always use xSemaphoreGiveFromISR() inside interrupts to avoid problems.
Use portYIELD_FROM_ISR() to switch to a higher priority task immediately if needed.
Binary semaphores are good for signaling events between ISR and tasks.
Semaphores let tasks wait for signals from interrupts.
Use xSemaphoreGiveFromISR() in ISR and xSemaphoreTake() in tasks.
This helps tasks respond safely and quickly to hardware events.
Practice
Solution
Step 1: Understand semaphore role in FreeRTOS
Semaphores are synchronization tools used to signal between tasks or between ISRs and tasks.Step 2: Identify ISR-to-task signaling purpose
In FreeRTOS, semaphores let an ISR notify a task safely without blocking or complex synchronization.Final Answer:
To safely notify a task from an interrupt service routine (ISR) -> Option CQuick Check:
Semaphore signals task from ISR = A [OK]
- Thinking semaphores create tasks
- Confusing semaphores with disabling interrupts
- Using semaphores for memory allocation
Solution
Step 1: Recall ISR-safe semaphore functions
FreeRTOS provides special functions for ISR context to avoid blocking and ensure safety.Step 2: Identify the correct ISR semaphore give function
The function to give a semaphore from an ISR isxSemaphoreGiveFromISR().Final Answer:
xSemaphoreGiveFromISR() -> Option AQuick Check:
Give semaphore from ISR = xSemaphoreGiveFromISR() [OK]
- Using xSemaphoreGive() inside ISR (not safe)
- Confusing take and give functions
- Assuming xSemaphoreCreateFromISR() exists
SemaphoreHandle_t xSemaphore;
void ISR_Handler() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
}
void TaskFunction(void *pvParameters) {
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
printf("Semaphore received\n");
}
}Solution
Step 1: Analyze ISR giving semaphore
The ISR callsxSemaphoreGiveFromISR()which releases the semaphore.Step 2: Analyze task waiting on semaphore
The task waits indefinitely withxSemaphoreTake()and prints "Semaphore received" when it gets the semaphore.Final Answer:
Semaphore received -> Option DQuick Check:
Task prints after semaphore take = C [OK]
- Thinking semaphore is given twice
- Assuming no output if ISR runs
- Expecting runtime error without initialization
void ISR_Handler() {
xSemaphoreGive(xSemaphore);
}Solution
Step 1: Check function suitability for ISR
xSemaphoreGive()is not safe to call inside an ISR because it may block or cause race conditions.Step 2: Identify correct ISR function
UsexSemaphoreGiveFromISR()inside ISRs to safely give semaphores.Final Answer:
xSemaphoreGive() cannot be called from an ISR -> Option AQuick Check:
Use xSemaphoreGiveFromISR() in ISR, not xSemaphoreGive() [OK]
- Calling xSemaphoreGive() inside ISR
- Ignoring ISR context restrictions
- Assuming semaphore must be taken before giving
Solution
Step 1: Identify correct semaphore type and usage
Binary semaphore is suitable for signaling events from ISR to task.Step 2: Confirm correct function calls and order
ISR must callxSemaphoreGiveFromISR()to signal; task waits withxSemaphoreTake()blocking indefinitely (portMAX_DELAY) until signaled.Final Answer:
Create binary semaphore; ISR calls xSemaphoreGiveFromISR(); task calls xSemaphoreTake() with portMAX_DELAY -> Option BQuick Check:
Binary semaphore + ISR give + task take = A [OK]
- Using mutex instead of semaphore
- Calling give in task and take in ISR
- Using zero timeout causing missed signals
Ready to prove it?
Pass the test and this pattern moves unknown
