FreeRTOS——信号量

server/2024/11/23 22:26:54/

目录

一、概念及其应用

1.1定义

1.2作用

二、二值信号量

2.1定义

2.2二值信号量工作机制

2.3二值信号量应用场景—同步

2.4二值信号量API

2.4.1创建二值信号量

2.4.2任务中释放信号量

2.4.3中断中释放信号量

2.4.4任务中获取信号量

2.4.5中断中获取信号量

三、计数信号量

3.1定义

3.2作用

 3.3创建计数信号量

3.4获取当前计数信号量的值

四、实现原理 

队列、信号量、互斥信号量都是为了解决任务和中断之间通讯、同步、互斥的问题

一、概念及其应用

1.1定义

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

1.2作用

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

容易混淆:

        临界段是内核的一种处理机制,不让任务或大部分中断  打断

        消息队列是实现任务与任务或任务与中断间通信的数据结构,可类比裸机编程中的数组,消息队列中的数据是重要的,而信号量中不关心数据,只关心是否为空

二、二值信号量

2.1定义

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

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

2.2二值信号量工作机制

TASK1阻塞等待信号量,直到TASK2释放后获得,解除阻塞态

2.3二值信号量应用场景—同步

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

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

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

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

2.4二值信号量API

2.4.1创建二值信号量

#inlcude "FreeRTOS.h"
#include "semphr.h"/*创建二值信号量*/
SemaphoreHandle_t xSemaphoreCreatBinary(void)func:dynamically creat binary semaphore and return  semaphore_handle //创建二值信号量并返回句柄,初始化信号量值为0return: NULL: 堆空间不足Any other value: 成功返回的句柄matters needing attention: 
configSUPPORT_DYNAMIC_ALLOCATION必须置1

2.4.2任务中释放信号量

#inlcude "FreeRTOS.h"
#include "semphr.h"/*任务中释放信号量(无论是哪种具体的信号量 都用这个API!!!)*/
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore)func:release semaphore in task//任务中释放信号量params:xSemaphore    return: pdTRUE: 释放成功pdFAIL: 因为信号量的实现是基于消息队列,返回失败的主要原因是消息队列已经满了matters needing attention: 
此函数不支持使用 xSemaphoreCreateRecursiveMutex()创建的信号量

2.4.3中断中释放信号量

#inlcude "FreeRTOS.h"
#include "semphr.h"/*中断中释放信号量(无论是哪种具体的信号量 都用这个API!!!)*/
BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken)func:release semaphore in ISR //中断中释放信号量    params:xSemaphore 句柄pxHigherPriorityTaskWoken 用于保存是否有高优先级任务准备就绪 意味着释放信号量成功后,是否进行上下文切换(pdTRUE) 一般使用NULLreturn: pdTRUE:        释放成功errQUEUE_FULL: 已经释放过了,相当于信号量的值顶满了 1~1matters needing attention: 
此函数不支持使用 xSemaphoreCreateMutex ()创建的信号量

2.4.4任务中获取信号量

#inlcude "FreeRTOS.h"
#include "semphr.h"/*任务中获取信号量(无论是哪种具体的信号量 都用这个API!!!)*/
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait)func:get semaphore in task//任务中获取信号量    params:xSemaphore   句柄xTicksToWait 阻塞时间 portMAX_DELAY表示一直“痴情”等return: pdTRUE: 获取成功pdFAIL: 获取失败matters needing attention: 
此函数不支持使用 xSemaphoreCreateRecursiveMutex()创建的信号量

2.4.5中断中获取信号量

#inlcude "FreeRTOS.h"
#include "semphr.h"/*中断中获取信号量(无论是哪种具体的信号量 都用这个API!!!)*/
BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken)func:get semaphore in isr//中断中获取信号量    params:xSemaphore 句柄pxHigherPriorityTaskWoken 用于保存是否有高优先级任务准备就绪 意味着释放信号量成功后,是否进行上下文切换(pdTRUE) 一般使用NULL   return: pdTRUE: 获取成功pdFAIL: 获取失败matters needing attention: 
只能在中断中调用,没有阻塞功能

三、计数信号量

3.1定义

取值为0~n(n>1具体用户决定)的信号量

3.2作用

计数信号量是资源管理的重要手段,主要用于任务与任务间

 3.3创建计数信号量

#inlcude "FreeRTOS.h"
#include "semphr.h"/*创建计数信号量*/
SemaphoreHandle_t xSemaphoreCreatCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount)func:dynamically creat counting semaphore and return  semaphore_handle //创建、初始化计数信号量并返回句柄param: uxMaxCount       最大值uxInitialCount   初始值  return: NULL: 堆空间不足Any other value: 成功返回的句柄matters needing attention: 
configSUPPORT_DYNAMIC_ALLOCATION必须置1
USE_COUNTING_SEMAPHORE必须置1

3.4获取当前计数信号量的值

#inlcude "FreeRTOS.h"
#include "semphr.h"/*获取当前计数信号量的值*/
SemaphoreHandle_t xSemaphoreGetCount(SemaphoreHandle_t xSemaphore)func:return current value of counting semaphore //返回当前计数信号量的值param: xSemaphore  计数信号量句柄matters needing attention: None

四、实现原理 

信号量是基于消息队列实现的机制,这点在代码中有很好的印证

1.二值信号量的创建

xSemaphoreCreatBinary(队列长度=1,ItemSize=0,消息队列类型参数)

消息大小为0因为消息空间没有意义

2.计数信号量

xSemaphoreCreatCounting() 实际接口xQueueCreatCountingSemaphore(),内部调用消息队列的创建API

uxMessageWaiting = uxInitialCount 表示创建后就可获取,不用阻塞等待

3.信号量的删除

完全拷贝消息队列的删除

4.释放信号量

Give对应Send,任务级对应任务级,中断级对应中断级。

消息队列的发送/接收都有阻塞任务的功能,但信号量的释放是把阻塞参数设为0,因为信号量释放是一个紧急事件,当信号量资源达到最大,就不需要再等待其他任务使用

中断中的Give实际又封装了一个消息队列give的API,与send的区别就是没有数据拷贝功能(也不需要),因为信号不占用空间

5.获取信号量

如同Give对应Send,Take则对应Receive,区别就是接收缓冲区=NULL,出队固定删除空间


http://www.ppmy.cn/server/144370.html

相关文章

《鸿蒙系统:开启智能新时代的璀璨之星》

一、鸿蒙系统:崛起之路 鸿蒙系统的发展历程堪称一部科技创新的传奇。2012 年,华为前瞻性地启动鸿蒙系统研发项目,彼时或许很少有人能预见到它未来的辉煌。2019 年,鸿蒙系统首个开发者预览版的发布,如同夜空中的一颗璀…

第二十二章 Spring之假如让你来写AOP——Target Object(目标对象)篇

Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…

I.MX6U 裸机开发15.IRQ中断——GPIO中断处理

I.MX6U 裸机开发15.IRQ中断——GPIO中断处理 一、向GPIO驱动添加中断处理函数1. GPIO 相关寄存器(1)GPIOx_ICRn 按键GPIO设置中断模式(2)使能GPIO对应的中断(3)GPIOx_EDGE_SEL(4)GPI…

4-7-1.C# 数据容器 - LinkedList(LinkedList 的定义、LinkedList 结点的遍历、LinkedList 的常用方法)

LinkedList 概述 LinkedList<T> 通过节点&#xff08;Node&#xff09;来存储数据&#xff0c;每个节点包含数据和指向下一个节点的引用 LinkedList<T> 存储的元素是可重复的 LinkedList<T> 支持泛型&#xff0c;可以指定存储的元素的类型 LinkedList<…

ETCD调优

ETCD是一种高可用的分布式键值存储&#xff0c;广泛用于Kubernetes和其他云原生应用。为了确保ETCD在生产环境中的性能和稳定性&#xff0c;以下是一些调优建议&#xff1a; 1. 硬件和网络 节点配置&#xff1a;使用较高配置的硬件&#xff0c;尤其是CPU和内存&#xff0c;以…

Sobey融媒体 硬编码漏洞复现

0x01 产品描述: ‌ Sobey融媒体‌是成都索贝数码科技股份有限公司(简称索贝)提供的一系列融媒体解决方案,旨在帮助媒体机构实现新闻内容的快速采集、高效生产、首发首推、安全可控和灵活迭代。这些解决方案主要应用于广播、电视和新媒体各渠道,提供轻量化、移动化…

PDF内容提取,MinerU使用

准备环境 # python 3.10 python3 -m pip install huggingface_hub python3 -m pip install modelscope python3 -m pip install -U magic-pdf[full] --extra-index-url https://wheels.myhloli.com下载需要的模型 import json import osimport requests from huggingface_hub…

【AI系统】GPU 架构回顾(从2010年-2017年)

GPU 架构回顾 1999 年&#xff0c;英伟达发明了 GPU&#xff08;graphics processing unit&#xff09;&#xff0c;本文将介绍英伟达 GPU 从 Fermi 到 Blackwell 共 9 代架构&#xff0c;时间跨度从 2010 年至 2024 年&#xff0c;具体包括费米&#xff08;Feimi&#xff09;…