FreeRTOS 实时操作系统第十二讲 - 计数信号量

news2024/10/5 16:23:22

一、信号量的概念

1、信号量的基本概念

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

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

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

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

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

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

2、信号量的分类

  1. 二值信号量 (重点讲解同步应用)
  2. 技术信号量 (重点讲解资源管理)
  3. 互斥信号量 (重点讲解互斥访问)
  4. 递归互斥信号量 (简要了解即可)

二、计数信号量的定义与应用

1、计数信号量的定义

  取值只有 0 与 1 两种状态的信号量称之为二值信号量
  取值大于 1 的信号量称之为计数信号量
  Note:计数信号量的取值也可以为 1,但通常大于 1,如果取值为 1,相当于只有 0 与 1 两种状态,用二值信号量即可。
  创建计数信号量时,系统会为创建的计数信号量分配内存,计数信号量创建完成后的示意图如下:

  从上图可以看出,计数信号量是一种长度大于 1,消息大小为 0 的特殊消息队列。

  因为这个队列的消息大小为 0,因此在运用时,只需要知道队列中是否有消息即可,而无需关注消息是什么。

2、计数信号量的应用

  在嵌入式操作系统中,计数信号量是资源管理的重要手段,主要用于任务与任务间。

应用场景:

  计数信号量允许多个任务对其进行操作,但限制了任务的数量。比如有一个停车场,里面只有 50 个车位,那么只能停 50 辆车,相当于我们的信号量有 50 个。假如一开始停车场的车位还有 50 个,那么每进去一辆车就要消耗一个停车位,车位的数量就要减 1,相应地,我们的信号量在使用之后也需要减 1。当停车场停满了 50 辆车时,此时的停车位数量为 0,再来的车就不能停进去了,否则将没法停车了,也相当于我们的信号量为 0,后面的任务对这个停车场资源的访问也无法进行。当有车从停车场离开时,车位又空余出来了,那么后面的车就能停进去了。信号量操作也是一样的,当我们释放了这个资源,后面的任务才能对这个资源进行访问。

三、计数信号量的运作机制

FreeRTOS 任务间计数信号量的实现

  任务间信号量的实现是指各个任务之间使用信号量实现任务的同步或者资源共享功能。下面我们通过如下的框图来说明一下 FreeRTOS 计数信号量的实现,让大家有一个形象的认识。


运行条件:

  1. 创建 任务 Task1 和 Task2 至 N。
  2. 创建计数信号量可用资源为 N。

运行过程描述如下:

  • 任务 Task1 运行过程中调用函数 xSemaphoreTake 获取信号量资源,如果信号量大于 0,Task1 将直接获取资源。如果信号量为 0,任务 Task1 将由运行态转到阻塞状态,等待资源可用。一旦获取了资源并使用完毕后会通过函数 xSemaphoreGive 释放掉资源。

  • 任务 Task2 至 N 运行过程中调用函数 xSemaphoreTake 获取信号量资源,如果信号量大于 0,Task2 至 N 将直接获取资源。如果信号量为 0,任务 Task2 至 N 将由运行态转到阻塞状态,等待资源可用。一旦获取了资源并使用完毕后会通过函数 xSemaphoreGive 释放掉资源。

上面就是一个简单的 FreeRTOS 任务间计数信号量的使用过程。

四、计数信号量常用的 API 函数

1、使用计数信号量的典型流程如下:

  1. 创建计数信号量
  2. 释放计数信号量
  3. 获取计数信号量
  4. 删除计数信号量

2、常用 API 函数如下:

  1. xSemaphoreCreateCounting()
  2. xSemaphoreGive() 与 xSemaphoreGiveFromISR()
  3. xSemaphoreTake()
  4. vSemaphoreDelete()

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

二值信号量控制块 (句柄)

  如下图:计数信号量的句柄为消息队列的句柄,因为计数信号量是一种长度大于 1,消息大小为 0 的特殊消息队列

计数信号量创建

函数原型:

SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, /* 支持的最大计数值 */                             UBaseType_t uxInitialCount); /* 初始计数值 */

函数描述:
  函数 xSemaphoreCreateCounting 用于创建计数信号量。

  1. 第 1 个参数是设置此计数信号量支持的最大计数值。
  2. 第 2 个参数是设置计数信号量的初始值。
  3. 返回值,如果创建成功会返回消息队列的句柄,如果由于 FreeRTOSConfig.h 文件中 heap 大小不足,无法为此消息队列提供所需的空间会返回 NULL

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

应用举例:

计数信号量删除

函数原型:

void vSemaphoreDelete(void)

函数描述:

  函数 vSemaphoreDelete 可用于删除计数信号量。

4、任务中计数信号量释放

函数原型:

xSemaphoreGive(SemaphoreHandle_t xSemaphore); /* 信号量句柄 */

函数描述:

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

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

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

  1. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是 xSemaphoreGiveFromISR。
  2. 使用此函数前,一定要保证用函数 xSemaphoreCreateBinary(), xSemaphoreCreateMutex() 或者 xSemaphoreCreateCounting() 创建了信号量。
  3. 此函数不支持使用 xSemaphoreCreateRecursiveMutex() 创建的信号量。

应用举例:

5、中断中计数信号量释放

函数原型:

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 () 创建的信号量。

6、计数信号量获取

函数原型:

xSemaphoreTake( SemaphoreHandle_t xSemaphore, /* 信号量句柄 */ 

             TickType_t xTicksToWait ); /* 等待信号量可用的最大等待时间 */

函数描述:
  函数 xSemaphoreTake 用于在任务代码中获取信号量。

  • 第 1 个参数是信号量句柄。
  • 第 2 个参数是没有信号量可用时,等待信号量可用的最大等待时间,单位系统时钟节拍。
  • 返回值,如果创建成功会获取信号量返回 pdTRUE,否则返回 pdFALSE。

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

  1. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序使用的是 xSemaphoreTakeFromISR。
  2. 如果消息队列为空且第 2 个参数为 0,那么此函数会立即返回。
  3. 如果用户将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为 1 且第 2 个参数配置为 portMAX_DELAY,那么此函数会永久等待直到信号量可用。

应用举例:

五、技术信号量的应用编程

视频讲解

串口输出信息:

STM32cubeMX 配置:



代码:


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

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

相关文章

【MATLAB源码-第105期】基于matlab的4PAM调制解调仿真,输出误码率和误符号曲线并且和理论值对比。

操作环境: MATLAB 2022a 1、算法描述 4PAM(4-Pulse Amplitude Modulation,4脉冲幅度调制)是一种数字调制技术,它通过改变载波信号的幅度来表示数据。在4PAM中,载波的幅度可以采用四种不同的水平&#xf…

Docker安装Centos8系统

引言:最小安装版Centos8系统安装docker软件安装记录 官网安装教程:https://dockerdocs.cn/engine/install/centos/index.html 操作系统镜像版本 CentOS-Stream-8-x86_64-latest-boot.iso 第一步:更新yum yum -y update第二步:…

H266/VVC环路滤波技术概述

环路滤波 环路滤波:是提高编码视频主客观质量的有效工具,不同于图像增强处理中的滤波技术,环路滤波是在视频编码过程进行滤波,滤波后的图像用于后续图像的编码,即位于“环路”中。 环路滤波的作用: 一方面…

【hcie-cloud】【17】华为云Stack灾备服务介绍【灾备方案概述、备份解决方案介绍】【上】

文章目录 前言灾备方案概述灾备的定义灾备的重要性故障和灾难对业务连续性带来的挑战灾备系统的衡量指标RTO与RPO分析 灾备等级标准数据中心容灾解决方案全景图云灾备服务总结架构华为云Stack灾备服务总览 备份解决方案介绍云备份服务介绍备份服务架构介绍云备份服务组件功能介…

标签函数 - 打造JavaScript组件

📢 鸿蒙专栏:想学鸿蒙的,冲 📢 C语言专栏:想学C语言的,冲 📢 VUE专栏:想学VUE的,冲这里 📢 CSS专栏:想学CSS的,冲这里 &#x1f4…

vite 如何打包 dist 文件到 zip 使用插件 vite-plugin-zip-pack,vue3 ts

vite 如何打包 dist 文件到 zip 使用插件 vite-plugin-zip-pack,vue3 ts 开发过程中一个经常做的事就是将 ./dist 文件夹打包成 zip 分发。 每次手动打包还是很费劲的, vite 同样也有能把 ./dist 文件夹打包成 .zip 的插件,当然这个打包的文…

ubuntu 22 virt-manger(kvm)安装winxp; ubuntu22体验 firebird3.0

安装 、启动 virt-manager sudo apt install virt-manager sudo systemctl start libvirtdsudo virt-manager安装windowsXP 安装过程截图如下 要点1 启用 “包括寿终正寝的操作系统” win_xp.iso 安装过程 : 从winXp.iso启动, 执行完自己重启从硬盘重启&#xff0c…

09、docker 安装nacos并配置mysql存储配置信息

docker 安装nacos并配置mysql存储配置信息 1、docker启动nacos的各种方式2、Docker安装nacos3、MySQL中新建nacos的数据库4、挂载数据or配置目录5、运行 1、docker启动nacos的各种方式 内嵌derby数据源 docker run -d \ -e PREFER_HOST_MODEhostname \ -e SPRING_DATASOURCE_…

如何从 Android手机存储卡中恢复已删除的文件

作为 Android 用户,您可能会使用 存储卡来扩展手机的存储容量,并存储照片、视频和其他类型的文件。但意外发生时,您可能会错误地删除其中一些文件,或者由于其他原因而丢失它们。在大多数情况下,您可以通过主动并遵循正…

Microsoft Visual Studio 2022 install Project 下载慢

1. 关闭Internet 协议版本6 2. 如果没有效果,打开Internet 协议版本4,更改DNS 3. 在浏览器中下载后安装,下载地址如下: Microsoft Visual Studio Installer Projects 2022 - Visual Studio Marketplace 4. 安装时注意关闭vs&…

在Flyway执行数据库脚本之前创建数据库

Flyway让我们不用手动执行sql脚本,但是众所周知,前提是要先创建项目的数据库。为了能够让运维的同事再偷一次懒,通过代码来自动完成数据库的创建,于是有了这篇文章的分享~ 要实现这个效果,只需要两步: 第一…

Python基础(十九、文件操作写入与追加)

文章目录 一、文件的写入(使用 "w" 模式)二、文件的追加(使用 "a" 模式)三、文件备份案例接之前的答案 在 Python 中,open() 是一个内置函数,用于打开文件并返回文件对象。它是处理文件…

HTML的简单介绍

文章目录 1. HTML1.1 HTML 基础认识1.2 快速生成代码框架1.3 HTML 基础标签 1. HTML 1.1 HTML 基础认识 什么是HTML呢? HTML叫做超文本标记语言。超文本:例如图片,视频,文本,声音,表格,链接等…

智能语音机器人NXCallbot

受出海公司业务全球化的影响,智能客服逐渐从便捷应用变为市场刚需。新基建七大领域中,人工智能及场景应用的基础建设是最核心的领域,而智能客服作为商业化实际应用的核心场景之一,能提升企业运营效率,为行业客户赋能。…

晶振老化和晶振引脚氧化的原因与影响

相信大部分的客户都会遇到晶振老化和晶振引脚氧化,而很多新手也难民啊会混淆晶振老化和晶振引脚样话这两个概念,也不理解。那么接下来,晶发给大家详细讲解,这两种情况怎么发生以及如何避免此类情况发生,保护我们的晶振…

苹果macOS 14.3开发者预览版Beta 2发布 修复API会意外失败的问题

1 月 4 日消息,苹果向 Mac 电脑用户推送了 macOS 14.3 开发者预览版 Beta 2 更新(内部版本号:23D5043d),本次更新距离上次发布隔了 22 天。 macOS Sonoma 14.3 Beta 2 主要以修复 BUG、提高安全性为主。根据苹果官方更…

Linux内核(1)-内核目录介绍,每个人都应该了解的内核目录结构

1.总览 2.详解 arch目录:架构相关目录,例如arm、arm64 arch/arm/configs:不同平台的默认配置文件,例如xxx_defconfig arch/arm/boot/dts:设备树文件 arch/arm/boot:编译出的Image和zImage Linux镜像文件 …

强化学习5——动态规划初探

动态规划具体指的是在某些复杂问题中,将问题转化为若干个子问题,并在求解每个子问题的过程中保存已经求解的结果,以便后续使用。实际上动态规划更像是一种通用的思路,而不是具体某个算法。 在强化学习中,被用于求解值函…

LLM之RAG实战(十三)| 利用MongoDB矢量搜索实现RAG高级检索

想象一下,你是一名侦探,身处庞大的信息世界,试图在堆积如山的数据中找到隐藏的一条重要线索,这就是检索增强生成(RAG)发挥作用的地方,它就像你在人工智能和语言模型世界中的可靠助手。但即使是最…

外包干了4个月,技术退步明显了...

先说一下自己的情况,大专生,18年通过校招进入武汉某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四…