一、二值信号量简介

二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一些细微的差别,互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号另更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问。和队列一样,信号量API函数允许设置一个阻塞时间,阻塞时间是当任务获取信号量的时候由于信号量无效从而导致任务进入阻塞态的最大时钟节拍数。如果多个任务同时阻塞在同一个信号量上的话那么优先级最高的那个任务优先获得信号量,这样当信号量有效的时候高优先级的任务就会解除阻塞状态二值信号量其实就是一个只有一个队列项的队列,这个特殊的队列要么是满的,要么是空的,这不正好就是二值的吗?任务和中断使用这个特殊队列不用在乎队列中存的是什么消息,只需要知道这个队列是满的还是空的。可以利用这个机制来完成任务与中断之间的同步。在实际应用中通常会使用一个任务来处理MCU的某个外设,比如网络应用中,一般最简单的方法就是使用一个任务去轮询的查询MCU的ETH(网络相关外设,如STM32的以太网MAC)外设是否有数据,当有数据的时候就处理这个网络数据。这样使用轮询的方式是很浪费CPU资源的,而且也阻止了其他任务的运行。最理想的方法就是当没有网络数据的时候网络任务就进入阻塞态,把CPU让给其他的任务,当有数据的时候网络任务才去执行。现在使用二值信号量就可以实现这样的功能,任务通过获取信号量来判断是否有网络数据,没有的话就进入阻塞态,而网络中断服务函数(大多数的网络外设都有中断功能,比如STM32的MAC专用DMA中断,通过中断可以判断是否接收到数据)通过释放信号量来通知任务以太网外设接收到了网络数据,网络任务可以去提取处理了。网络任务只是在一直的获取二值信号量,它不会释放信号量,而中断服务函数是一直在释放信号量,它不会获取信号量。在中断服务函数中发送信号量可以使用函数xSemaphoreGiveFromISR(),也可以使用任务通知功能来替代二值信号量,而且使用任务通知的话速度更快,代码量更少。使用二值信号量来完成中断与任务同步的这个机制中,任务优先级确保了外设能够得到及时的处理,这样做相当于推迟了中断处理过程。也可以使用队列来替代二值信号量,在外设事件的中断服务函数中获取相关数据,并将相关的数据通过队列发送给任务。如果队列无效的话任务就进入阻塞态,直至队列中有数据,任务接收到数据以后就开始相关的处理过程。下面几
个步骤演示了二值信号量的工作过程。

1、二值信号量无效

在上图中任务Task通过函数xSemaphoreTake()获取信号量,但是此时二值信号量无效,所以任务Task进入阻塞态。

2、中断释放信号量

此时中断发生了,在中断服务函数中通过函数xSemaphoreGiveFromISR()释放信号量,因此信号量变为有效。

3、任务获取信号量成功

由于信号量已经有效了,所以任务Task获取信号量成功,任务从阻塞态解除,开始执行相关的处理过程。

4、任务再次进入阻塞态
由于任务函数一般都是一个大循环,所以在任务做完相关的处理以后就会再次调用函数xSemaphoreTake0获取信号量。在执行完第三步以后二值信号量就已经变为无效的了,所以任务将再次进入阻塞态,和第一步一样,直至中断再次发生并且调用函数xSemaphoreGiveFromISR()释放信号量。

二、二值信号量相关函数

1、创建二值信号量
同队列一样,要想使用二值信号量就必须先创建二值信号量,二值信号量创建函数如下表:

函数 描述
vSemaphoreCreateBinary() 动态创建二值信号量,这个是老版本FreeRTOS中使用的创建二值信号量的API函数。
xSemaphoreCreateBinary() 动态创建二值信号量,新版本FreeRTOS中使用的创建二值信号量API函数。
SemaphoreCreateBinaryStatic() 静态创建二值信号量

- ①、函数vSemaphoreCreateBinary()

此函数是老版本FreeRTOS中的创建二值信号量函数,新版本已经不再使用了,新版本的FreeRTOS使用xSemaphoreCreateBinary()来替代此函数,这里还保留这个函数是为了兼容那些基于老版本FreeRTOS而做的应用层代码。此函数是个宏,具体创建过程是由函数
xQueueGenericCreate()来完成的,在文件semphr.h中有如下定义:

void vSemaphoreCreateBinary(SemaphoreHandle_t xSemaphore)
参数 描述
xSemaphore 保存创建成功的二值信号量句柄。

- ②、函数xSemaphoreCreateBinary()

此函数是vSemaphoreCreateBinary()的新版本,新版本的FreeRTOS中统一用此函数来创建二值信号量。使用此函数创建二值信号量的话信号量所需要的RAM是由FreeRTOS的内存管理部分来动态分配的。此函数创建好的二值信号量默认是空的,也就是说刚创建好的二值信号量使用函数xSemaphoreTake()是获取不到的,此函数也是个宏,具体创建过程是由函数
xQueueGenericCreate()来完成的,函数原型如下:

SemaphoreHandle_t xSemaphoreCreateBinary(void)
参数 描述
返回值 NULL:二值信号量创建失败。其他值:创建成功的二值信号量句柄。

- ③、函数xSemaphoreCreateBinaryStatic()

此函数也是创建二值信号量的,只不过使用此函数创建二值信号量的话信号量所需要的RAM需要由用户来分配,此函数是个宏,具体创建过程是通过函数xQueueGenericCreateStatic()来完成的,函数原型如下:

SemaphoreHandle_t xSemaphoreCreateBinaryStatic(
StaticSemaphore_t*pxSemaphoreBuffer)
参数 描述
pxSemaphoreBuffer 指向一个StaticSemaphore_t类型的变量,用来保存信号量结构体。
返回值 NULL:二值信号量创建失败。其他值:创建成功的二值信号量句柄。

2、释放信号量
释放信号量的函数有两个,如下表所示:

函数 描述
xSemaphoreGive() 任务级信号量释放函数
xSemaphoreGiveFromISR() 中断级信号量释放函数

同队列一样,释放信号量也分为任务级和中断级。不管是二值信号量、计数型信号量还是互斥信号量,它们都使用上述表中的函数释放信号量,递归互斥信号量有专用的释放函数。

  • ①、函数xSemaphoreGive()
    此函数用于释放二值信号量、计数型信号量或互斥信号量,此函数是一个宏,真正释放信号量的过程是由函数xQueueGenericSend()来完成的,函数原型如下:
BaseType_t xSemaphoreGive(xSemaphore)
参数 描述
xSemaphore 要释放的信号量句柄。
返回值 pdPASS:释放信号量成功。errQUEUE_FULL:释放信号量失败。

- ②、函数xSemaphoreGiveFromISR()
此函数用于在中断中释放信号量,此函数只能用来释放二值信号量和计数型信号量,绝对不能用来在中断服务函数中释放互斥信号量!此函数是一个宏,真正执行的是函数xQueueGiveFromISR(),此函数原型如下:

BaseType_t xSemaphoreGiveFromISR(
SemaphoreHandle_t xSemaphore,
BaseType_t* pxHigherPriorityTaskWoken)
参数 描述
xSemaphore 要释放的信号量句柄。
pxHigherPriorityTaskWoken 标记退出此函数以后是否进行任务切换,这个变量的值由这三个函数来设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为pdTRUE的时候在退出中断服务函数之前一定要进行一次任务切换。
返回值 pdPASS:释放信号量成功。errQUEUE_FULL:释放信号量失败。

3、获取信号量
获取信号量也有两个函数,如下表所示:

函数 描述
xSemaphoreTake() 任务级获取信号量函数
xSemaphoreTakeFromISR() 中断级获取信号量函数

上表获取信号量同释放信号量的API函数一样,不管是二值信号量、计数型信号量还是互斥信号量,它们都可以使用表中的函数获取信号量。

- ①、函数xSemaphoreTake()

此函数用于获取二值信号量、计数型信号量或互斥信号量,此函数是一个宏,真正获取信号量的过程是由函数xQueueGenericReceive()来完成的,函数原型如下:

BaseType_t xSemaphoreTake(
SemaphoreHandle_t xSemaphore,
TickType_t xBlockTime)
参数 描述
xSemaphore 要获取的信号量句柄。
xBlockTime 阻塞时间。
返回值 pdTRUE:获取信号量成功。pdFALSE:超时,获取信号量失败。

- ②、函数xSemaphoreTakeFromISR()
此函数用于在中断服务函数中获取信号量,此函数用于获取二值信号量和计数型信号量,绝对不能使用此函数来获取互斥信号量!此函数是一个宏,真正执行的是函数
xQueueReceiveFromISR(),此函数原型如下:

Base Type_t xSemaphoreTakeFromISR(
SemaphoreHandle_t xSemaphore,
BaseType_t* pxHigherPriorityTaskWoken)
参数 描述
xSemaphore 要获取的信号量句柄。
pxHigherPriorityTaskWoken 标记退出此函数以后是否进行任务切换,这个变量的值由这三个函数来设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为pdTRUE的时候在退出中断服务函数之前一定要进行一次任务切换。
返回值 pdPASS:获取信号量成功。pdFALSE:获取信号量失败。

FreeRTOS二值信号量就讲解到这里啦!!!下一讲计数信号量。

FreeRTOS信号量详解第二讲(全网最全)——二值信号量相关推荐

  1. C#:Krypton控件使用方法详解(第二讲) ——kryptonCheckBox

    今天介绍的Krypton控件中的kryptonCheckBox,这个控件和VS中带的CheckBox控件还是不一样的,下面介绍这个控件. kryptonCheckBox控件的外观属性如下图所示: Ch ...

  2. FreeRTOS信号量详解第四讲(全网最全)——互斥信号量

    一.互斥信号量简介 互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中(任务与任务或中断与任务之间的同步)二值信号量最适合.互斥信号量适合用于那些需要互斥访问的应用中.在互斥访问中互斥信 ...

  3. FreeRTOS信号量详解第三讲(全网最全)——计数信号量

    一.计数型信号量简介 有些资料中也将计数型信号量叫做数值信号量,二值信号量相当于长度为1的队列,那么计数型信号量就是长度大于1的队列.**同二值信号量一样,用户不需要关心队列中存储了什么数据,只需要关 ...

  4. IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm(转载)

    IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm 自从本系列发布之后,收到了很多的朋友的回复!非常感谢,同时很多朋友问到了一些问题,有些问 ...

  5. PD3.1详解 第二章(EPR)

    PD3.1详解 第二章(EPR) 第一章节简单的介绍了如何进入EPR模式,这里主要逐步说明具体的细节: 一. 如果需要进入EPR 那么所用的线必须要满要求,我们知道PD3.0中我们必须要有emark线 ...

  6. css中float详解,CSS浮动属性Float详解?史上最全Float详解

    我们在学习css样式的时候,都知道css是盒概念,并且每一个盒子都是一个元素,下面我们就对CSS浮动属性Float进行详解,让你彻底了解Float. 一:什么是Float浮动? Float浮动是css ...

  7. FreeRTOS信号量---二值信号量

    信号量可以用来进行资源管理和任务同步,FreeRTOS中信号量又分为二值信号量.计算型信号量.互斥信号量和递归互斥信号量. 0x01 二值信号量 二值信号量其实就是一个只有一个队列项的队列,这个特殊的 ...

  8. 米家app扫描不到石头机器人_2000元档新擂主?详解石头扫地机器人 P5战力值

    原标题:2000元档新擂主?详解石头扫地机器人 P5战力值 透过这个令人不堪回首的长假,方了解自己的懒惰底线在哪,晨起的生物钟被调到了自然醒,每天饿到下午吃挂面--望着地板上日益渐厚的灰尘,悄然打起了 ...

  9. 35 freertos任务通知-代替二值信号量

    三十五. freertos任务通知-代替二值信号量 /** ********************************************************************** ...

最新文章

  1. ASP.NET 2.0 绑定高级技巧
  2. AI大事件 | OpenAI员工离职创立机器人新公司,spaCy v2.0.0发布
  3. [转]C#开发高性能Log Help类设计开发
  4. mysql or会用到索引吗_mysql or条件可以使用索引而避免全表
  5. CentOS 6.5系统安装配置LAMP(Apache+PHP5+MySQL)服务器环境
  6. Codeforces Round #476 (Div. 2) C - Greedy Arkady
  7. c语言中memset_C中的memset()
  8. hsql导入mysql_在测试过程中使用HSQL数据库
  9. 9种常见的HR数据分析方法
  10. isilon SMB 控制允许IP访问
  11. TB交易开拓者入门教程
  12. 阿伯丁大学计算机科学硕士申请,又双叒有更多硕士专业可以一月入学了 | 阿伯丁大学2021年春季入学专业名单更新(2020年8月更新)...
  13. 分布式路由策略(Hash取余,一致性Hash,Hash槽)
  14. EXCEL-VBA:EXCEL的各种文件名获取
  15. 关于产品研发管理-《培思的力量》
  16. [11]JDK9新特性
  17. 深度学习入门笔记(十一):权重初始化
  18. linux trash命令,Linux/Ubuntu: 使用 trash-cli 防止 rm 命令误删除重要文件
  19. echarts——实现3D地图+3D柱状图 效果——粗糙代码记录——技能提升
  20. 无法正常启动程序0xc0000142是什么意思?无法正常启动程序0xc0000142该如何解决?

热门文章

  1. OSChina 周三乱弹 ——程序员、魔法师和麻瓜
  2. 中移动的这三波操作,让分布式存储一下子就亮了
  3. 7-2 微博昵称的冒泡排序
  4. bootstrap-table中使用bootstrap-switch开关按钮
  5. MTK Android操作系统11种传感器介绍
  6. Android Studio 期末大作业(英语app)[免费开源]
  7. STM32F1固件库启动文件的选择
  8. 问题记录:multiple definition of `xxxx` 问题解决 struct定义类的error:“unknown type name“
  9. 最新2022【iOS开发面试真题】初级,中级,高级
  10. macos 修改mysqlworkbench快捷键