(六)信号量

本文详细介绍了FreeRTOS中信号量(包括二值信号量和计数信号量)的概念、创建和使用方法,以及互斥量和递归互斥量的运用,通过代码示例展示了如何在任务间进行同步与互斥访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欢迎入群共同学习交流

一、概念

(1)信号量是一种实现任务间同步与互斥的机制,可以实现任务与任务之间、中断与任务之间同步或临界资源的互斥访问,基于队列实现
(2)二值信号量:只有一个消息,空和满的状态标志信号量是否有效可用,主要应用于任务与任务、任务与中断之间的同步
(3)计数信号量:长度大于1的队列,主要应用于事件计数和资源管理

二、常用函数

(1)xSemaphoreCreateBinary创建二值信号量
(2)xSemaphoreCreateCounting创建计数信号量,使用计数信号量时需要将configUSE_COUNTING_SEMAPHORES宏定义打开
(3)vSemaphoreDelete删除信号量
(4)xSemaphoreGive释放信号量,使信号量变为有效状态供任务获取
(5)xSemaphoreGiveFromISR释放信号量,带中断保护
(6)xSemaphoreTake获取信号量,使信号量有效状态个数减一,减到零无可用信号量
(7)xSemaphoreTakeFromISR获取信号量,带中断保护

三、代码示例

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

static void vAppInitTask(void* pParam);
static void task1(void* pParam);
static void task2(void* pParam);

static TaskHandle_t handler1;
static TaskHandle_t handler2;
static TaskHandle_t appHandler;

SemaphoreHandle_t binaryHandler;

//主函数
int main(void)
{  
    //初始化硬件
    led_init();

    BaseType_t xReturn;
    xReturn = xTaskCreate(vAppInitTask,         //任务函数入口
                        "vAppInitTask",         //任务名称
                        512,                    //任务堆栈大小
                        NULL,                   //传递参数
                        2,                      //任务优先级
                        &appHandler             //任务句柄
                );
    
    if(pdPASS == xReturn){
        vTaskStartScheduler();      //开启任务调度器
    }
    
    while(1);
}

//APP任务
void vAppInitTask(void* pParam)
{
    taskENTER_CRITICAL();//进入临界区
    
    //创建二值信号量
    binaryHandler = xSemaphoreCreateBinary();
    if(binaryHandler != NULL){//创建成功
    }
        
    //由于app任务创建成功后便开启了调度器,于是下边创建的任务创建后便会立即执行
    xTaskCreate(task2,           //任务函数入口
            "task2",         //任务名称
            512,                //任务堆栈大小
            NULL,               //传递参数
            2,                  //任务优先级
            &handler2         //任务句柄
            );
    
    xTaskCreate(task1,           //任务函数入口
                "task1",         //任务名称
                512,                //任务堆栈大小
                NULL,               //传递参数
                2,                  //任务优先级
                &handler1         //任务句柄
                );
    
    vTaskDelete(appHandler);
    
    taskEXIT_CRITICAL();//退出临界区
}

//任务1获取信号量
void task1(void* pParam)
{
    BaseType_t pdReturn;
    while(1){
        pdReturn = xSemaphoreTake(binaryHandler,portMAX_DELAY);
        if(pdReturn != pdFALSE){
            open();
        }
    }
}

//任务2释放信号量
void task2(void* pParam)
{
    while(1){
        xSemaphoreGive(binaryHandler);
    }
}

四、互斥量

(1)使用互斥量和递归互斥量需要打开configUSE_MUTEXESconfigUSE_RECURSIVE_MUTEXES宏定义
(2)互斥量就是具有优先级继承的二值信号量

五、互斥量相关函数介绍

(1)xSemaphoreCreateMutex创建互斥量
(2)xSemaphoreCreateRecursiveMutex创建递归互斥量
(3)vSemaphoreDelete删除互斥量
(4)xSemaphoreTake获取互斥量
(5)xSemaphoreGive释放互斥量
(6)xSemaphoreTakeRecursive获取递归互斥量
(7)xSemaphoreGiveRecursive释放递归互斥量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值