[FreeRTOS] Semaphore related function usage and example explanation

Semaphores in FreeRTOS are a mechanism for synchronization between tasks. It can be used to implement mutual exclusion between tasks to access shared resources or to wait for an event to occur.
insert image description here

semaphore type

There are two types of semaphores in FreeRTOS: binary semaphores and counting semaphores.

1. Binary Semaphore:

  • A binary semaphore has only two states: 0 and 1.
  • When a task acquires a binary semaphore, it will decrement the value of the semaphore by 1. If the value of the semaphore is already 0, the task will be blocked until another task releases the semaphore.
  • When a task releases a binary semaphore, it increments the value of the semaphore by 1, and if other tasks are waiting on the semaphore, it wakes up one of the waiting tasks.

2. Counting Semaphore:

  • A counting semaphore can have multiple states, depending on its initial value and increments or decrements per operation.
  • When a task obtains the counting semaphore, it will subtract the specified value of the semaphore from the value of the semaphore. If the value of the semaphore is already 0, the task will be blocked until enough semaphores are released by other tasks. .
  • When a task releases the counting semaphore, it will add the value of the semaphore to the specified increment or decrement value, and if other tasks are waiting for the semaphore, it will wake up one of the waiting tasks.

The steps to use semaphores in FreeRTOS are as follows:

  1. Create a semaphore object, you can use xSemaphoreCreateBinary()the function to create a binary semaphore, or use xSemaphoreCreateCounting()the function to create a counting semaphore.
  2. Use the function in the task xSemaphoreTake()to obtain the semaphore, and call the function where you need to access shared resources or wait for events to occur.
  3. Use a function in the task xSemaphoreGive()to release the semaphore, which is called after the access to the shared resource is completed or after the event occurs.
  4. Optionally, you can use xSemaphoreTake()the function's blocking time parameter to control how long a task waits for a semaphore.

Semaphore usage

1. xSemaphoreCreateBinary()

  • Prototype :

    SemaphoreHandle_t xSemaphoreCreateBinary(void)
    
  • Function : Create a binary semaphore.

  • Parameters : None.

  • Return Value : Returns a handle ( ) pointing to the semaphore SemaphoreHandle_t.

2. xSemaphoreCreateCounting()

  • Prototype :

    SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount)
    
  • Role : Create a counting semaphore.

  • Parameters : One parameter specifying the maximum count value of the semaphore.

  • Return Value : Returns a handle ( ) pointing to the semaphore SemaphoreHandle_t.

3. xSemaphoreCreateMutex()

  • Prototype :
SemaphoreHandle_t xSemaphoreCreateMutex(void)
  • Function : Create a mutex semaphore.
  • Parameters : None.
  • Return Value : Returns a handle ( ) pointing to the semaphore SemaphoreHandle_t.

4. xSemaphoreTake()

  • Prototype :
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait)
  • Function : Get a semaphore.
  • Parameters : handle to the semaphore ( SemaphoreHandle_t) and an optional timeout ( TickType_t).
  • Return value : Return if the acquisition is successful pdTRUE; return if the acquisition fails (timeout or other reasons) pdFALSE.

5. xSemaphoreGive()

  • prototype:
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore)
  • Function : Release a semaphore.
  • Parameters : handle to the semaphore ( SemaphoreHandle_t).
  • Return value : None.

sample code block

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

// 共享资源
int sharedResource = 0;

// 互斥信号量
SemaphoreHandle_t mutex;

void task1(void *pvParameters)
{
    
    
    while (1) {
    
    
        // 获取互斥信号量
        xSemaphoreTake(mutex, portMAX_DELAY);

        // 访问共享资源
        sharedResource++;

        // 释放互斥信号量
        xSemaphoreGive(mutex);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void task2(void *pvParameters)
{
    
    
    while (1) {
    
    
        // 获取互斥信号量
        xSemaphoreTake(mutex, portMAX_DELAY);

        // 访问共享资源
        sharedResource--;

        // 释放互斥信号量
        xSemaphoreGive(mutex);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

int main(void)
{
    
    
    // 创建互斥信号量
    mutex = xSemaphoreCreateMutex();

    // 创建任务
    xTaskCreate(task1, "Task 1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
    xTaskCreate(task2, "Task 2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    return 0;
}

In the example, the above functions are used to create the mutex semaphore ( xSemaphoreCreateMutex()), acquire the mutex semaphore ( xSemaphoreTake()), and release the mutex semaphore ( xSemaphoreGive()). Among them, the handle of the mutex semaphore is stored in the global variable mutex.

Guess you like

Origin blog.csdn.net/Goforyouqp/article/details/132595076