普通信号量 PK 互斥信号量

重点:当串口发送数据同时有几个任务调用时,则出现打印数据混乱,此时就需要使用互斥信号量了,确保只有一个任务在调用串口发送。
数据混乱原因:多个不同优先级任务运行时使用同一个信号量将因为阻塞导致任务执行出现优先级翻转问题;

示例将演示任务优先级翻转问题:
创建3个任务,优先级不同,创建二值信号量并释放信号量。
任务1 优先级低:获取信号量,打印运行信息,任务调度,释放信号量,延时
任务2 优先级中:打印运行信息、延时
任务3 优先级高:获取信号量,打印运行信息,释放信号量,延时
示例代码:

二值信号量演示:

main.c

#include "AppTask.h"

static void BSP_Init(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//优先级0-15
	LED_GPIO_Config();
	USART_Config();
}

int main(void)
{
	BaseType_t xReturn  = pdPASS;

	BSP_Init();
	xReturn = xTaskCreate((TaskFunction_t) (AppCreate_Task),
						 (const char*)	"AppCreate_Task",
						 (uint16_t) 	512, 
						 (void*)		NULL,
						(UBaseType_t) 	1,
						(TaskHandle_t) 	(&AppCreateTask_Handle));
	if(xReturn == pdPASS)
	{
		printf("AppCreate_Task Create Succeed!\r\n");
		vTaskStartScheduler();//启动任务调度
	}
	else{printf("AppCreate_Task Create Fail!\r\n");}
	while(1);
}

AppTask.h

#ifndef _AppTask_H_
#define _AppTask_H_
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

#include "bsp_led.h"
#include "bsp_usart.h"

extern TaskHandle_t AppCreateTask_Handle;
extern void AppCreate_Task(void* parameter);

#endif

AppTask.c

#include "AppTask.h"

TaskHandle_t AppCreateTask_Handle = NULL;
static TaskHandle_t LowPriority_Handle = NULL;
static TaskHandle_t MidPriority_Handle = NULL;
static TaskHandle_t HigPriority_Handle = NULL;

SemaphoreHandle_t BinarySem_Handle = NULL;

void LowPriority_Task(void* parameter);
void MidPriority_Task(void* parameter);
void HigPriority_Task(void* parameter);

/**************************************
 * function:创建App任务函数
 * parameter:void*
 * return:void
 * date:2022.3.21
 * note:
 * ***********************************/
void AppCreate_Task(void* parameter)
{
    BaseType_t xReturn = pdPASS;

    taskENTER_CRITICAL();

    BinarySem_Handle = xSemaphoreCreateBinary();
    if(BinarySem_Handle == NULL){printf("BinarySem_Handle Create Fail!\r\n");}
    else{printf("BinarySem_Handle Create Succend!\r\n");}
    xReturn = xSemaphoreGive(BinarySem_Handle);
    if ( xReturn == pdTRUE )
		printf("BinarySem_Handle  二值信号量释放成功!\r\n");
	else
		printf("BinarySem_Handle  二值信号量释放失败!\r\n");

    xReturn = xTaskCreate((TaskFunction_t) LowPriority_Task,\
                            (const char*) "LowPriority_Task",\
                            (uint16_t) 128,\
                            (void*) NULL,\
                            (UBaseType_t) 2,\
                            (TaskHandle_t*) &LowPriority_Handle);
    if(xReturn != pdPASS){printf("LowPriority Create Fail!\r\n");}
    else{printf("LowPriority Create Succeed!\r\n");}

    xReturn = xTaskCreate((TaskFunction_t) MidPriority_Task,\
                            (const char*) "MidPriority_Task",\
                            (uint16_t) 128,\
                            (void*) NULL,\
                            (UBaseType_t) 3,\
                            (TaskHandle_t*) &MidPriority_Handle);
    if(xReturn != pdPASS){printf("MidPriority Create Fail!\r\n");}
    else{printf("MidPriority Create Succeed!\r\n");}

    xReturn = xTaskCreate((TaskFunction_t) HigPriority_Task,\
                            (const char*) "HigPriority_Task",\
                            (uint16_t) 128,\
                            (void*) NULL,\
                            (UBaseType_t) 4,\
                            (TaskHandle_t*) &HigPriority_Handle);
    if(xReturn != pdPASS){printf("HigPriority Create Fail!\r\n");}
    else{printf("HigPriority Create Succeed!\r\n");}

    vTaskDelete(AppCreateTask_Handle);
    taskEXIT_CRITICAL();
}

void LowPriority_Task(void* parameter)
{
    BaseType_t xReturn = pdPASS;
    unsigned long int i = 0;

    while(1)
    {
        printf("LowPriority_Task 获取信号量\r\n");
        xReturn = xSemaphoreTake(BinarySem_Handle,portMAX_DELAY);
        if(xReturn == pdTRUE)
        {
            printf("LowPriority_Task Run...\r\n");
            for(i=0;i < 2000000;i++){taskYIELD();}

            printf("LowPriority_Task 释放信号量\r\n");
            xReturn = xSemaphoreGive(BinarySem_Handle);
            vTaskDelay(1000);
        }
        else{printf("LowPriority_Task xSemaphoreTake Fail!\r\n");}
    }
}

void MidPriority_Task(void* parameter)
{
    while(1)
    {
        LED1_TOGGLE;vTaskDelay(1000); printf("MidPriority_Task Run...\r\n");
    }
}

void HigPriority_Task(void* parameter)
{
   BaseType_t xReturn = pdPASS;

    while(1)
    {
        printf("HigPriority_Task 获取信号量\r\n");
        xReturn = xSemaphoreTake(BinarySem_Handle,portMAX_DELAY);
        if(xReturn == pdTRUE)
        {
            printf("HigPriority_Task Run...\r\n");
            printf("HigPriority_Task 释放信号量\r\n");
            xReturn = xSemaphoreGive(BinarySem_Handle);
            vTaskDelay(1000);
        }
        else{printf("HigPriority_Task xSemaphoreTake Fail!\r\n");}
    }
}

示例现象:
在这里插入图片描述
注:低优先级任务执行过程中,高优先级任务插队运行没有获取到信号量而阻塞,故低优先级任务继续执行,被中优先级任务抢占执行,导致中间多个中优先级任务执行完后低优先级才能释放信号量,高优先级任务获取到信号而继续执行。
但是高优先级任务被打断占用较多时间,此时程序设计已经出现不想要的结果。

互斥信号量演示:

AppTask.c

#include "AppTask.h"

TaskHandle_t AppCreateTask_Handle = NULL;
static TaskHandle_t LowPriority_Handle = NULL;
static TaskHandle_t MidPriority_Handle = NULL;
static TaskHandle_t HigPriority_Handle = NULL;

SemaphoreHandle_t MutexSem_Handle = NULL;

void LowPriority_Task(void* parameter);
void MidPriority_Task(void* parameter);
void HigPriority_Task(void* parameter);

/**************************************
 * function:创建App任务函数
 * parameter:void*
 * return:void
 * date:2022.3.21
 * note:
 * ***********************************/
void AppCreate_Task(void* parameter)
{
    BaseType_t xReturn = pdPASS;

    taskENTER_CRITICAL();

    MutexSem_Handle = xSemaphoreCreateMutex();
    if(MutexSem_Handle == NULL){printf("MutexSem_Handle Create Fail!\r\n");}
    else{printf("MutexSem_Handle Create Succend!\r\n");}
    xReturn = xSemaphoreGive(MutexSem_Handle);
    if ( xReturn == pdTRUE )
		printf("MutexSem_Handle  二值信号量释放成功!\r\n");
	else
		printf("MutexSem_Handle  二值信号量释放失败!\r\n");

    xReturn = xTaskCreate((TaskFunction_t) LowPriority_Task,\
                            (const char*) "LowPriority_Task",\
                            (uint16_t) 128,\
                            (void*) NULL,\
                            (UBaseType_t) 2,\
                            (TaskHandle_t*) &LowPriority_Handle);
    if(xReturn != pdPASS){printf("LowPriority Create Fail!\r\n");}
    else{printf("LowPriority Create Succeed!\r\n");}

    xReturn = xTaskCreate((TaskFunction_t) MidPriority_Task,\
                            (const char*) "MidPriority_Task",\
                            (uint16_t) 128,\
                            (void*) NULL,\
                            (UBaseType_t) 3,\
                            (TaskHandle_t*) &MidPriority_Handle);
    if(xReturn != pdPASS){printf("MidPriority Create Fail!\r\n");}
    else{printf("MidPriority Create Succeed!\r\n");}

    xReturn = xTaskCreate((TaskFunction_t) HigPriority_Task,\
                            (const char*) "HigPriority_Task",\
                            (uint16_t) 128,\
                            (void*) NULL,\
                            (UBaseType_t) 4,\
                            (TaskHandle_t*) &HigPriority_Handle);
    if(xReturn != pdPASS){printf("HigPriority Create Fail!\r\n");}
    else{printf("HigPriority Create Succeed!\r\n");}

    vTaskDelete(AppCreateTask_Handle);
    taskEXIT_CRITICAL();
}

void LowPriority_Task(void* parameter)
{
    BaseType_t xReturn = pdPASS;
    unsigned long int i = 0;

    while(1)
    {
        printf("LowPriority_Task 获取信号量\r\n");
        xReturn = xSemaphoreTake(MutexSem_Handle,portMAX_DELAY);
        if(xReturn == pdTRUE)
        {
            printf("LowPriority_Task Run...\r\n");
            for(i=0;i < 2000000;i++){taskYIELD();}

            printf("LowPriority_Task 释放信号量\r\n");
            xReturn = xSemaphoreGive(MutexSem_Handle);
            vTaskDelay(1000);
        }
        else{printf("LowPriority_Task xSemaphoreTake Fail!\r\n");}
    }
}

void MidPriority_Task(void* parameter)
{
    while(1)
    {
        LED1_TOGGLE;vTaskDelay(1000); printf("MidPriority_Task Run...\r\n");
    }
}

void HigPriority_Task(void* parameter)
{
   BaseType_t xReturn = pdPASS;

    while(1)
    {
        printf("HigPriority_Task 获取信号量\r\n");
        xReturn = xSemaphoreTake(MutexSem_Handle,portMAX_DELAY);
        if(xReturn == pdTRUE)
        {
            printf("HigPriority_Task Run...\r\n");
            printf("HigPriority_Task 释放信号量\r\n");
            xReturn = xSemaphoreGive(MutexSem_Handle);
            vTaskDelay(1000);
        }
        else{printf("HigPriority_Task xSemaphoreTake Fail!\r\n");}
    }
}

演示现象:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值