FreeRTOS(二值信号量)

资料来源于硬件家园:资料汇总 - FreeRTOS实时操作系统课程(多任务管理)

目录

一、信号量的概念

1、信号量的基本概念

2、信号量的分类

二、二值信号量的定义与应用

1、二值信号量的定义

2、二值信号量的应用

三、二值信号量的运作机制

1、FreeRTOS任务间二值信号量的实现

2、FreeRTOS中断方式二值信号量的实现

四、二值信号量的常用API函数

1、使用二值信号量典型流程与API

2、二值信号量创建与删除

3、任务与中断中二值信号量释放

五、二值信号量编程

 1、信号量创建

2、避免串口误同步

3、任务释放信号量

 4、任务获取信号量

5、中断释放信号量

6、任务中获取中断释放的信号量


一、信号量的概念

1、信号量的基本概念

消息队列是实现任务与任务或任务与中断间通信的数据结构,可类比裸机编程中的数组

信号量是实现任务与任务或任务与中断间通信的机制,可以类比裸机编程中的标志位

信号量(semaphore)可以实现任务与任务或任务与中断间的同步功能(二值信号量)资源管理(计数信号量)临界资源的互斥访问(互斥信号量)

信号量是一个非负正数,二值信号量与互斥信号量取值范围为0-1计数信号量取值范围是0-N(N>1)

0:信号量为空,所有试图获取它的任务都将处于阻塞状态,直到超时退出或其他任务释放信号量

正数:表示有一个或多个信号量供获取

2、信号量的分类

二值信号量(同步应用)

计数信号量(资源管理)

互斥信号量(互斥访问)

递归互斥信号量(简要了解即可)

二、二值信号量的定义与应用

1、二值信号量的定义

当信号量被获取了,信号量值变为0;当信号量被释放了,信号量值变为1。 把这种取值只有0与1两种状态的信号量称之为二值信号量。创建二值信号量时,系统会为创建的二值信号量分配内存

二值信号量是一种长度为1,消息大小为0的特殊消息队列。  因为这个队列只有空或满两种状态,而且消息大小为0,因此在运用时,只需要知道队列中是否有消息即可,而无需关注消息是什么。

2、二值信号量的应用

在嵌入式操作系统中,二值信号量是任务与任务或任务与中断间同步的重要手段。二值信号量也可以用于临界资源的访问,但不建议,因为存在任务优先级翻转问题.

任务与任务中同步的应用场景:

假设有一个温湿度传感器,每1s采集一次数据,那么让它在液晶屏中显示数据,这个周期也是1s,如果液晶屏刷新的周期是100ms,那么此时的温湿度数据还没更新,液晶屏根本无须刷新,只需要在1s后温湿度数据更新时刷新即可,否则CPU就是白白做了多次的无效数据更新操作,造成 CPU 资源浪费。如果液晶屏刷新的周期是 10s,那么温湿度的数据都变化了10次,液晶屏才来更新数据,那么这个产品测得的结果就是不准确的,所以还是需要同步协调工作,在温湿度采集完毕之后进行液晶屏数据的刷新,这样得到的结果才是最准确的,并且不会浪费 CPU 的资源。

任务与中断中同步的应用场景:

在串口接收中,我们不知道什么时候有数据发送过来,但如果设置一个任务专门时刻查询是否有数据到来,将会浪费CPU资源,所以在这种情况下使用二值信号量是很好的办法:当没有数据到来时,任务进入阻塞态,不参与任务的调度;等到数据到来了,释放一个二值信号量,任务就立即从阻塞态中解除,进入就绪态,然后在运行时处理数据,这样系统的资源就会得到很好的利用。

三、二值信号量的运作机制

1、FreeRTOS任务间二值信号量的实现

任务间二值信号量的实现是指各个任务之间使用信号量实现任务的同步功能。

运行条件:

创建 2 个任务 Task1 和 Task2。 

创建二值信号量默认的初始值是 0,也就是没有可用资源。

运行过程描述如下:

任务 Task1 运行过程中调用函数 xSemaphoreTake 获取信号量资源,但是由于创建二值信号的初始值是 0,没有信号量可以用,任务 Task1 将由运行态转到阻塞状态。运行的过程中,任务 Task2 通过函数 xSemaphoreGive 释放信号量,任务 Task1 由阻塞态进入到就绪态,在调度器的作用下由就绪态又进入到运行态,实现Task1与Task2的同步功能。

2、FreeRTOS中断方式二值信号量的实现

运行条件:

创建 1 个任务 Task1 和一个串口接收中断。 

二值信号量的初始值为 0,串口中断调用函数 xSemaphoreGiveFromISR 释放信号量,任务 Task1调用函数 xSemaphoreTake 获取信号量资源。

运行过程描述如下:

任务 Task1 运行过程中调用函数 xSemaphoreTake,由于信号量的初始值是 0,没有信号量资源可用,任务 Task1 由运行态进入到阻塞态。

Task1 阻塞的情况下,串口接收到数据进入到了串口中断服务程序,在串口中断服务程序中调用函数xSemaphoreGiveFromISR 释放信号量资源,信号量数值加 1,此时信号量计数值为 1,任务 Task1由阻塞态进入到就绪态,在调度器的作用下由就绪态又进入到运行态,任务 Task1 获得信号量后,信号量数值减 1,此时信号量计数值又变成了 0。 

再次循环执行时,任务 Task1 调用函数 xSemaphoreTake 由于没有资源可用再次进入到挂起态,等待串口释放二值信号量资源,如此往复循环。

实际应用中,中断方式的消息机制要注意以下四个问题:

 中断函数的执行时间越短越好,防止其它低于这个中断优先级的异常不能得到及时响应

 实际应用中,建议不要在中断中实现消息处理,用户可以在中断服务程序里面发送消息通知任务,在任务中实现消息处理,这样可以有效地保证中断服务程序的实时响应。同时此任务也需要设置为高优先级,以便退出中断函数后任务可以得到及时执行

 中断服务程序中一定要调用专用于二值信号量设置函数,即以 FromISR 结尾的函数

 如果 FreeRTOS 工程的中断函数中调用了 FreeRTOS 的二值信号量的 API 函数,退出的时候要检测是否有高优先级任务就绪,如果有就绪的,需要在退出中断后进行任务切换

四、二值信号量的常用API函数

1、使用二值信号量典型流程与API

> 创建二值信号量   xSemaphoreCreateBinary()

> 释放二值信号量    xSemaphoreGive() 与 xSemaphoreGiveFromISR() 

> 获取二值信号量    xSemaphoreTake()

> 删除二值信号量    vSemaphoreDelete()

2、二值信号量创建与删除

二值信号量控制块(句柄):二值信号量的句柄为消息队列的句柄,因为二值信号量是一种长度为1,消息大小为0的特殊消息队列

二值信号量创建

函数原型:SemaphoreHandle_t xSemaphoreCreateBinary(void)

函数描述:函数 xSemaphoreCreateBinary 用于创建二值信号量。 

 返回值,如果创建成功会返回二值信号量的句柄,如果由于 FreeRTOSConfig.h 文件中 heap 大小不足,无法为此二值信号量提供所需的空间会返回 NULL。

此函数基于消息队列函数实现:

图片

 应用举例

图片

 二值信号量删除

函数原型:void vSemaphoreDelete(void)

函数描述:函数 vSemaphoreDelete可用于删除二值信号量。 

3、任务与中断中二值信号量释放

任务中二值信号量释放

函数原型:xSemaphoreGive( SemaphoreHandle_t xSemaphore ); /* 信号量句柄 */

函数描述:函数 xSemaphoreGive 用于在任务代码中释放信号量。

 第 1 个参数是信号量句柄。

 返回值,如果信号量释放成功返回 pdTRUE,否则返回 pdFALSE,因为信号量的实现是基于消息队列,返回失败的主要原因是消息队列已经满了。

使用这个函数要注意以下问题:

1. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是xSemaphoreGiveFromISR。

2. 使用此函数前,一定要保证用函数 xSemaphoreCreateBinary(), xSemaphoreCreateMutex() 或者xSemaphoreCreateCounting()创建了信号量。

3. 此函数不支持使用 xSemaphoreCreateRecursiveMutex()创建的信号量。

中断中二值信号量释放

函数原型:xSemaphoreGiveFromISR ( SemaphoreHandle_t xSemaphore, /* 信号量句柄 */

    signed BaseType_t *pxHigherPriorityTaskWoken /* 高优先级任务是否被唤醒的状态保存 */ )

函数描述:函数 xSemaphoreGiveFromISR 用于中断服务程序中释放信号量。

 第 1 个参数是信号量句柄。

 第 2 个参数用于保存是否有高优先级任务准备就绪。如果函数执行完毕后,此参数的数值是 pdTRUE,说明有高优先级任务要执行,否则没有。

 返回值,如果信号量释放成功返回 pdTRUE,否则返回 errQUEUE_FULL。

使用这个函数要注意以下问题:

1. 此函数是基于消息队列函数 xQueueGiveFromISR 实现的:#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) \xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )

2. 此函数是用于中断服务程序中调用的,故不可以任务代码中调用此函数,任务代码中中使用的是xSemaphoreGive。

3. 使用此函数前,一定要保证用函数 xSemaphoreCreateBinary()或者 xSemaphoreCreateCounting()创建了信号量。

4. 此函数不支持使用 xSemaphoreCreateMutex ()创建的信号量。

五、二值信号量编程

 1、信号量创建

2、避免串口误同步

STM32Cube生成的FreeRTos代码创建二值信号量时,默认为1,此处释放避免串口误同步

  xSemaphoreTake(myBinarySem01Handle,0);//STM32CubeMX生成的FreeRTos代码创建二值信号量时,默认为1,此处释放,避免串口误同步xSemaphoreTake(myBinarySemISRHandle,0);//STM32CubeMX生成的FreeRTos代码创建二值信号量时,默认为1,此处释放,避免串口误同步

3、任务释放信号量

void ReleaseSem_Task(void const * argument)
{/* USER CODE BEGIN ReleaseSem_Task */BaseType_t xResult;uint16_t GiveCnt=0;   //释放计数char buff[50];/* Infinite loop */for(;;){HAL_UART_Transmit(&huart2, (uint8_t *)"发送同步信号!!! \r\n",18, HAL_MAX_DELAY);xResult=xSemaphoreGive(myBinarySem01Handle);if(xResult==pdTRUE){sprintf(buff,"成功发送二值信号量同步信号,次数 = %u \r\n",++GiveCnt);HAL_UART_Transmit(&huart2, (uint8_t *)buff, strlen(buff), HAL_MAX_DELAY);}else{HAL_UART_Transmit(&huart2, (uint8_t *)"发送同步信号失败 \r\n\r\n", 17, HAL_MAX_DELAY);}osDelay(1000);}/* USER CODE END ReleaseSem_Task */
}

 4、任务获取信号量

void BinarySem_Syn_Task(void const * argument)
{/* USER CODE BEGIN BinarySem_Syn_Task */BaseType_t xResult;uint16_t TakeCnt=0;   //获取计数char buff[50];/* Infinite loop */for(;;){HAL_UART_Transmit(&huart2,(uint8_t *)"等待同步信号,无限等待 \r\n", 25, HAL_MAX_DELAY);xResult=xSemaphoreTake(myBinarySem01Handle,portMAX_DELAY);if(xResult==pdTRUE){sprintf(buff,"成功接收到二值信号量同步信号,次数 = %u \r\n\r\n",++TakeCnt);HAL_UART_Transmit(&huart2, (uint8_t *)buff, strlen(buff), HAL_MAX_DELAY);}}/* USER CODE END BinarySem_Syn_Task */
}

5、中断释放信号量

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{BaseType_t xHigherPriorityTaskWoken =pdTRUE;if(huart->Instance==huart2.Instance){xSemaphoreGiveFromISR(myBinarySemISRHandle,&xHigherPriorityTaskWoken);//如果有高优先级任务就绪,执行一次任务切换portYIELD_FROM_ISR(xHigherPriorityTaskWoken);}
}

6、任务中获取中断释放的信号量

void BinarySemSyneISR_Task(void const * argument)
{/* USER CODE BEGIN BinarySemSyneISR_Task */BaseType_t xResult;uint16_t TakeCnt=0;   //获取计数char buff[50];char rxBuff[10];/* Infinite loop */for (;;){HAL_UART_Receive_IT(&huart2, (uint8_t*) rxBuff, strlen(rxBuff));HAL_UART_Transmit(&huart2, (uint8_t*) "等待串口中断同步信号,无限等待 \r\n", 21,HAL_MAX_DELAY);xResult = xSemaphoreTake(myBinarySemISRHandle, portMAX_DELAY);if (xResult == pdTRUE){sprintf(buff, "成功接收到二值信号量同步信号,次数 = %u \r\n\r\n", ++TakeCnt);HAL_UART_Transmit(&huart2, (uint8_t*) buff, strlen(buff),HAL_MAX_DELAY);sprintf(buff, "成功接收到串口数据: %s \r\n\r\n", rxBuff);HAL_UART_Transmit(&huart2, (uint8_t*) buff, strlen(buff),HAL_MAX_DELAY);}}/* USER CODE END BinarySemSyneISR_Task */
}

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

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

相关文章

Spring Web

◆ Spring整合web环境 - Javaweb三大组件及环境特点 - Spring整合web环境的思路及实现 把ApplicationContext放在ServleContent域【listen组件中】中 ContextLoaderListener :部分代码写死了 /*** 配置通用的Spring容器的创建,只需要创建一次就可以*/…

SQL server 与 MySQL count函数、以及sum、avg 是否包含 为null的值

sql server 与 mysql count 作用一样。 count 计算指定字段出现的个数, 不是计算 null的值 获取表的条数 count(n) n:常数 count(1),count(0)等 count(*) count(字段) 其中字段为null 不会统计在内。 avg(字段)、sum(字段) 跟count(字段)…

科技资讯|苹果手机版Vision Pro头显专利曝光,内嵌苹果手机使用

根据美国商标和专利局(USPTO)公示的清单,苹果公司近日获得了一项头显相关的技术专利,展示了一款亲民款 Vision Pro 头显,可以将 iPhone 放置在头显内部充当屏幕。 根据patentlyapple 媒体报道,这是苹果公司…

案例12 Spring MVC入门案例

网页输入http://localhost:8080/hello&#xff0c;浏览器展示“Hello Spring MVC”。 1. 创建项目 选择Maven快速构建web项目&#xff0c;项目名称为case12-springmvc01。 2.配置Maven依赖 <?xml version"1.0" encoding"UTF-8"?><project xm…

【计算机网络】TCP协议超详细讲解

文章目录 1. TCP简介2. TCP和UDP的区别3. TCP的报文格式4. 确认应答机制5. 超时重传6. 三次握手7. 为什么两次握手不行?8. 四次挥手9. 滑动窗口10. 流量控制11. 拥塞控制12. 延时应答13. 捎带应答14. 面向字节流15. TCP的连接异常处理 1. TCP简介 TCP协议广泛应用于可靠性要求…

IP 协议的相关特性和数据链路层相关知识总结

目录 IP 协议的相关特性 一、IP协议的特性 二、 IP协议数据报格式 三、 IP协议的主要功能 1. 地址管理 动态分配 IP地址 NAT机制 NAT背景下的通信 IPV6 2. 路由控制​​​​​​​ 3.IP报文的分片与重组 数据链路层相关知识 1、以太网协议&#xff08;Ethernet&#xff09; 2.M…

OpenCV实例(八)车牌字符识别技术(一)模式识别

车牌字符识别技术&#xff08;一&#xff09;模式识别 1.模式识别流程2. 模式识别方式 影响并导致汽车牌照内字符出现缺损、污染、模糊等情况的常见因素有照相机的性能、采集车辆图像时光照的差异、汽车牌照的清洁度等。为了提高汽车牌照字符识别的准确率&#xff0c;本节将把英…

【C语言】自定义实现strlen函数的3种方法

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C语言中自定义实现strlen函数的3种方法&#xff0c;如果大家觉得我写的不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 在自定义实现strlen函数之前&#xff0c;我们简单的介绍一下strlen函…

“冰箭卫士·IP发布会”首次亮相第14届海峡两岸(厦门)文博会

2023年8月6日,“冰箭卫士IP发布会”首次亮相海峡两岸文博会思明馆。此次发布会由厦门市文化创意产业协会、厦门理工&#xff08;集美区&#xff09;政产学研基地主办&#xff0c;厦门市文化创意产业协会IP设计研究院、厦门一笔之上文化发展有限公司、冰箭应急安全科技研究院承办…

T113-S3-调试debug串口修改

目录 前言 一、原理图示意 二、设备树文件配置 三、系统配置文件修改 四、调试问题 总结 前言 在嵌入式系统开发过程中&#xff0c;Debug串口是一个不可或缺的工具&#xff0c;用于输出调试信息、观察系统运行状态以及进行错误排查。T113-S3开发板作为一款功能强大的嵌入式…

20230811导出Redmi Note12Pro 5G手机的录音机APP的录音

20230811导出Redmi Note12Pro 5G手机的录音机APP的录音 2023/8/11 10:54 redmi note12 pro 录音文件 位置 貌似必须导出录音&#xff0c;录音的源文件不知道存储到哪里了&#xff01; 参考资料&#xff1a; https://jingyan.baidu.com/article/b87fe19e9aa79b1319356842.html 红…

Ubuntu18.04搭配无人机仿真环境(ROS,PX4,gazebo,Mavros,QGC安装教程)

Ubuntu18.04搭配无人机仿真环境 ROS环境配置版本安装 gazebo安装Mavrosa安装PX4源码下载和编译运行仿真地面站安装 ROS环境配置 我个人使用了代理环境进行下载。Linux没有代理的可以使用国内源。 清华大学源 sudo sh -c ‘. /etc/lsb-release && echo “deb http://m…

简单入门seleniumUI自动化测试

目录 一、selenium的介绍 二、selenium的原理 三、selenium的八种元素定位的方法 1、ID定位&#xff1a; 2 、name定位&#xff1a; 3、class定位&#xff1a; 4、tag定位&#xff1a; 5、link_text定位&#xff1a; 6、partial_link_text定位&#xff1a; 7、css定位…

vue table动态合并, 自定义合并,参照合并,组合合并

<template><div><el-table:data"tableData":span-method"objectSpanMethod"border:header-cell-style"{ textAlign: center }"><el-table-column prop"area" label"区域" align"center">…

【uniapp】一文读懂app端安装包升级

一、前言 首先&#xff0c;在app端开发上线的过程中&#xff0c;会面临一个问题&#xff0c;就是关于app端的版本升级的问题。如果不做相关处理来引导用户的话&#xff0c;那么app就会出现版本没有更新出现的各种问题&#xff0c;我们常见的有在线升级和去指定地址下载安装两种…

【CSS】CSS 布局——弹性盒子

Flexbox 是一种强大的布局系统&#xff0c;旨在更轻松地使用 CSS 创建复杂的布局。 它特别适用于构建响应式设计和在容器内分配空间&#xff0c;即使项目的大小是未知的或动态的。Flexbox 通常用于将元素排列成一行或一列&#xff0c;并提供一组属性来控制 flex 容器内的项目行…

LabVIEW开发图像采集和基于颜色的隔离

LabVIEW开发图像采集和基于颜色的隔离 在当今的工业和工厂中&#xff0c;准确性和精度是决定特定行业生产力的两个重要关键点。为了优化生产力&#xff0c;各行各业正在从手动操作转向自动操作和控制。机器人技术在工业过程中的出现为人类提供了机械辅助。机器视觉在工业机器人…

Java GUI,mybatis实现资产管理系统

Java GUI——资产管理系统 前言&#xff1a;为了做java课设&#xff0c;学了一手Java GUI。感觉蛮有意思的&#xff0c;写写文章&#xff0c;做个视频记录一下。欢迎大家友善指出我的不足 资产管理系统录制视频&#xff0c;从头敲到尾 模块划分 资产信息管理 资产信息查询 …

Vue实现详细界面里面有一个列表

目录 Vue实现详细界面里面有一个列表 理一下思路&#xff1a; 效果如下&#xff1a; 1、 主页面正常写 2、详细界面(重点) 3、详细界面里面的列表(重点) 要点&#xff1a; Vue实现详细界面里面有一个列表 理一下思路&#xff1a; 1、首先需要这条数据的主键id&#xff…

CAD练习——绘制电风扇

注意要在三维空间内完成绘制 先绘制扇叶 两条射线确定角度 绘制圆弧&#xff08;圆修剪&#xff09; 绘制扇叶形状&#xff08;3点圆弧&#xff09; 圆角&#xff1a; 将这几段圆弧合成同一条多段线 换个立体视图 拉伸出厚度 绘制一个球 取二者交集&#xff08;带弧面的扇叶&a…