Semaphore timeout handling helps your program wait for a resource only for a limited time. This avoids getting stuck forever if the resource is not available.
Semaphore timeout handling in FreeRTOS
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
xSemaphore is the semaphore you want to take (use).
xTicksToWait is how long to wait in ticks before giving up.
if (xSemaphoreTake(xSemaphore, pdMS_TO_TICKS(1000)) == pdTRUE) { // Got the semaphore } else { // Timeout happened }
if (xSemaphoreTake(xSemaphore, 0) == pdTRUE) { // Take semaphore immediately or fail }
This program creates a binary semaphore and two tasks. Task1 waits up to 2 seconds to take the semaphore, does some work, then releases it. Task2 waits up to 1 second to take the semaphore. If it times out, it prints a timeout message.
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include <stdio.h> SemaphoreHandle_t xSemaphore; void vTask1(void *pvParameters) { printf("Task1: Waiting for semaphore...\n"); if (xSemaphoreTake(xSemaphore, pdMS_TO_TICKS(2000)) == pdTRUE) { printf("Task1: Got the semaphore!\n"); vTaskDelay(pdMS_TO_TICKS(1500)); // Simulate work xSemaphoreGive(xSemaphore); printf("Task1: Released the semaphore.\n"); } else { printf("Task1: Timeout waiting for semaphore.\n"); } vTaskDelete(NULL); } void vTask2(void *pvParameters) { printf("Task2: Waiting for semaphore...\n"); if (xSemaphoreTake(xSemaphore, pdMS_TO_TICKS(1000)) == pdTRUE) { printf("Task2: Got the semaphore!\n"); xSemaphoreGive(xSemaphore); printf("Task2: Released the semaphore.\n"); } else { printf("Task2: Timeout waiting for semaphore.\n"); } vTaskDelete(NULL); } int main(void) { xSemaphore = xSemaphoreCreateBinary(); if (xSemaphore == NULL) { printf("Failed to create semaphore.\n"); return 1; } // Give semaphore initially so Task1 can take it xSemaphoreGive(xSemaphore); xTaskCreate(vTask1, "Task1", 1000, NULL, 2, NULL); xTaskCreate(vTask2, "Task2", 1000, NULL, 1, NULL); vTaskStartScheduler(); // Should never reach here for(;;); }
Use pdMS_TO_TICKS() to convert milliseconds to ticks for the timeout.
If you set xTicksToWait to 0, the function returns immediately if the semaphore is not available.
Always check the return value to know if you got the semaphore or if a timeout happened.
Semaphore timeout lets you wait for a resource only for a limited time.
Use xSemaphoreTake() with a timeout to avoid blocking forever.
Always handle the case when the timeout happens to keep your program responsive.
Practice
What does the timeout parameter in xSemaphoreTake() control?
Solution
Step 1: Understand the role of timeout in xSemaphoreTake()
The timeout parameter specifies the maximum time the task will wait to obtain the semaphore.Step 2: Relate timeout to task blocking
If the semaphore is not available within this time, the function returns failure, preventing indefinite blocking.Final Answer:
How long the task waits for the semaphore before giving up -> Option AQuick Check:
Timeout controls wait duration = B [OK]
- Confusing timeout with task priority
- Thinking timeout changes semaphore count
- Assuming timeout affects queue size
Which of the following is the correct way to call xSemaphoreTake() with a 100 tick timeout?
SemaphoreHandle_t sem;Solution
Step 1: Check function signature
xSemaphoreTake takes the semaphore handle first, then the timeout as TickType_t.Step 2: Match parameters correctly
Passing sem as first argument and 100 as timeout matches the correct syntax.Final Answer:
xSemaphoreTake(sem, 100); -> Option DQuick Check:
Semaphore handle first, timeout second = A [OK]
- Swapping arguments order
- Passing address of timeout
- Passing address of semaphore handle
What will be the output of this code snippet?
SemaphoreHandle_t sem = xSemaphoreCreateBinary();
if(xSemaphoreTake(sem, 10) == pdTRUE) {
printf("Got semaphore\n");
} else {
printf("Timeout occurred\n");
}Solution
Step 1: Understand semaphore initial state
xSemaphoreCreateBinary creates a semaphore initially empty (not given).Step 2: Check xSemaphoreTake behavior
Since semaphore is empty and no give is called, xSemaphoreTake waits 10 ticks then times out.Final Answer:
Timeout occurred -> Option CQuick Check:
Empty semaphore + timeout = timeout message [OK]
- Assuming semaphore is initially given
- Ignoring timeout effect
- Expecting compilation error
Identify the error in this code snippet that uses xSemaphoreTake() with timeout:
SemaphoreHandle_t sem = xSemaphoreCreateBinary();
if(xSemaphoreTake(sem, portMAX_DELAY)) {
// Critical section
} else {
// Handle timeout
}Solution
Step 1: Understand portMAX_DELAY meaning
portMAX_DELAY means wait indefinitely for the semaphore.Step 2: Analyze if-else behavior
Since wait is infinite, timeout never occurs, so else block is unreachable.Final Answer:
Using portMAX_DELAY disables timeout, so else block never runs -> Option AQuick Check:
portMAX_DELAY means infinite wait = C [OK]
- Thinking else block handles timeout with portMAX_DELAY
- Assuming semaphore uninitialized causes error here
- Confusing syntax error with logic error
You want to wait for a semaphore but only up to 50 ticks. If the semaphore is not available, you want to perform a fallback task immediately. Which code snippet correctly implements this behavior?
Solution
Step 1: Check timeout usage
Using 50 ticks as timeout means wait up to 50 ticks for semaphore.Step 2: Verify fallback logic
If take returns pdTRUE, resource is used; else fallback task runs immediately after timeout.Final Answer:
Correctly waits 50 ticks and runs fallback if timeout -> Option BQuick Check:
Timeout 50 ticks + fallback on failure = A [OK]
- Using portMAX_DELAY disables fallback
- Swapping if-else blocks
- Using zero timeout incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
