FreeRTOS学习(十) 信号量

2023-05-16

声明及感谢: 跟随正点原子资料学习, 在此作为学习的记录和总结
环境 keil , stm32f103

二值信号量:

二值信号量 通常用于互斥访问,或同步, 大多数用于同步(任务与任务 或 任务 与中断的同步).
和队列一样,信号量API函数允许设置一个阻塞时间, 阻塞时间是当任务获取信号量时, 由于信号量无效从而导致
任务进入阻塞态的最大时钟节拍数. 如果多个任务同时阻塞在同一个信号量上的话,那么优先级最高的那个任务会有限获得信号量. 这样当信号量有效的时候高优先级的任务会解除阻塞状态.

1. 创建二值信号量

SemaphoreHandle_t BinarySemaphore;	// 二值信号量句柄
BinarySemaphore = xSemaphoreCreateBinary();	 // 创建二值信号量
	
	if(BinarySemaphore!=NULL)
	{
		xSemaphoreGive(BinarySemaphore);  // 二值信号量创建成功以后要先释放一下
	}	

注意 创建成功之后需要先释放一下.
信号量的创建 由xSemaphoreCreateBinary() 函数进行创建
此函数无参数
返回值 NULL 为创建失败
其他值 : 创建成功的 二值信号量的句柄.

2. 获取信号量
分两种
第一种 : 在任务中获取信号量
函数原型

xSemaphoreTake( xSemaphore, xBlockTime )

参数 xSemaphore 信号量句柄
xBlockTime 阻塞时间

返回值 pdTRUE 获取信号量成功
pdFALSE 获取信号量失败

第二种 在中断中获取信号量

函数原型

xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken )

参数 xSemaphore 信号量句柄
pxHigherPriorityTaskWoken 标记退出此函数以后是否进行任务切换, 当此值为pdTRUE的时候在退出中断服务函数之前一定要进行一次任务切换.

返回值 pdTRUE 获取信号量成功
pdFALSE 获取信号量失败

注意: 进行任务切换 即 调用 portYIELD_FROM_ISR(pxHigherPriorityTaskWoken ); 参数传 发送消息的第三个参数进去, 即可.

3. 释放信号量

释放信号量分两种
第一种 任务中释放信号量
函数原型

xSemaphoreGive( xSemaphore )

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

返回值 pdPASS 释放信号量成功
errQUEUE_FULL 释放信号量失败

第二种 中断中释放信号量
函数原型

xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken )	

参数 xSemaphore 信号量句柄
pxHigherPriorityTaskWoken 标记退出此函数以后是否进行任务切换, 当此值为pdTRUE的时候在退出中断服务函数之前一定要进行一次任务切换.

返回值 pdPASS 释放信号量成功
errQUEUE_FULL 释放信号量失败

注意: 进行任务切换 即 调用 portYIELD_FROM_ISR(pxHigherPriorityTaskWoken ); 参数传 发送消息的第三个参数进去, 即可.

示例:

SemaphoreHandle_t BinarySemaphore;	// 二值信号量句柄
BinarySemaphore = xSemaphoreCreateBinary();	 // 创建二值信号量 

void DataProcess_task(void *pvParameters)   // 在任务函数中
{
  BaseType_t err = pdFALSE;
   /*** 此处省略部分代码***/
    while(1)
    {
          if(BinarySemaphore!=NULL)
          {
            	err = xSemaphoreTake(BinarySemaphore,portMAX_DELAY);	// 获取信号量
            	if(err==pdTRUE)		// 获取信号量成功, 
			  {
			      // 处理事情.代码省略
			  }
          }
          else if(err==pdFALSE)
		{
			vTaskDelay(10);      // 相对延时 10个时钟节拍
		}
    }
}


在中断服务函数中

void USART1_IRQHandler(void) 
{
	省略部分代码
	BaseType_t xHigherPriorityTaskWoken;
	if(// 满足释放信号量条件)
	{
	    	xSemaphoreGiveFromISR(BinarySemaphore,&xHigherPriorityTaskWoken);	// 释放二值信号量
	    	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);// 注意 要检测是否需要进行任务切换
	}
	
}

上面示例就演示了, 使用二值信号量任务和中断的同步

计数型信号量

对于信号量来说, 长度为1的叫二值信号量,那么信号量长度大于1的队列就叫计数型信号量. 同二值信号量一样, 用户不需要关心队列中存储了什么数据, 只需关心 队列是否为空,
计数型信号量通常用于如下两个场合
1, 事件计数
2, 资源管理

1. 创建计数型信号量

SemaphoreHandle_t CountSemaphore;  // 计数型信号量句柄
CountSemaphore = xSemaphoreCreateCounting(255,0);	  // 创建计数型信号量

xSemaphoreCreateCounting( uxMaxCount, uxInitialCount )
参数 uxMaxCount: 计数信号量最大计数值, 当信号量等于此值的时候释放信号量就会失败.
uxInitialCount 计数信号量初始值

返回值 : NULL: 计数型信号量创建失败
其他值: 计数型信号量创建成功, 返回计数型信号量句柄.

2.释放计数值信号量
和释放二值信号量一样.

3. 获取计数值信号量
和获取二值信号量一样.

互斥信号量

为什么需要使用互斥信号量.

答: 有一个概念叫优先级翻转. 当一个低优先级任务和一个高优先级任务同时使用同一个信号量,而系统中还有其他中等优先级任务时, 如果低优先级任务获得了信号量, 那么高优先级的任务就会处于等待状态, 但是中等优先级的任务可以打断低优先级任务而先于高优先级任务运行(此时高优先级的任务在等待信号量, 所以不能运行,)这就是出现了优先级翻转的现象. 一旦出现优先级翻转, 那么后果很严重

想要解决优先级反转问题, 需要引入互斥信号量:

互斥信号量其实就是一个拥有优先级继承的二值信号量。
互斥信号量使用的函数和二值信号量的API函数相同, 当一个互斥信号量正在被一个低优先级的任务使用,而此时有高优先级的任务也尝试获取这个互斥信号量的话就会被阻塞。 不过这高优先级的任务会将低优先级的任务的优先级提升到与自己相同的优先级,这个过程就是优先级继承。
所以优先级集成并不能完全的消除优先级翻转,它只是尽可能的降低优先级翻转带来的影响。所以在设计之初就要避免优先级翻转的发生, 互斥信号量不能用户中断服务函数中,
原因如下:
(1) 互斥信号量有优先级继承的机制, 所以只能用在任务中, 不能被用于中断服务函数。
(2) 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态

1. 创建互斥信号量

SemaphoreHandle_t MutexSemaphore;	// 互斥信号量
MutexSemaphore=xSemaphoreCreateMutex();  // 创建互斥信号量

xSemaphoreCreateMutex()
参数 : 无
返回值: NULL 互斥信号量创建失败。
其它值, 创建互斥信号量的句柄。

2.获取和释放互斥信号量
xSemaphoreTake() // 获取信号量
xSemaphoreGive() // 释放信号量。

这两个函数和二值信号量时调用是一样的,所以就简单叙述。

递归互斥信号量

 递归互斥信号量可以看做是一个特殊的互斥信号量, 普通的互斥信号量是已经获取了互斥信号量的任务就不能在此获取这个互斥信号量, 但是递归互斥信号量不同, 已经获取了递归互斥信号量的任务可以在此获取这个递归互斥信号量,而且次数不限!, 一个任务使用函数 xSemaphoreTakeRecursive()成功获取了多少次递归互斥信号量就得使用函数xSemaphoreGiveRecursive() 释放多少次!, 比如某个任务成功的获取了5次递归信号量, 那么这个任务也得同样释放5次递归信号量。 
 	递归互斥信号量也有优先级集成的机制, 所以当任务使用完递归互斥信号量后一定要释放, 同互斥信号量一样,递归互斥信号量不能用在中断服务函数中,
 	由于优先级继承的存在,就限定了递归互斥信号量只能用在任务中, 不能再中断服务函数中,
 	中断服务函数不能设置阻塞时间。
 	要使用递归互斥信号量的话 需要设置 configUSE_RECURSIVE_MUTEXES 必须为1


xSemaphoreCreateRecursiveMutex()  // 创建递归互斥信号量
xSemaphoreTakeRecursive()  // 获取递归互斥信号量
xSemaphoreGiveRecursive() // 释放递归互斥信号量
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS学习(十) 信号量 的相关文章

  • 详解FreeRTOS中的软件定时器

    软件定时器用于让某个任务定时执行 或者周期性执行 比如设定某个时间后执行某个函数 或者每隔一段时间执行某个函数 由软件定时器执行的函数称为软件定时器的回调函数 参考资料 Mastering the FreeRTOS Real Time Ke
  • 【FreeRtos学习笔记】STM32 CubeMx——Timers(定时器)

    目录 1 软件定时器 2 示例程序 2 1 例程功能 2 2 步骤 2 3 实验结果 2 4 函数讲解 1 软件定时器 定时器是MCU常用的外设 我们在学习各种单片机时必然会学习它的硬件定时器 但是 MCU自带的硬件定时器资源是有限的 而且
  • FreeRTOS记录(七、FreeRTOS信号量、事件标志组、邮箱和消息队列、任务通知的关系)

    我们在前面单独介绍过FreeRTOS的任务通知和消息队列 但是在FreeRTOS中任务间的通讯还有信号量 邮箱 事件组标志等可以使用 这篇文章就这些成员与消息队列和任务通知的关系进行说明分析 增加邮箱部分 任务通知发送消息 Demo 202
  • FreeRTOS-内核控制函数

    FreeRTOS 内核控制函数 FreeRTOS中有一些内核函数 一般来说这些内核函数在应用层不会使用 但是内核控制函数是理解FreeRTOS中断的基础 接下来我们逐一分析这些内核函数 taskYIELD 该函数的作用是进行任务切换 这是一
  • FreeRTOS系列

    1 RTOS简介 RTOS全称为 Real Time Operation System 即实时操作系统 RTOS强调的是实时性 又分为硬实时和软实时 硬实时要求在规定的时间内必须完成操作 不允许超时 而软实时里对处理过程超时的要求则没有很严
  • STM32移植FreeRTOS的Tips

    转自 http bbs armfly com read php tid 7140 1 在FreeRTOS的demo文件夹中拷贝对应的FreeRTOSConfig h文件后 需要加入一行 define configUSE MUTEXES 1
  • ZYNQ中FreeRTOS中使用定时器

    使用普通的Timer中断方式时 Timer中断可以正常运行 但是UDP通信进程无法启动 其中TimerIntrHandler是中断服务程序 打印程序运行时间与从BRAM中读取的数据 void SetupInterruptSystem XSc
  • FreeRTOS打印任务对CPU的占有率

    1 配置RTOS 1 打开RTOS Config Parameter 找到Run Time And Task States gathering related definitions 使能GENERATE RUN TIME STATS US
  • freeRTOS使用uxTaskGetStackHighWaterMark函数查看任务堆栈空间的使用情况

    摘要 每个任务都有自己的堆栈 堆栈的总大小在创建任务的时候就确定了 此函数用于检查任务从创建好到现在的历史剩余最小值 这个值越小说明任务堆栈溢出的可能性就越大 FreeRTOS 把这个历史剩余最小值叫做 高水位线 此函数相对来说会多耗费一点
  • 基于HAL库的FREERTOS-----------三.队列

    一 队列简介 在实际的应用中 常常会遇到一个任务或者中断服务需要和另外一个任务进行 沟通交流 这个 沟通交流 的过程其实就是消息传递的过程 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式 但是如果在使用操作系统的应用中用
  • freertos————互斥锁

    线程安全 多线程程序处于一个多变的环境 可访问的全局变量和堆数据随时可能被其他的线程改变 多个线程同时访问一个共享数据 可能造成严重的后果 出现问题的是之前移植了一个freemodbus的从站 多个任务访问全局变量保持寄存器区 导致最后读出
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • stm32f103zet6移植标准库的sdio驱动

    sdio移植 st官网给的标准库有给一个用于st出的评估板的sdio外设实现 但一是文件结构有点复杂 二是相比于国内正点原子和野火的板子也有点不同 因此还是需要移植下才能使用 当然也可以直接使用正点原子或野火提供的实例 但为了熟悉下sdio
  • 基于STM32的FreeRTOS学习之中断测试实验(五)

    记录一下 方便以后翻阅 本章内容是接着上一章节进行的实际演练 1 实验目的 FreeRTOS可以屏蔽优先级低于configMAX SYSCALL INTERRUPT PRIORITY的中断 不会屏蔽高于其的中断 本次实验就是验证这个说法 本
  • FreeRTOS笔记(十)中断

    中断 当CPU在执行某一事件A时 发生另外一个更重要紧急的事件B请求CPU去处理 产生了中断 于是CPU暂时中断当前正在执行的事件A任务而对对事件B进行处理 CPU处理完事件B后再返回之前中断的位置继续执行原来的事件A 这一过程统称为中断
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • FreeRTOS多任务调度器基础

    Cortex M4中SysTick调度器核心 Cortex M4中的中断管理 Cortex M4中影子栈指针 Cortex M4中SVC和PendSV异常 1 Cortex M4中SysTick调度器核心 systick每一次中断都会触发内
  • GNU Arm Cortex m4 上的 C++ 异常处理程序与 freertos

    2016 年 12 月更新现在还有一个关于此行为的最小示例 https community nxp com message 862676 https community nxp com message 862676 我正在使用带有 free

随机推荐

  • Ubuntu18.04安装ROS Melodic步骤及问题解决

    1 sudo sh c 39 echo 34 deb http packages ros org ros ubuntu lsb release sc main 34 gt etc apt sources list d ros latest
  • 关于使用vscode断点调试ORB_SLAM2程序时,断点无效的解决方案

    需要在CMakeLists txt 里加 set CMAKE CXX FLAGS CMAKE CXX FLAGS g 开启debug 不然断点调试是无效的 具体配置见文章https blog csdn net weixin 39754100
  • 关于ros安装过程设置密钥不成功解决方案

    问题 xff1a 设置密钥语句 xff1a curl s https raw githubusercontent com ros rosdistro master ros asc sudo apt key add 出现错误 xff1a gp
  • CmakeLists所遇命令用法总结

    1 option命令 xff1a 形式 xff1a option lt variable gt 34 lt help text gt 34 value 简介 xff1a cmake中option起到编译开关的作用 xff0c CMakeLi
  • OpenCV——图像二值化

    OpenCV图像二值化提供了两种函数 threshold double threshold InputArray src OutputArray dst double thresh double maxval int type src xf
  • ubuntu18.04运行ORBSLAM2踩坑记录

    坑1 xff1a error 39 usleep 39 was not declared in this scope usleep 3000 解决办法 xff1a 在对应报错文件中添加头文件 xff1a include lt unistd
  • 单目相机标定

    1 下载usb cam安装包 xff0c 放置到 catkin ws src目录下 cd catkin ws src git clone https github com bosch ros pkg usb cam git usb cam
  • ubuntu18.04安装google浏览器

    sudo wget http www linuxidc com files repo google chrome list P etc apt sources list d wget q O https dl google com linu
  • ubuntu18.04安装opencv3.2.0

    1 下载所需安装包 opencv 3 2 0下载地址 xff1a opencv 3 2 0 opencv contrib 3 2 0下载地址 xff1a opencv contrib 3 2 0 2 安装所需依赖 sudo apt get
  • vscode调试orbslam2配置过程

    1 c cpp properties json 34 configurations 34 34 name 34 34 Linux 34 34 includePath 34 34 workspaceFolder 34 34 usr inclu
  • 喜茶皇茶茶叶带您走上致富之路

    我国是茶文化的发源地 xff0c 尤其是南方各类品种的茶层出不穷 xff0c 茶韵茶香引人入胜 消费者生活水平大幅提高 xff0c 饮茶几乎已经成为一种时尚 xff0c 皇茶 在市场上受到大家的认可与喜爱 xff0c 短短时间内迅速发展壮大
  • UCOSII pdf 电子书籍

    https pan baidu com share init surl 61 RrZKnhvCuC 3qCOT0bi1Gg 提取码 xff1a 4a0f
  • 变频器的逆变、变频原理

    变频器的逆变 变频原理 YJZhang 从事制造业质量管理 xff0c 做过PCBA 线束 电话机 变频器行业 90 人赞同了该文章 变频器将直流电转变为交流电的这个过程叫 逆变 xff08 inverting 先讲逆变过程 xff0c 分
  • 8086中断系统——《x86汇编语言:从实模式到保护模式》读书笔记04

    80X86中断系统 能够处理256个中断 用中断向量号0 xff5e 255区别 可屏蔽中断还需要借助专用中断控制器Intel 8259A实现优先权管理 1 中断的分类 中断可以分为内部中断和外部中断 xff08 1 xff09 内部中断
  • 任务切换的方法——《x86汇编语言:从实模式到保护模式》读书笔记37

    任务切换的方法 x86汇编语言 xff1a 从实模式到保护模式 读书笔记37 1 中断门和陷阱门 在实模式下 xff0c 内存最低端的1M是中断向量表 xff0c 保存着256个中断处理过程的段地址和偏移 当中断发生时 xff0c 处理器把
  • 不用 H5,闲鱼 Flutter 如何玩转小游戏?

    阿里妹导读 xff1a 最近APP游戏化成为了一个新的风口 xff0c 把在游戏中一些好玩的 能吸引用户的娱乐方式或场景应用在应用当中 xff0c 以达到增加用户粘性 xff0c 提升DAU的效果 xff0c 成本较低 同时在一些需要对用户
  • 【Invalid bound statement (not found)的解决方法】

    前言 xff1a 先说下我自己 xff0c 最开始我是可以的 xff0c 结果我去改了下mapper接口里方法的参数类型 xff0c 突然就报Invalid bound statement not found 这个错误 xff0c 我在网上
  • FreeRTOS学习(四) 列表的插入和删除

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 首先定义列表 xff0c 以及列表项 List t TestList 列表 ListItem t ListItem1 列表项1 ListItem
  • FreeRTOS学习(六) 时间片调度

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 对于FreeRTOS 允许同等任务优先级存在 那么对于多个同等优先级的任务运行 情况的是如何 FreeRTOS 的机制就是对于同等优先级任务来说
  • FreeRTOS学习(十) 信号量

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 二值信号量 二值信号量 通常用于互斥访问 或同步 大多数用于同步 任务与任务 或 任务 与中断的同步 和队列一样 信号量API函数允许设置一个阻