FreeRTOS——互斥信号量知识总结及其实战

1互斥信号量的概念

1)互斥信号量:是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中!

2)优先级继承:当一个互斥信号量正在被一个低优先级的任务持有时, 如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。

3)互斥信号量有任务优先级继承的机制, 但是中断不是任务,没有任务优先级, 所以互斥信号量只能用与任务中,不能用于中断服务函数。

4)中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

2 互斥信号量的使用流程

1)使用互斥信号量:首先将宏configUSE_MUTEXES置一

2)使用流程:创建互斥信号量 ->(task)获取信号量 ->(give)释放信号量

3 互斥信号量API函数

#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )

返回值: NULL 创建失败

其他 返回信号量失败

互斥信号量的释放和获取函数与二值信号量相同 !只不过互斥信号量不支持中断中调用

注意:创建互斥信号量时,会主动释放一次信号量

4 互斥信号量实战

实验设计:将优先级翻转所用到的信号量函数,修改成互斥信号量即可,通过串口打印提示信息

4.1 freertos_demo.c

c 复制代码
#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

//FreeRTOS配置

//1.任务配置
//1.1 START_TASK 任务 配置

#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

//1.2 TASK1 任务 配置

#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            lowTask_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

//1.2 TASK2 任务 配置

#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            middleTask_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

//1.3 TASK3 任务 配置

#define TASK3_PRIO      4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            highTask_Handler;  /* 任务句柄 */
void task3(void *pvParameters);             /* 任务函数 */

//1.4 二值信号量句柄定义
SemaphoreHandle_t        mutexSemaphore;  

//2.在freertos_demo函数中创建start_task任务
void freertos_demo(void)
{
    //创建互斥信号量
     mutexSemaphore = xSemaphoreCreateMutex();         //互斥型信号量创建成功后会释放一次信号量
    if(mutexSemaphore != NULL)
    {
        printf("二值信号量创建成功!!!\r\n");
    }
    xTaskCreate((TaskFunction_t )start_task,            /* 任务函数 */
                (const char*    )"start_task",          /* 任务名称 */
                (uint16_t       )START_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )START_TASK_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&StartTask_Handler);   /* 任务句柄 */
    vTaskStartScheduler();
}

//3.在start_task函数中创建task1、task2任务
void start_task(void *pvParameters)
{
    
    //进入临界区
    taskENTER_CRITICAL();
    //创建任务1
      xTaskCreate((TaskFunction_t )task1,            /* 任务函数 */
                (const char*    )"task1",          /* 任务名称 */
                (uint16_t       )TASK1_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK1_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&lowTask_Handler);   /* 任务句柄 */
     //创建任务2          
     xTaskCreate((TaskFunction_t )task2,            /* 任务函数 */
                (const char*    )"task2",          /* 任务名称 */
                (uint16_t       )TASK2_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK2_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&middleTask_Handler);   /* 任务句柄*/
    //创建任务3          
    xTaskCreate((TaskFunction_t )task3,            /* 任务函数 */
                (const char*    )"task3",          /* 任务名称 */
                (uint16_t       )TASK3_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK3_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&highTask_Handler);   /* 任务句柄*/         
      //删除开始任务        
      vTaskDelete(StartTask_Handler);   
                
     //退出临界区
     taskEXIT_CRITICAL();
}


//4.任务一 低优先级任务
void task1(void *pvParameters)
{
    while (1)
    {
        printf("low Task获取信号量\r\n");
        xSemaphoreTake(mutexSemaphore, portMAX_DELAY);
        printf("low Task正在运行\r\n");
        delay_ms(3000);
        printf("low Task正在释放信号量\r\n");
        xSemaphoreGive(mutexSemaphore);
        vTaskDelay(1000);
    }
}

//5.任务二 中优先级任务
void task2(void *pvParameters)
{
    
    while(1)
    {
        printf("middle Task正在释放信号量\r\n");
        vTaskDelay(1000); 
    }
   
}

//6.任务三 高优先级任务
void task3(void *pvParameters)
{
    while(1)
    {
        printf("high Task获取信号量\r\n");
        xSemaphoreTake(mutexSemaphore, portMAX_DELAY);
        printf("high Task正在运行\r\n");
        delay_ms(1000);
        printf("high Task正在释放信号量\r\n");
        xSemaphoreGive(mutexSemaphore);
        vTaskDelay(1000);
    }
}
相关推荐
No0d1es2 小时前
202506 电子学会青少年等级考试机器人五级器人理论真题
单片机·嵌入式硬件·青少年编程·机器人·电子学会·五级·理论综合
范纹杉想快点毕业4 小时前
C 语言主控开发与显控开发能力体系及技术栈详解,STM32、QT、嵌入式、边缘系统显示
stm32·单片机·tcp/ip·microsoft·fpga开发·51单片机·wpf
不会先思考4 小时前
C5.3:发射极偏置和LED驱动电路
嵌入式硬件·模拟电路·三极管·发射极偏置电路·bjt
LJWWD6 小时前
AI小智单片机esps32-s3烧录教程
单片机·嵌入式硬件
szxinmai主板定制专家10 小时前
基于FPGA的热电偶测温数据采集系统,替代NI的产品(二)总体设计方案
arm开发·人工智能·嵌入式硬件·fpga开发
herderl12 小时前
【无标题】命名管道(Named Pipe)是一种在操作系统中用于**进程间通信(IPC)** 的机制
java·linux·服务器·嵌入式硬件·php
智者知已应修善业13 小时前
【51单片机数码管循环显示3位数字】2022-10-26
c语言·经验分享·笔记·嵌入式硬件·算法·51单片机
何以问天涯15 小时前
K210人脸识别系统
人工智能·python·嵌入式硬件·ai编程
嵌入式小李15 小时前
stm32项目(25)——基于stm32的植物生长箱环境监测系统
stm32·单片机·嵌入式硬件
青草地溪水旁16 小时前
socket编程中系统调用send()详细讲解
嵌入式硬件·socket·内核空间·用户空间