FreeRTOS 互斥信号量


FreeRTOS 互斥信号量

一、FreeRTOS互斥信号量的基本概念

FreeRTOS中的互斥信号量是一种特殊的二进制信号量,用于实现任务间的互斥访问。它主要用于保护临界区代码,防止多个任务同时访问共享资源而导致的数据不一致问题。互斥信号量的工作机制基于“请求-授予”模型,即当一个任务需要访问共享资源时,会先请求互斥信号量,如果信号量可用(即当前没有任务持有信号量),则任务获得信号量并进入临界区;如果信号量不可用(即已有任务持有信号量),则任务会被阻塞,直到信号量被释放。

二、FreeRTOS互斥信号量的使用步骤

包含头文件
在使用FreeRTOS互斥信号量之前,需要包含相应的头文件。通常,我们需要包含FreeRTOS.htask.h头文件,以使用FreeRTOS提供的API函数。
定义互斥信号量
使用xSemaphoreCreateMutex函数来创建一个互斥信号量。这个函数会返回一个信号量句柄,用于后续的信号量操作。
加锁与解锁
在访问共享资源之前,任务需要使用xSemaphoreTake函数来获取互斥信号量(即加锁)。如果信号量不可用,任务会被阻塞,直到信号量被释放。完成共享资源的访问后,任务需要使用xSemaphoreGive函数来释放信号量(即解锁)。
销毁互斥信号量
当不再需要使用互斥信号量时,可以使用vSemaphoreDelete函数来销毁它。注意,在销毁信号量之前,应确保没有任务持有该信号量。

xSemaphoreHandle xMutex = xSemaphoreCreateMutex();

// 加锁
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
    // 访问共享资源
    // ...

    // 解锁
    xSemaphoreGive(xMutex);
}

vSemaphoreDelete(xMutex);

三、FreeRTOS互斥信号量实例分析

以下是一个简单的FreeRTOS互斥信号量使用实例,展示了如何在两个任务之间保护共享资源的访问。

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
// 共享资源
int sharedResource = 0;
// 互斥信号量句柄
xSemaphoreHandle xMutex;
// 任务1:增加共享资源值
void vTask1(void *pvParameters) {
    for (int i = 0; i < 10; i++) {
        // 加锁
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 访问共享资源
            sharedResource++;
            printf("Task1: sharedResource = %d\n", sharedResource);
            // 解锁
            xSemaphoreGive(xMutex);
            // 模拟任务处理时间
            vTaskDelay(100 / portTICK_PERIOD_MS);
        }
    }
}
// 任务2:减少共享资源值
void vTask2(void *pvParameters) {
    for (int i = 0; i < 10; i++) {
        // 加锁
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 访问共享资源
            sharedResource--;
            printf("Task2: sharedResource = %d\n", sharedResource);
            // 解锁
            xSemaphoreGive(xMutex);
            // 模拟任务处理时间
            vTaskDelay(150 / portTICK_PERIOD_MS);
        }
    }
}
int main(void) {
    // 创建互斥信号量
    xMutex = xSemaphoreCreateMutex();
    // 创建任务1和任务2
    xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
    xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL);
    // 启动调度器
    vTaskStartScheduler();
    // 永远不会到达这里,因为调度器已经启动
    for (;;);
}

在这个实例中,我们创建了两个任务vTask1vTask2,它们分别负责增加和减少共享资源sharedResource的值。为了确保对共享资源的独占访问,我们使用了互斥信号量xMutex。在访问共享资源之前,任务会先请求互斥信号量(加锁),完成访问后释放信号量(解锁)。这样,即使两个任务同时运行,也不会出现数据竞争问题。

### FreeRTOS互斥信号量使用方法 #### 创建互斥信号量 为了创建一个互斥信号量,可以使用 `xQueueCreateMutex()` 函数。如果希望静态分配内存,则可采用 `xSemaphoreCreateMutexStatic()` 宏来实现[^3]。 ```c // 动态创建互斥信号量 SemaphoreHandle_t xMutex; xMutex = xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ); if (xMutex != NULL) { // 互斥信号量创建成功 } else { // 处理错误情况 } ``` 对于静态创建的情况: ```c static StaticSemaphore_t xMutexBuffer; // 静态缓冲区 SemaphoreHandle_t xMutex; xMutex = xSemaphoreCreateMutexStatic(&xMutexBuffer); ``` #### 获取互斥信号量 当任务需要访问受保护的共享资源时,应先尝试获取互斥信号量。可以通过调用 `xSemaphoreTake()` 来完成这一操作。此函数会指定等待时间,在这段时间内如果没有获得锁将会超时并返回失败状态;也可以设置无限期等待直至得到锁为止[^2]。 ```c if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) { // 成功获取到互斥信号量,现在可以安全地访问临界区内的数据结构或其他资源 // 访问完成后记得释放互斥信号量 xSemaphoreGive(xMutex); } ``` #### 释放互斥信号量 一旦完成了对共享资源的操作,应当立即通过 `xSemaphoreGive()` 将互斥信号量归还给系统,以便其他正在等待的任务能够继续运行。 ```c if (xSemaphoreGive(xMutex) == pdPASS) { // 正常交出了互斥信号量 } ``` #### 错误处理与调试支持 在某些情况下可能还需要考虑如何捕获异常状况以及利用内置工具辅助开发过程中的问题排查工作。例如,`traceRETURN_xQueueCreateMutex()` 可帮助追踪互斥信号量创建的过程,这对于理解系统的实时行为非常有用[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盼海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值