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

2023-05-16

一、二值信号量简介

二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一些细微的差别,互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号另更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问。和队列一样,信号量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二值信号量就讲解到这里啦!!!下一讲计数信号量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS信号量详解第二讲(全网最全)——二值信号量 的相关文章

  • 二、pixhawk光流传感器PX4FLOW

    这东西不好用啊 在官网介绍里我们主要看到这个是关于光流扩展的一般还会有一个声呐传感器 xff0c 就是那个MaxBotix I2CXL MaxSonar EZ这里有介绍 这个超声波传感器得说一下 xff0c 它可以单独通过IIC去链接pix
  • 五、关于pixhawk的仿真,jmavsim和Gazebo

    实物飞总是很麻烦的 xff0c 一个不小心就炸鸡了 所以在仿真环境里去验证是最好的方法 xff0c 我也觉得先艹仿真再艹飞机是很正确的一种方式 先介绍一下jmavsim 官网介绍 前面说的环境搭建好了 xff0c 就可以直接make px4
  • 六、PX4的ros/mavros搭建

    老规矩 xff0c 看官网 这里 我看这个上面已经在推ROS2了 不过对于我这种只接触过ROS1版本的还是MAVROS来得清切 MAVROS说白了就是MAVLINK的进一步封装 xff0c 可以使得计算机通过串口发送指令给pixhawk x
  • ajaxSubmit

    34 form 34 ajaxSubmit xff09 介绍 http www cnblogs com qiantuwuliang archive 2009 09 14 1566604 html jQuery extend 函数详解 htt
  • git的使用

    无情的标题 首先这次正对的是码云平台上的一个小deno 第一步进入码云平台fork我们的demo 登录注册一条龙 搜索这个demo 点击fork xff0c 一般帅哥美女都会随手点一个star 然后返回自己的本地空间就可以看到啦 首先我们要
  • 逻辑分析仪使用

    首先我们打开软件 软件自行下载 xff0c 我用的是这一个软件 在测试的时候 xff0c 我们确保软件界面左上角或者是上方显示connected xff0c 不然我们看到的波形会是一个相当标准的正弦 xff08 或者余弦 xff09 波 然
  • ubuntu修改pip的官方源为豆瓣源

    ubuntu修改pip的官方源为豆瓣源 编辑配置文件 如果没有就新建一份 span class token function mkdir span pip span class token function vim span pip pip
  • SDN和SD-WAN的概念别再搞混了

    最近 xff0c SD WAN 在融资领域是一个比较热的话题 国外几家 SD WAN 的头部企业不断地取得融资 xff0c 也包括被思科 VMware等巨头收购和兼并 xff0c 国内创业公司推出了各种 SD WAN 产品和解决计划 不得不
  • SD-WAN重要功能-网络加速!

    网络加速是SDWAN的特点之一 xff0c 它可以通过数据压缩和纠错来实现网络加速 在计算机通信中 xff0c 主要有两个错误 xff1a 包丢失和错误 错误的原因是一些比特数据的畸变 xff1b 丢失的原因是一些数据包没有收到 底层协议通
  • django3.x 使用haystack 报错:ImportError: cannot import name 'six' from 'django.utils'

    django3 x 使用haystack 报错 xff1a ImportError cannot import name 39 six 39 from 39 django utils 39 原因解决办法 原因 django 3 x 系列删除
  • 机器学习sklearn之预估器(estimator)使用

    预估器 xff08 估计器 xff09 estimator 概述 因为sklearn机器学习算法的实现都属于estimator的子类 xff1a 分类算法 xff1a k 近邻 贝叶斯 逻辑回归 决策树与随机森林 回归算法 xff1a 线性
  • 复杂网络分析——networkx的使用

    1 基本图操作 导包 span class token keyword import span networkx span class token keyword as span nx span class token keyword im
  • python3+android自动化之Uiautomator2

    python3 43 android自动化之Uiautomator2 1 环境准备 xff1a android sdk xff1a 下载地址 https developer android google cn studio releases
  • 复杂网络数据集处理——无向无权最大连通子图

    复杂网络数据集处理 无向无权最大连通子图 前言一 环境Python3networkx 二 代码三 使用说明总结 前言 由于来源不同 xff0c 导致网上公开的网络数据集格式也没有统一规范 xff0c 在进行科学计算时往往由数据格式的差异导致
  • CentOS 6.0 下 VNC 配置方法(带防火墙配置)

    CentOS 6 0 下 VNC 配置方法 xff08 带防火墙配置 xff09 2012 12 03 16 30 53 编辑 删除 转载 标签 xff1a linux tigervnc配置 it 分类 xff1a linux 一 安装 V
  • linux – telnet 【host】【port】,设置超时时间

    http www cocoachina com articles 51080 这将运行不超过2秒 xff1a span class token keyword echo span quit span class token operator
  • 基于python 自己动手写一个简单的web服务器

    1 前言 如今一提到服务器首先就想到 apache tomcat nginx等 虽然这些服务器很优秀 但是对于我们平时拿来练手的一些小项目来说却是大材小用 xff0c 杀鸡用牛刀 xff0c 而且上述主流服务器配置起来也略嫌麻烦 俗话说自己
  • 基于Python的逆波兰表达式的转换与求值

    一 逆波兰表达式简介 逆波兰式 xff08 Reverse Polish notation xff0c RPN xff0c 或逆波兰记法 xff09 xff0c 也叫后缀表达式 xff08 将运算符写在操作数之后 xff09 而与之对应的是
  • Invalid bound statement (not found):出现的原因和解决方法

    解决错误的步骤 出现了什么错误可能导致的原因解决办法 出现了什么错误 错误截图 xff1a BindingException 数据绑定异常 not found 找不到 org apache ibatis binding BindingExc
  • 软件设计师笔记:软件工程

    文章目录 一 软件开发模型1 1 瀑布模型 xff08 SDLC xff09 1 2 其他经典模型 xff08 原型模型 增量模型 演化模型 xff09 1 3 螺旋模型1 4 V模型1 5 喷泉模型与RAD1 6 构件组装模型 xff08

随机推荐