These functions help tasks share resources safely by controlling access one at a time.
xSemaphoreGive() and xSemaphoreTake() in FreeRTOS
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait); BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
xSemaphoreTake() tries to take (lock) the semaphore. It waits up to xTicksToWait ticks.
xSemaphoreGive() releases (unlocks) the semaphore so other tasks can take it.
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
// Access shared resource
xSemaphoreGive(xSemaphore);
}if (xSemaphoreTake(xSemaphore, 10) == pdTRUE) { // Use resource xSemaphoreGive(xSemaphore); } else { // Could not get semaphore in 10 ticks }
This program creates a binary semaphore and two tasks. Each task waits to take the semaphore, prints messages when it takes and gives it back, simulating work with a delay.
#include "FreeRTOS.h" #include "semphr.h" #include "task.h" #include <stdio.h> SemaphoreHandle_t xSemaphore; void vTask1(void *pvParameters) { if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { printf("Task 1 took the semaphore\n"); vTaskDelay(100 / portTICK_PERIOD_MS); // Simulate work xSemaphoreGive(xSemaphore); printf("Task 1 gave the semaphore\n"); } vTaskDelete(NULL); } void vTask2(void *pvParameters) { if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { printf("Task 2 took the semaphore\n"); vTaskDelay(50 / portTICK_PERIOD_MS); // Simulate work xSemaphoreGive(xSemaphore); printf("Task 2 gave the semaphore\n"); } vTaskDelete(NULL); } int main(void) { xSemaphore = xSemaphoreCreateBinary(); if (xSemaphore == NULL) { printf("Failed to create semaphore\n"); return 1; } // Give the semaphore initially so tasks can take it xSemaphoreGive(xSemaphore); xTaskCreate(vTask1, "Task1", 1000, NULL, 1, NULL); xTaskCreate(vTask2, "Task2", 1000, NULL, 1, NULL); vTaskStartScheduler(); // Should never reach here return 0; }
Always give the semaphore once before tasks try to take it if you use a binary semaphore.
Use portMAX_DELAY to wait forever or a number of ticks to wait for a limited time.
Check the return value of xSemaphoreTake() to know if you got the semaphore or timed out.
xSemaphoreTake() locks the semaphore to use a resource.
xSemaphoreGive() unlocks the semaphore to let others use the resource.
They help tasks share resources safely without conflicts.
Practice
xSemaphoreTake() in FreeRTOS?Solution
Step 1: Understand the role of
This function is used by a task to lock a semaphore, which means it tries to gain exclusive access to a shared resource.xSemaphoreTake()Step 2: Differentiate from
xSemaphoreGive()xSemaphoreGive()is used to release or unlock the semaphore, not to lock it.Final Answer:
To lock the semaphore and gain exclusive access to a resource -> Option AQuick Check:
xSemaphoreTake()locks = B [OK]
- Confusing take with give
- Thinking take creates semaphore
- Mixing up locking and unlocking
xSemaphore with a block time of 100 ticks?Solution
Step 1: Recall function signature of
The correct syntax isxSemaphoreTake()xSemaphoreTake(SemaphoreHandle, BlockTimeTicks);where the first argument is the semaphore handle and second is the block time.Step 2: Match the options with correct order
xSemaphoreTake(xSemaphore, 100); matches the correct order:xSemaphoreTake(xSemaphore, 100);. Options B and D usexSemaphoreGivewhich is wrong here. xSemaphoreTake(100, xSemaphore); reverses the arguments.Final Answer:
xSemaphoreTake(xSemaphore, 100); -> Option BQuick Check:
Take(semaphore, time) = C [OK]
- Swapping arguments order
- Using xSemaphoreGive instead of xSemaphoreTake
- Passing block time as first argument
if (xSemaphoreTake(xSemaphore, 10) == pdTRUE) {
// Critical section
xSemaphoreGive(xSemaphore);
printf("Access granted\n");
} else {
printf("Access denied\n");
}
What will be printed if the semaphore is already taken by another task and not given back within 10 ticks?Solution
Step 1: Understand
If the semaphore is already taken and not released within the 10 tick block time,xSemaphoreTake()behavior with timeoutxSemaphoreTake()returnspdFALSE.Step 2: Analyze the if condition and output
SincexSemaphoreTake()returnspdFALSE, the else branch executes, printing "Access denied".Final Answer:
Access denied -> Option DQuick Check:
Semaphore busy + timeout = Access denied [OK]
- Assuming take always succeeds
- Ignoring block time effect
- Expecting 'Access granted' always
if (xSemaphoreGive(xSemaphore) == pdTRUE) {
// Critical section
xSemaphoreTake(xSemaphore, portMAX_DELAY);
}Solution
Step 1: Understand correct semaphore usage order
A task must first take (lock) the semaphore before giving (unlocking) it. CallingxSemaphoreGive()beforexSemaphoreTake()is incorrect.Step 2: Check function return types and usage
xSemaphoreGive()returnsBaseType_t, so comparing topdTRUEis valid. UsingportMAX_DELAYinxSemaphoreTake()is allowed to wait indefinitely.Final Answer:
xSemaphoreGive should not be called before taking the semaphore -> Option AQuick Check:
Give before Take is wrong order [OK]
- Calling give before take
- Misunderstanding return values
- Thinking portMAX_DELAY is invalid
xSemaphore. Task A takes the semaphore, performs work, then gives it back. Task B tries to take the semaphore with a 50 tick timeout. If Task A forgets to give the semaphore back, what will happen to Task B?Solution
Step 1: Understand semaphore blocking with timeout
Task B callsxSemaphoreTake()with a 50 tick timeout, so it will wait up to 50 ticks for the semaphore to become available.Step 2: Analyze effect of Task A not giving semaphore back
If Task A never gives the semaphore back, Task B will wait the full 50 ticks, thenxSemaphoreTake()returnspdFALSE, so Task B continues without the resource.Final Answer:
Task B will block for 50 ticks, then continue without the resource -> Option CQuick Check:
Timeout reached without give = block then continue [OK]
- Assuming infinite block without timeout
- Thinking semaphore is taken immediately
- Believing system crashes on semaphore misuse
Ready to prove it?
Pass the test and this pattern moves unknown
