SEMAPHORE | TASK EXECUTION ORDER CONTROL AND RESOURCE SHARING¶
References
This document is based on the DURUOFU's ESP32-GUIDE. For more information, please refer to the original version: DURUOFU ESP32-GUIDE.
Note
FreeRTOS provides semaphores and mutexes for task synchronization and resource sharing management. Semaphores are more inclined to task synchronization, while mutexes are used to protect shared resources.
1. Binary Semaphore¶
The binary semaphore is the most basic semaphore, with only two states: available and unavailable (or 1 and 0). It is usually used for task-to-task or interrupt-to-task synchronization. When an event occurs, the semaphore is released by an interrupt or task, and the waiting task is awakened. Binary semaphores are suitable for simple event notification scenarios, such as notifying a task to process external input or complete a task.
1.1 API Description:¶
API Function | Description |
---|---|
xSemaphoreCreateBinary() | Create a binary semaphore. |
xSemaphoreTake() | Take a semaphore. |
xSemaphoreGive() | Give a semaphore. |
1.2 Example Code:¶
// Binary Semaphore
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
static const char *TAG = "main";
// Binary Semaphore
SemaphoreHandle_t semaphoreHandle;
// Shared variable
int shareVariable = 0;
void task1(void *pvParameters)
{
for (;;)
{
// Take the semaphore, the semaphore becomes 0
xSemaphoreTake(semaphoreHandle, portMAX_DELAY);
for (int i = 0; i < 10; i++)
{
shareVariable++;
ESP_LOGI(TAG, "task1 shareVariable:%d", shareVariable);
vTaskDelay(pdMS_TO_TICKS(1000));
}
// Give the semaphore, the semaphore becomes 1
xSemaphoreGive(semaphoreHandle);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void task2(void *pvParameters)
{
for (;;)
{
// Take the semaphore
xSemaphoreTake(semaphoreHandle, portMAX_DELAY);
for (int i = 0; i < 10; i++)
{
shareVariable--;
ESP_LOGI(TAG, "task2 shareVariable:%d", shareVariable);
vTaskDelay(pdMS_TO_TICKS(1000));
}
// Give the semaphore
xSemaphoreGive(semaphoreHandle);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void app_main(void)
{
semaphoreHandle = xSemaphoreCreateBinary();
xSemaphoreGive(semaphoreHandle);
xTaskCreate(task1, "task1", 2048, NULL, 10, NULL);
xTaskCreate(task2, "task2", 2048, NULL, 10, NULL);
}