使用 FreeRTOS 的二进制信号量进行任务同步
在嵌入式系统中,任务之间的同步是一项重要的任务,特别是在多任务环境下。FreeRTOS 是一个流行的实时操作系统内核,它提供了许多同步机制,其中包括二进制信号量。本文将介绍二进制信号量的概念、工作原理以及如何在 FreeRTOS 中使用二进制信号量进行任务同步。
介绍
什么是二进制信号量?
二进制信号量是一种同步机制,用于控制任务之间的访问。它只有两种状态:可用和不可用。任务可以尝试获取二进制信号量,如果信号量可用,则任务获取成功并继续执行;如果信号量不可用,则任务会被阻塞,直到信号量变为可用。
二进制信号量只有两个状态:0和1。
- 0:表示资源被占用或不可用。
- 1:表示资源可用。
二进制信号量的工作原理
在 FreeRTOS 中,二进制信号量由 SemaphoreHandle_t
类型的句柄表示。任务可以通过 xSemaphoreTake()
函数获取信号量,通过 xSemaphoreGive()
函数释放信号量。
当任务尝试获取二进制信号量时,如果信号量可用,则任务获取成功,信号量变为不可用状态。如果信号量不可用,则任务会被阻塞,直到信号量变为可用。
当任务释放信号量时,信号量变为可用状态,等待获取信号量的任务可以继续执行。
如何使用二进制信号量进行任务同步?
以下是使用 FreeRTOS 的二进制信号量进行任务同步的一般步骤:
-
创建二进制信号量:在程序开始时,通过
xSemaphoreCreateBinary()
函数创建一个二进制信号量。 -
获取信号量:在需要同步的任务中,使用
xSemaphoreTake()
函数获取信号量。如果信号量不可用(信号量为0不可用,1表示资源可用),则任务会被阻塞。 -
释放信号量:在任务完成操作后,使用
xSemaphoreGive()
函数释放信号量,使得其他等待获取信号量的任务可以继续执行。
🚨需要注意在FreeRTOS中,创建二进制信号量时,信号量的初始状态为“不可用”或“空”(即值为0)。这意味着在创建后,如果一个任务立即尝试获取信号量(使用xSemaphoreTake
),它会阻塞直到另一个任务释放信号量(使用xSemaphoreGive
)。
示例:任务同步
下面是一个简单的示例,演示了如何在 FreeRTOS 中使用二进制信号量进行任务同步:
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
// 定义二进制信号量句柄
SemaphoreHandle_t xSemaphore;
// 任务函数
void Task1(void *pvParameters);
void Task2(void *pvParameters);
void setup() {
// 创建二进制信号量
xSemaphore = xSemaphoreCreateBinary();
// 创建任务1
xTaskCreate(Task1, "任务1", 10000, NULL, 1, NULL);
// 创建任务2
xTaskCreate(Task2, "任务2", 10000, NULL, 1, NULL);
// 启动调度器
vTaskStartScheduler();
}
void loop() {
// 什么都不做
}
// 任务1函数
void Task1(void *pvParameters) {
while (1) {
// 获取二进制信号量
xSemaphoreTake(xSemaphore, portMAX_DELAY);
// 任务1处理逻辑
// ...
// 释放二进制信号量
xSemaphoreGive(xSemaphore);
}
}
// 任务2函数
void Task2(void *pvParameters) {
while (1) {
// 任务2处理逻辑
// ...
// 发送信号给任务1
xSemaphoreGive(xSemaphore);
// 等待一段时间再发送信号
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
在这个示例中,任务1会等待二进制信号量,一旦信号量可用,任务1将执行其处理逻辑,并在处理完毕后释放信号量。任务2会定期发送信号给任务1,触发任务1的执行。
结论
二进制信号量是一种强大的任务同步机制,在 FreeRTOS 中通过正确地使用二进制信号量,可以实现任务之间的协调和同步