FreeRTOS复习笔记(四) —— 信号量

阅读: 评论:0

FreeRTOS复习笔记(四) —— 信号量

FreeRTOS复习笔记(四) —— 信号量

FreeRTOS复习笔记(四) —— 信号量

一、二值信号量与计数信号量

1.本例程思路:

本篇将二值信号量与计数信号量写入同一段代码,使用 _USE_BINARY_SEMAPHORE 与 _USE_COUNT_SEMAPHORE 进行区分

对于二值信号量,创建两个任务,一个任务用于释放信号量,另一个任务用于获取信号量,当KEY_GPIO(PA0)出现下降沿时释放信号量

对于计数信号量,当KEY_GPIO(PA0)出现下降沿时获取信号量和释放信号量,并打印当前可使用信号量数量

二值信号量的创建可以调用 xSemaphoreCreateBinary 函数,计数信号量的创建可以调用 xSemaphoreCreateCounting 函数

释放信号量使用 xSemaphoreGive,获取信号量使用 xSemaphoreTake

2.代码编写

/********************************************************************************* @文件名: xxx.c* @作  者: author* @版  本: v1.0.0* @日  期: 2021.12.24* @简  介: 无* @注  意: 无*******************************************************************************/
#include "stm32f10x.h"#include "dr_usart.h"
#include "dr_led.h"
#include "dr_key.h"#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"//#define _USE_BINARY_SEMAPHORE
#define _USE_COUNT_SEMAPHOREvoid AppTaskCreateTask(void *);
void LEDTask(void *);
void KEYTask(void *);/* --- 任务 --- */
TaskHandle_t LEDTask_Handle = NULL;#ifdef _USE_BINARY_SEMAPHORE
/* --- 二值信号量 --- */
SemaphoreHandle_t BinarySemaphore_Handle = NULL;
#endif#ifdef _USE_COUNT_SEMAPHORE
/* --- 计数信号量 --- */
SemaphoreHandle_t CountSemaphore_Handle = NULL;
#endif/*** @简  介: 无* @参  数: 无* @返回值: 无*/
int main(void)
{/* --------- --------- --------- --------- --------- --------- ---------  *//* 中断分组4 */NVIC_Priority_Group_Config();                                        /* * *//* 串口1配置 */USART1_Config();                                                     /* * *//* LED(PA8, PA6)配置 */LED_GPIO_Config();                                                   /* * *//* KEY(PA0)配置 */KEY_GPIO_Config();/* --------- --------- --------- --------- --------- --------- ---------  *//* 创建任务 */xTaskCreate(AppTaskCreateTask, "AppTaskCreateTask", 128, NULL, 1, NULL);/* 开启任务调度 */vTaskStartScheduler();while(1);
}/*** @简  介: 无* @参  数: 无* @返回值: 无*/
void AppTaskCreateTask(void *pvParameters)
{/* 临界保护 */taskENTER_CRITICAL();/* 创建任务 */xTaskCreate(LEDTask, "LEDTask", 128, NULL, 2, &LEDTask_Handle);xTaskCreate(KEYTask, "KEYTask", 128, NULL, 3, NULL);#ifdef _USE_BINARY_SEMAPHORE/* 创建二值信号量 */BinarySemaphore_Handle = xSemaphoreCreateBinary();if (BinarySemaphore_Handle != NULL)printf("--- The BinarySemaphore was created successful ---.rnrn");
#endif#ifdef _USE_COUNT_SEMAPHORE/* 创建计数信号量, 信号量个数 初始化均可被获取 */CountSemaphore_Handle = xSemaphoreCreateCounting(2, 2);if (CountSemaphore_Handle != NULL)printf("--- The CountSemaphores was created ---.rnrn");
#endifvTaskDelete(NULL);taskEXIT_CRITICAL();
}/*** @简  介: 无* @参  数: 无* @返回值: 无*/
void LEDTask(void *pvParameters)
{BaseType_t xReturn = pdFALSE;for (;;){#ifdef _USE_BINARY_SEMAPHORE/* 获取二值信号量, 信号量句柄 等待超时时间 */xReturn = xSemaphoreTake(BinarySemaphore_Handle, 0);if (xReturn == pdTRUE)printf("The BinarySemaphore has been obtained.rn");#endif/* 翻转LED */GPIOA->ODR ^= ((uint16_t)0x0100);//		printf("LED %srn", ((GPIOA->IDR & 0x0100) != 0) ? "is running." : "stops running.");(void)xReturn;vTaskDelay(50);}
}/*** @简  介: 无* @参  数: 无* @返回值: 无*/
void KEYTask(void *pvParameters)
{uint8_t level_high = 0;uint8_t level_low  = 0;uint8_t edge_fall  = 0;uint8_t edge_rise  = 0;uint8_t _switch = 0;BaseType_t xReturn = pdFALSE;UBaseType_t CurrentSemaphoreNum = 0;for (;;){/* 高电平/上升沿检测 */if ( (GPIOA->IDR & 0x0001) != 0 ){if(level_low == 1)edge_rise = 1;level_low  = 0;level_high = 1;}/* 低电平/下降沿检测 */if ( (GPIOA->IDR & 0x0001) == 0 ){if(level_high == 1)edge_fall  = 1;level_high = 0; level_low  = 1;}/* 出现下降沿 */if (edge_fall){#ifdef _USE_BINARY_SEMAPHORE/* 释放二值信号量 */xReturn = xSemaphoreGive(BinarySemaphore_Handle);if (xReturn == pdTRUE)printf("The BinarySemaphore has been released successful.rn");#endif#ifdef _USE_COUNT_SEMAPHOREswitch(_switch){case 0:/* 获取计数信号量, 信号量句柄 等待超时时间 */xReturn = xSemaphoreTake(CountSemaphore_Handle, 0);_switch++;break;case 1:/* 获取计数信号量 */xReturn = xSemaphoreTake(CountSemaphore_Handle, 0);_switch++;break;case 2:/* 获取计数信号量 */xReturn = xSemaphoreTake(CountSemaphore_Handle, 0);_switch++;break;case 3:/* 释放计数信号量, 信号量句柄 */xReturn = xSemaphoreGive(CountSemaphore_Handle);_switch++;break;case 4:/* 释放计数信号量 */xReturn = xSemaphoreGive(CountSemaphore_Handle);_switch = 0;break;default: _switch = 0;}if ( (_switch == 1) || (_switch == 2) || (_switch == 3) ){if (xReturn == pdTRUE)printf("obtained. ");elseprintf("#error: no Semaphore. ");}if ( (_switch == 0) || (_switch == 4) )printf("released. ");/* 计数信号量数量 */CurrentSemaphoreNum = uxSemaphoreGetCount(CountSemaphore_Handle);printf("CurrentSemphoresNum: %lurn", CurrentSemaphoreNum);#endif}edge_fall = 0;edge_rise = 0;(void)edge_rise;(void)_switch;(void)CurrentSemaphoreNum;vTaskDelay(20);}
}

3.使用串口观察输出信息

二值信号量(一个任务释放信号量,另一个任务获取信号量)

计数信号量(获取后信号量数量减少,释放后增加)

经验证,程序运行结果与预想一致

二、互斥信号量

1.本例程思路:

创建三个任务,首先使用二值信号量模拟出优先级翻转,随后将二值信号量改为使用互斥信号量,与二值信号量进行对比,展示出互斥信号量的优先级继承机制

本篇使用 _USE_BINARY_SEMAPHORE 与 _USE_MUTEX_SEMAPHORE 区分使用二值信号量与互斥信号量

创建二值信号量调用 xSemaphoreCreateBinary 函数,创建互斥信号量调用 xSemaphoreCreateMutex 函数

2.代码编写

/********************************************************************************* @文件名: xxx.c* @作  者: author* @版  本: v1.0.0* @日  期: 2021.12.26* @简  介: 无* @注  意: 无*******************************************************************************/
#include "stm32f10x.h"#include "dr_usart.h"
#include "dr_led.h"
#include "dr_key.h"#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"//#define _USE_BINARY_SEMAPHORE
#define _USE_MUTEX_SEMAPHOREvoid AppTaskCreateTask(void *);
void LowPriorityTask(void *);
void MidPriorityTask(void *);
void HighPriorityTask(void *);#ifdef _USE_BINARY_SEMAPHORE
/* --- 二值信号量 --- */
SemaphoreHandle_t BinarySemaphore_Handle = NULL;
#else
/* --- 互斥信号量 --- */
SemaphoreHandle_t MutexSemaphore_Handle = NULL;
#endif/*** @简  介: 无* @参  数: 无* @返回值: 无*/
int main(void)
{/* --------- --------- --------- --------- --------- --------- ---------  *//* 中断分组4 */NVIC_Priority_Group_Config();                                        /* * *//* 串口1配置 */USART1_Config();                                                     /* * *//* LED(PA8, PA6)配置 */LED_GPIO_Config();                                                   /* * *//* KEY(PA0)配置 */KEY_GPIO_Config();/* --------- --------- --------- --------- --------- --------- ---------  *//* 创建任务 */xTaskCreate(AppTaskCreateTask, "AppTaskCreateTask", (uint16_t)128, NULL, (UBaseType_t)1, NULL);/* 开启任务调度 */vTaskStartScheduler();while(1);
}/*** @简  介: 无* @参  数: 无* @返回值: 无*/
void AppTaskCreateTask(void *pvParameters)
{/* 临界保护 */taskENTER_CRITICAL();/* 创建任务 */xTaskCreate(HighPriorityTask, "HighPriorityTask", (uint16_t)128, NULL, (UBaseType_t)4, NULL);xTaskCreate(MidPriorityTask, "MidPriorityTask", (uint16_t)128, NULL, (UBaseType_t)3, NULL);xTaskCreate(LowPriorityTask, "LowPriorityTask", (uint16_t)128, NULL, (UBaseType_t)2, NULL);#ifdef _USE_BINARY_SEMAPHORE/* 创建二值信号量 */BinarySemaphore_Handle = xSemaphoreCreateBinary();if (BinarySemaphore_Handle != NULL)printf("--- BinarySemaphore was Created ---.rnrn");/* 释放二值信号量 */xSemaphoreGive(BinarySemaphore_Handle);
#else/* 创建互斥信号量 */MutexSemaphore_Handle = xSemaphoreCreateMutex();if (MutexSemaphore_Handle != NULL)printf("--- MutexSemaphore was Created ---.rnrn");
#endifvTaskDelete(NULL);taskEXIT_CRITICAL();
}/*** @简  介: 无* @参  数: 无* @返回值: 无*/
void LowPriorityTask(void *pvParameters)
{uint32_t i = 0;BaseType_t xReturn = pdFALSE;for (;;){#ifdef _USE_BINARY_SEMAPHORE/* 等待二值信号量 */xReturn = xSemaphoreTake(BinarySemaphore_Handle, portMAX_DELAY);#else/* 等待互斥信号量 */xReturn = xSemaphoreTake(MutexSemaphore_Handle, portMAX_DELAY);#endif/* LowPriorityTask 占用信号量 */if (xReturn == pdTRUE)printf("LowPriorityTask has obtained the semaphore.rn");/* 任务切换 */for(i = 0; i < 0x7ffff; i++)taskYIELD();#ifdef _USE_BINARY_SEMAPHORE/* 释放二值信号量 */xReturn = xSemaphoreGive(BinarySemaphore_Handle);#else/* 释放互斥信号量 */xReturn = xSemaphoreGive(MutexSemaphore_Handle);#endif/* LowPriorityTask 释放信号量 */if (xReturn == pdTRUE)printf("LowPriorityTask has released the semaphore.rn");vTaskDelay(50);}
}/*** @简  介: 无* @参  数: 无* @返回值: 无*/
void MidPriorityTask(void *pvParameters)
{for (;;){/* 翻转LED */GPIOA->ODR ^= ((uint16_t)0x0100);printf("MidPriorityTask is running.rn");vTaskDelay(50);}
}/*** @简  介: 无* @参  数: 无* @返回值: 无*/
void HighPriorityTask(void *pvParameters)
{BaseType_t xReturn = pdFALSE;for (;;){#ifdef _USE_BINARY_SEMAPHORE/* 等待二值信号量 */xReturn = xSemaphoreTake(BinarySemaphore_Handle, portMAX_DELAY);#else/* 等待互斥信号量 */xReturn = xSemaphoreTake(MutexSemaphore_Handle, portMAX_DELAY);#endif/* HighPriorityTask 占用信号量 */if (xReturn == pdTRUE)printf("HighPriorityTask has obtained the semaphore.rn");#ifdef _USE_BINARY_SEMAPHORE/* 释放二值信号量 */xReturn = xSemaphoreGive(BinarySemaphore_Handle);#else/* 释放互斥信号量 */xReturn = xSemaphoreGive(MutexSemaphore_Handle);#endif/* HighPriorityTask 释放信号量 */if (xReturn == pdTRUE)printf("HighPriorityTask has released the semaphore.rn");vTaskDelay(50);}
}

3.使用串口观察输出信息

二值信号量(发生了优先级翻转,打断了高优先级任务)

互斥信号量(体现出了互斥量的优先级继承机制,提升了低优先级任务的优先级)

经验证,程序运行结果与预想一致

本文发布于:2024-01-31 22:16:41,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170671060131747.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:信号量   笔记   FreeRTOS
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23