Consider the following FreeRTOS code snippet where an ISR signals a task using a binary semaphore. What will be the output printed by the task?
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include <stdio.h> SemaphoreHandle_t xBinarySemaphore; void vISR_Handler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } void vTaskFunction(void *pvParameters) { if(xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdTRUE) { printf("Semaphore taken, task running\n"); } else { printf("Failed to take semaphore\n"); } vTaskDelete(NULL); } int main(void) { xBinarySemaphore = xSemaphoreCreateBinary(); xTaskCreate(vTaskFunction, "Task", 1000, NULL, 1, NULL); vISR_Handler(); vTaskStartScheduler(); return 0; }
Think about what happens when the ISR gives the semaphore before the task tries to take it.
The ISR gives the binary semaphore before the task attempts to take it. Since the semaphore is given, the task successfully takes it and prints "Semaphore taken, task running".
In FreeRTOS, why are semaphores commonly used for signaling from an ISR to a task?
Consider what ISRs must avoid doing and how tasks can be notified safely.
ISRs must not block or perform long operations. Semaphores allow ISRs to signal tasks safely without blocking, enabling tasks to run when appropriate.
Identify the error in the following code snippet and what happens when the ISR tries to give the semaphore.
SemaphoreHandle_t xSem;
void ISR_Handler(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGive(xSem); // Incorrect function used
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void Task(void *pvParameters) {
if(xSemaphoreTake(xSem, portMAX_DELAY) == pdTRUE) {
// Task code
}
}Check the function used inside the ISR to give the semaphore.
xSemaphoreGive must not be called from an ISR. Instead, xSemaphoreGiveFromISR must be used. Using xSemaphoreGive in ISR can cause runtime errors or undefined behavior.
Choose the correct syntax to give a binary semaphore from an ISR in FreeRTOS.
Remember the function signature requires a pointer to a variable for context switching.
xSemaphoreGiveFromISR requires two parameters: the semaphore handle and a pointer to a BaseType_t variable to indicate if a context switch is needed. Passing NULL is valid if context switch is not needed.
A binary semaphore is created and initially empty. The ISR calls xSemaphoreGiveFromISR three times in quick succession before the task attempts to take the semaphore once. How many times will the task unblock if it calls xSemaphoreTake once with portMAX_DELAY?
Think about the difference between binary and counting semaphores.
A binary semaphore can only hold a maximum count of one. Multiple gives before a take do not accumulate. So the task unblocks only once.
