【FreeRTOS】RTOS任务的同步与互斥:(二)信号量

【FreeRTOS】RTOS任务的同步与互斥:(二)信号量

  • 信号量概念
  • 二值信号量
    • 二值信号量概念
    • 二值信号量相关API函数
    • 二值信号量的案例设计
      • cubeMX配置
      • 软件程序设计
  • 计数型信号量
    • 计数型信号量概念
    • 计数型信号量相关API函数
    • 二值信号量的案例设计
      • cubeMX配置
      • 软件程序设计

同步与互斥是学习FreeRTOS的重点内容,同步与互斥的相关的内容可参考:
FreeRTOS入门教程(同步与互斥)
RTOS任务的同步与互斥:(一)队列

同步与互斥的概念:

  • 同步: A等待B做完某件事

  • 互斥: 某一资源同一时间仅能有一个用户访问

  • RTOS同步与互斥的方式: 队列(queue)、信号量(semaphoe)、互斥量(mutex)、事件组(event group)、任务通知(task notification)等

信号量概念

  • 信号量(Semaphore),是在多任务环境下使用的一种机制,是可以用来保证两个或多个关键代码段不被并 发调用。
  • 信号量这个名字,我们可以把它拆分来看,信号可以起到通知信号的作用,然后我们的量还可以用来表示资源的数量,当我们的量只有0和1的时候,它就可以被称作二值信号量,只有两个状态,当我们的那个量没有限制的时候,它就可以被称作为计数型信号量。
  • 信号量也是队列的一种。

二值信号量

二值信号量概念

二值信号量其实就是一个长度为1,大小为零的队列,只有0和1两种状态,通常情况下,我们用它来进行互斥访问或任务同步。
互斥访问: 比如门钥匙,只有获取到钥匙才可以开门
任务同步: 比如采集完成环境数据后才能显示

二值信号量相关API函数

函数描述
xSemaphoreCreateBinary()使用动态方式创建二值信号量
xSemaphoreCreateBinaryStatic()使用静态方式创建二值信号量
xSemaphoreGive()释放信号量
xSemaphoreGiveFromISR()在中断中释放信号量
xSemaphoreTake()获取信号量
xSemaphoreTakeFromISR()在中断中获取信号量

创建二值信号量

SemaphoreHandle_t xSemaphoreCreateBinary( void )

返回值:

  • 成功,返回对应二值信号量的句柄;
  • 失败,返回 NULL 。

释放二值信号量

BaseType_t  xSemaphoreGive( SemaphoreHandle_t xSemaphore )

参数:
xSemaphore:要释放的信号量句柄

返回值:

  • 成功,返回 pdTRUE
  • 失败,返回 errQUEUE_FULL

获取二值信号量

BaseType_t  xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );

参数:

  • xSemaphore:要获取的信号量句柄
  • xTicksToWait:超时时间,0 表示不超时,portMAX_DELAY表示卡死等待;

返回值:

  • 成功,返回 pdTRUE
  • 失败,返回 errQUEUE_FULL 。

二值信号量的案例设计

创建一个二值信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。
注意:

  • 该配置建立在RTOS的基础工程上进行配置,不熟悉基础配置的可参考:使用CubeMX快速移植FreeRTOS工程到蓝桥杯开发板
  • 硬件平台使用的是蓝桥杯的开发板(STM32G431RBT6),若平台不一致,请根据自行的按键与LED灯进行配置
  • 底层LED与按键扫描的实现函数请参考: 使用CubeMX快速移植FreeRTOS工程到蓝桥杯开发板 的文末底层功能驱动函数的实现

cubeMX配置

创建2个任务

动态方式创建一个二值信号量

软件程序设计

通过CubeMX生成的代码,已经为我们创建好了个任务及其信号量,后续用户只需要写任务逻辑即可

任务一检测到按键一按下放入信号量

void task1(void const * argument)
{uint8_t key;while(1){key = key_scan();			//扫描按键if(key == KEY1_PRES)	//按键一按下{//printf("key1 按下\r\n");if(xSemaphoreGive(binarySem1Handle) == pdTRUE)	//放入信号量printf("二值信号量放入成功\r\n");elseprintf("二值信号量放入失败\r\n");}osDelay(10);}
}

任务二检测到按键二按下获取信号量(以阻塞的方式获取为例)

void task2(void const * argument)
{uint8_t key;while(1){key = key_scan();if(key == KEY2_PRES){//printf("key2 按下\r\n");//以阻塞等待的方式获取信号量if(xSemaphoreTake(binarySem1Handle,portMAX_DELAY) == pdTRUE)	printf("二值信号量获取成功\r\n");elseprintf("二值信号量获取失败\r\n");}osDelay(10);}
}

注意: 系统封装的创新信号量函数 osSemaphoreCreate 在创建的时候默认已经放入了一个信号量,因此需要先读取信号量后才能放入成功,当然可以注释系统的默认创建,通过xSemaphoreCreateBinary函数重新创建一个空的信号量,这里采用默认创建。

测试效果:


计数型信号量

计数型信号量概念

  计数型信号量相当于队列长度大于1 的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的。

计数信号量的停车位模拟图

计数型信号量相关API函数

函数描述
xSemaphoreCreateCounting()使用动态方法创建计数型信号量
xSemaphoreCreateCountingStatic()使用静态方法创建计数型信号量
uxSemaphoreGetCount()获取信号量的计数值

创建计数型信号量函数原型

SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);
参数描述
uxMaxCount可以达到的最大计数值
uxInitialCount创建信号量时分配给信号量的计数值

返回值:

  • 成功,返回对应计数型信号量的句柄;
  • 失败,返回 NULL 。

计数型信号量的释放和获取与二值信号量完全相同 !!!
释放二值信号量

BaseType_t  xSemaphoreGive( SemaphoreHandle_t xSemaphore )

参数:
xSemaphore:要释放的信号量句柄

返回值:

  • 成功,返回 pdTRUE
  • 失败,返回 errQUEUE_FULL

获取二值信号量

BaseType_t  xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );

参数:

  • xSemaphore:要获取的信号量句柄
  • xTicksToWait:超时时间,0 表示不超时,portMAX_DELAY表示卡死等待;

返回值:

  • 成功,返回 pdTRUE
  • 失败,返回 errQUEUE_FULL 。

二值信号量的案例设计

创建一个计数型信号量,按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

cubeMX配置

创建2个任务:同二值信号量及其任务的管理一样,创建两个任务用于检测按键并实现逻辑业务控制程序

使能计数型信号量

创建一个计数型信号量:以默认的动态方式创建即可,核心需要修改信号量的名称和计数型信号量的长度

软件程序设计

通过CubeMX生成的代码,已经为我们创建好了个计数型信号量,同二值信号量一样,默认创建的初值量为最大值,这里使用创建,使得信号量初始值为0。

任务一检测到按键一按下放入计数型信号量

void task1(void const * argument)
{uint8_t key;while(1){key = key_scan();			//扫描按键if(key == KEY1_PRES)	//按键一按下{//printf("key1 按下\r\n");if(xSemaphoreGive(countingSem1Handle) == pdTRUE)	//放入信号量printf("计数型信号量放入成功\r\n\r\n");elseprintf("计数型信号量放入失败\r\n\r\n");}osDelay(10);}
}

任务二检测到按键二按下读取计数型信号量
这里获取信号量采用非阻塞方式,或信号量为空,则返回获取失败。

void task2(void const * argument)
{uint8_t key;while(1){key = key_scan();if(key == KEY2_PRES){//printf("key2 按下\r\n");//以阻塞等待的方式获取信号量if(xSemaphoreTake(countingSem1Handle,portMAX_DELAY) == pdTRUE)	printf("计数型信号量获取成功\r\n\r\n");elseprintf("计数型信号量获取失败\r\n\r\n");}osDelay(10);}
}

测试:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/549.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VUE 页码分页封装

VUE 页码封装组件 pagination/index.vue &#xff1a; <template><div class"pagination-contianer"><el-pagination background layout"prev, pager, next" :total"total" current-change"currentChange"> </e…

点赞列表查询列表

点赞列表查询列表 BlogController GetMapping("/likes/{id}") public Result queryBlogLikes(PathVariable("id") Long id) {return blogService.queryBlogLikes(id); }BlogService Override public Result queryBlogLikes(Long id) {String key BLOG_…

零基础小白如何自学网络安全(入门)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

从数据库中到处所有表的列、注释、类型、是否必填等信息

从数据库中到处所有中文表名、英文表名、所有列、注释、类型、长度、是否必填等信息&#xff0c;效果如下&#xff1a; 要实现上面的表格可以直接用SQL实现&#xff0c;实现SQL如下&#xff1a; #查询SQL select* FROMinformation_schema.COLUMNS as columns left join (sele…

【Jenkins PipeLine】Jenkins PipeLine 联动参数示例

目录 1. Pipeline script&#xff1a; 1.1.代码说明&#xff1a; 2. 实现效果&#xff1a; 3.联动说明&#xff1a; 4.Jenkins安装插件 1. Pipeline script&#xff1a; properties([parameters([[$class: "ChoiceParameter", choiceType: "PT_SINGLE_SELE…

在mini2440上编写linux应用程序、字符设备驱动程序的编写与编译

在mini2440上编写linux应用程序 结合前两篇的学习&#xff0c;一个linux操作系统已经在mini2440上运行起来了&#xff0c;结合交叉编译环境和nfs等工具&#xff0c;我们可以在mini2440上编写任何我们在linux系统编程中学到的应用程序。一个简要的多文件Makefile文件如下&#…

数组*巴巴拉拉

一&#xff0c;数组的定义以及创建方式 数组的作用&#xff1a;数组可以把一组数据的集合存放在单个变量下 创建数组有两种方式&#xff1a; 1.利用new创建数组 var arr new Array() 2.利用数组字面量创建数组(常用) var arr [] 注意点&#xff1a;数组里可以存放任…

C++笔记2:基类的静态变量子类能共享吗

C里&#xff0c;基类的静态变量子类能共享吗&#xff0c;为了验证这个问题这里写了一段代码进行测试&#xff1a; #include <iostream>class Base { public:static int staticVariable; };class Derived : public Base { };int Base::staticVariable 10;int main() {Ba…

2013–2022年福建漳江口互花米草分布无人机遥感数据集

文章目录 摘要数据集内容数据集命名方式数据引用与参考文献引用 摘要 本数据集利用无人机搭载可见光相机&#xff0c;获取福建漳江口湿地2013-2022年期间的航拍影像&#xff0c;通过影像拼接生成整个研究区的正射影像&#xff0c;制作十年尺度的遥感影像数据集及互花米草空间数…

Vue-条件渲染(初识vue渲染)

目录 一、Vue条件渲染-介绍 1.概念 2.特点 3.功能 4.好处 5.应用 二、Vue条件渲染-使用 1.初识渲染 2.条件v-if的使用 3.条件v-if-else的使用 4.条件v-else-if使用 5.template元素使用 6.条件渲染-阶段案例 7.条件v-show 三、Vue条件渲染-实例 1.权限管理系统 …

数据结构:查找与排序

注&#xff1a;以下代码均为C 查找 一、线性表的查找 1. 顺序查找 int search_seq(vector<int> s, int key){for(int i 0; i < s.size(); i){if(s[i] key)return i;}return -1; }2. 折半查找 (1)非递归&#xff1a;循环 int search_bin1(vector<int> s,…

C++初阶学习第一弹——C++入门(上)

前言&#xff1a; 很高兴&#xff0c;从今天开始&#xff0c;我们就要步入C的学习了&#xff0c;在这之前我们已经对C语言有了不错的了解&#xff0c;对数据结构也有了一些自己的认识&#xff0c;今天开始&#xff0c;我们就进入这个新的主题的学习——C 目录 一、C的发展即其特…

一个快速克隆方法引出深浅拷贝说明

提供的代码是一个泛型扩展方法&#xff0c;用于对任意类型的对象T进行浅拷贝&#xff08;shallow copy&#xff09;。这个方法使用反射来调用对象的MemberwiseClone方法&#xff0c;该方法为所有字段&#xff08;包括值类型和引用类型字段&#xff09;创建新的副本&#xff0c;…

解析OceanBase v4.2函数索引进行查询优化

一、如何通过函数索引来进行查询优化 函数索引是一种优化查询的技术&#xff0c;其主要作用在于提升包含函数调用的查询语句的执行速度。当查询语句中包含函数调用时&#xff0c;数据库系统需要逐行执行函数计算&#xff0c;这无疑会增加查询的复杂性&#xff0c;导致查询速度…

【C语言】多字节字符、宽字符(涉及字符集和编码)

字符集、编码&#xff1a; 字符集&#xff1a;一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称&#xff0c;包括各国家文字、标点符号、图形符号、数字等。例如&#xff1a;ASCII、Unicode、GB2312、GBK、GB18030、BIG5(繁体中文) ... 编码方式&#xff1a;符号…

【Flutter】自动生成图片资源索引插件一:FlutterAssetRefGenerator

介绍 FlutterAssetRefGenerator 插件&#xff1a;windows上 点击生成图片索引按钮后&#xff0c;pubspec.yaml 会出现中文乱码&#xff0c;需要手动改乱码&#xff1b;mac上没问题。 优点&#xff1a;点击图标自动生成。 目录 介绍一、安装二、使用 一、安装 安装FlutterAsset…

移动端不居中问题/安卓和ios下line-height上下居中 css兼容问题

移动端开发过程&#xff0c;经常会写带0.5px边框角标类的样式&#xff0c;直接使用border设置0.5px边框&#xff0c;ios有些机型会出现显示不完整的情况。所以改用伪元素方法实现边框。代码如下&#xff1a; .comment-entry::after{content: ;position: absolute;left: 0;top: …

快速IO的方式|Java快读模板

处理IO的方式&#xff1a; 处理输入和输出的方式&#xff1a; C&#xff1a;cin / cout Java&#xff1a;Scanner / System.out 但是这两种有超时的风险 那么C处理方式&#xff1a;直接改为scanf / printf &#xff0c;也就是C语言中的读写方式 Java处理方式&#xff1a;准备一…

Python 中 + 和 += 赋值操作的性能比较

1. 问题背景 在 Python 中&#xff0c;我们可以通过 和 … 完成累加操作&#xff0c;在实际开发过程中我们一般会优先选择 &#xff0c;然而最近在对比 和 … 的性能时出现了 反而更慢的现象。因此&#xff0c;我们决定对此问题进行深入探讨。 2. 解决方案 为了准确地…

C语言---贪吃蛇(一)---准备工作

文章目录 前言1.Win32 API介绍1.1.Win32 API1.2. 控制台程序1.3.控制台屏幕上的坐标[COORD](https://learn.microsoft.com/zh-cn/windows/console/coord-str)1.4.[GetStdHandle](https://learn.microsoft.com/zh-cn/windows/console/getstdhandle)1.5.[GetConsoleCursorInfo](h…