一文带你深度了解FreeRTOS——计数型信号量

 

本文记录FreeRTOS的计数型信号量知识,希望我的分享对你有所帮助!

目录

一、计数型信号量简介 

二、创建计数型信号量

1、动态创建计数型信号量

2、静态创建计数型信号量

三、结语 


一、计数型信号量简介 

计数型信号量在FreeRTOS中用于管理对共享资源的访问。它允许多任务间同步和互斥,通过设置最大计数值来限制资源的使用。任务可以“获取”信号量,如果计数值大于0,则计数减1并继续执行;如果计数为0,任务会被阻塞直到信号量被释放。信号量被“释放”时,计数值增加,可能会唤醒阻塞的任务。这个机制帮助管理并发任务对有限资源的访问。

我们知道,二值信号量相当于长度为1的队列,那么计数型信号量就是长度大于1的队列,作为用户不需要知道队列里存的是什么,只需要关心队列是否为空就行。

计数型信号量通常被应用于以下场合:

【1】用于事件计数

在事件每次发生的时候,就在事件处理函数中释放信号量,即增加信号量的计数值,其他任务会在此时获取信号量,即信号量计数值减一(此处的信号量值就是结构体成员变量:uxMessagesWaiting),进而根据信号量计数值的变化来处理事件。

在这种场合中创建的计数型信号量初始计数值为0.

【2】资源管理

这时的信号量值表示的是当前资源的可用数量。比如会场剩余的座位数量。一个任务如果想获得资源的使用权,首先必须获取信号量,获取成功后的信号量值就会减一。当信号量的值为0的时候就说明以已经没有资源了。而且,如果一个任务使用完资源后,就一定要释放信号量,释放信号量以后信号量的值就会加一。

在这种场合中信号量的初始值就应该是资源的数量,比如会场的座位数量为100,那么创建信号量的时候信号量的初始值就应该是100.

二、创建计数型信号量

1、动态创建计数型信号量

xSemaphoreCreateCounting 是 FreeRTOS 中用于创建计数型信号量的函数。计数型信号量可以用于任务之间的同步和互斥。

SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);

参数

  • uxMaxCount:

    • 类型: UBaseType_t
    • 描述: 计数型信号量可以持有的最大计数值。即信号量的“最大值”。
  • uxInitialCount:

    • 类型: UBaseType_t
    • 描述: 创建信号量时的初始计数值。即信号量的“初始值”。这个值应该小于或等于 uxMaxCount

返回值

  • 成功: 返回一个 SemaphoreHandle_t 类型的信号量句柄。这个句柄用于以后对信号量的操作。
  • 失败: 返回 NULL,表示信号量创建失败。创建失败可能是由于内存不足或其他原因。

创建实例:

#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"// 定义信号量句柄
SemaphoreHandle_t xSemaphore;void vTask1(void *pvParameters) {for (;;) {// 请求信号量if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {// 成功获取信号量,执行任务// ...// 释放信号量xSemaphoreGive(xSemaphore);}// 延时,模拟任务执行vTaskDelay(pdMS_TO_TICKS(1000));}
}void vTask2(void *pvParameters) {for (;;) {// 请求信号量if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {// 成功获取信号量,执行任务// ...// 释放信号量xSemaphoreGive(xSemaphore);}// 延时,模拟任务执行vTaskDelay(pdMS_TO_TICKS(500));}
}int main(void) {// 创建计数型信号量,最大计数为3,初始计数为3xSemaphore = xSemaphoreCreateCounting(3, 3);if (xSemaphore == NULL) {// 信号量创建失败,进行错误处理// ...}// 创建两个任务xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);// 启动调度器vTaskStartScheduler();// 启动调度器后不会返回for (;;);
}

2、静态创建计数型信号量

xSemaphoreCreateCountingStatic() 是 FreeRTOS 提供的一个 API,用于创建一个静态分配的计数型信号量。它的主要功能是用于管理对共享资源的访问。

函数原型:

SemaphoreHandle_t xSemaphoreCreateCountingStatic(UBaseType_t uxMaxCount,UBaseType_t uxInitialCount,StaticSemaphore_t *pxSemaphoreBuffer
);

参数说明:

  • uxMaxCount:信号量的最大计数值,即可以支持的最大资源数量。
  • uxInitialCount:信号量的初始计数值,通常是资源的初始可用数量。
  • pxSemaphoreBuffer:指向 StaticSemaphore_t 结构体的指针,这个结构体用于保存信号量的静态分配数据。

返回值:

  • 如果成功创建信号量,返回信号量句柄(SemaphoreHandle_t)。
  • 如果创建失败,返回 NULL

使用示例:

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"// 定义信号量缓冲区
StaticSemaphore_t xSemaphoreBuffer;
SemaphoreHandle_t xCountingSemaphore;// 任务函数
void vTask1(void *pvParameters) {for (;;) {if (xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) == pdTRUE) {// 访问共享资源// 执行任务代码printf("Task 1 acquired the semaphore.\n");// 释放共享资源xSemaphoreGive(xCountingSemaphore);}vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1秒}
}void vTask2(void *pvParameters) {for (;;) {if (xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) == pdTRUE) {// 访问共享资源// 执行任务代码printf("Task 2 acquired the semaphore.\n");// 释放共享资源xSemaphoreGive(xCountingSemaphore);}vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1秒}
}int main(void) {// 创建计数型信号量xCountingSemaphore = xSemaphoreCreateCountingStatic(3,              // 最大计数值3,              // 初始计数值&xSemaphoreBuffer  // 静态分配的缓冲区);if (xCountingSemaphore == NULL) {// 处理信号量创建失败的情况printf("Failed to create semaphore.\n");return 1;}// 创建任务xTaskCreate(vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);xTaskCreate(vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);// 启动调度器vTaskStartScheduler();// 如果到达此处,说明调度器启动失败for (;;);return 0;
}

说明:

  • xSemaphoreCreateCountingStatic() 被用于创建一个最大计数值为 3 的计数型信号量,初始计数值也为 3。
  • vTask1 和 vTask2 是两个任务,它们会尝试获取和释放信号量,模拟对共享资源的访问。
  • xSemaphoreTake() 和 xSemaphoreGive() 分别用于获取和释放信号量。
  • vTaskDelay() 用于任务间的延时,以模拟任务的执行时间和避免过于频繁的信号量操作。

三、结语 

关于FreeRTOS的计数型信号量就分享到此了,敬请关注,一起加油!

持续更新中~~~

 

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

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

相关文章

拥有这些AI绘画网站,让你轻松告别手绘时代!

在这个充满无限可能的数字世界里,AI 绘画动漫网站已经成为了许多艺术家和设计师的新宠。从手绘时代的岁月如歌,到今天科技的飞速发展,我们已经可以用AI技术创作出令人惊叹的艺术作品,打开了全新的创作空间。接下来,就让…

如何打造一个智能化的远程在线考试系统?

远程教育与在线考试已成为提升知识传播效率和学习灵活性的重要手段。 土著刷题在线考试系统,凭借其完善的多功能考试模块,为教育机构、学校乃至企业提供了一个智能化的远程在线考试解决方案。 接下来将介绍土著刷题在线考试系统如何助力用户构建一个高效…

小琳Python课堂:Python 高并发实现的基本原理(简化版)

大家好,这里是小琳Python课堂! 今天,我们来聊聊Python中实现高并发的三个核心概念:线程安全性、线程同步和原子性。这些概念对于确保我们的程序在多线程环境中正确、高效地运行至关重要。 线程安全性 首先,什么是线程…

51单片机-串口通信(单片机和PC互发数据)

作者:Whappy 时间:2024.9.3 关于串口的疑问? 根据我的代码是不是初始化完成串口之后,只要我们使用串口发送数据就会触发中断? (在文章下面) ChatGPT said: ChatGPT 是的,根据…

[AWS云]EC2扩容磁盘之linux系统

背景: ec2的磁盘存储满了,需要扩容。 1.控制台修改存储大小: 2. 3.登录服务器,刷新磁盘: 云盘扩容 growpart /dev/vdb 1对ext4扩容命令resize2fs /dev/vdb1对xfs扩容命令xfs_growfs /dev/vdc1

传统CV算法——基于opencv的答题卡识别判卷系统

基于OpenCV的答题卡识别系统,其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术,自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述: 1. 导入必要的库 系统首先导入…

openlayers+vite+vue3实现规划某一特定行政区(二)

在前一期实现离线地图初始化的基础上,本文中主要阐述如何实现规划某一特定行政区,并展示其行政区的区县名称。 提示:因前文中阐述了如何实现离线地图的初始化,所以在此不再进行书写并详解初始化的过程和流程,如有不明…

MySQL简介和管理

目录 一、数据库基本概念 1.1、数据 1.2、表 1.3、数据库 1.4、数据库管理系统 1.5、数据库系统 二、数据库发展史 2.1、第一代数据库 2.2、第二代数据库 2.3、第三代数据库 三、数据库类型 3.1、关系型数据库 3.2、关系型数据库应用 3.3、非关系型数据库 3.4、…

【Python】数据分析分类图可视化

目录 条形图 箱形图 散点图 分簇散点图 小提琴 分簇小提琴 条形图 条形图是一种直观的图表形式,它通过不同长度的矩形条(即“条形”)来展示数值变量的中心趋势估计值,其中每个矩形的高度直接对应于该组数据的某个中心量度&…

若依微服务Admin控制台不显示ruoyi-file问题解决

本地启动完若依微服务,发现Admin控制台只显示了6个服务,其中ruoyi-file启动成功,但是没有在Admin控制台中显示处理,本章问题,给出这个问题的解决办法。 一、什么是服务监控 监视当前系统应用状态、内存、线程、堆栈、日志等等相关信息,主要目的在服务出现问题或者快要出…

JMeter 安装使用

JMeter 安装使用 a.安装 下载链接:Apache JMeter - Download Apache JMeter 环境变量 打开 cmd 输入 jmeter,即可启动 b.使用 http请求接口 300 个线程设置 1 s 的预热时间 右键 start

【STM32+HAL库】---- 基础定时器中断控制LED

硬件开发板:STM32G0B1RET6 软件平台:cubemaxkeilVScode1 新建cubemax工程 1.1 配置系统时钟RCC 1.2 配置LED LED由PA5引脚控制,选择PA5引脚,选择GPIO_Output模式 1.3 定时时间的计算 T ( 预分频系数 1 ) ( 重装载值 1 ) 时…

数仓基础(九):各大公司实时数仓实践

文章目录 各大公司实时数仓实践 一、网易实时数仓实践 二、汽车之家实时数仓实践 三、顺丰实时数仓实践 四、​​​​​​​腾讯实时数仓实践 五、​​​​​​​​​​​​​​滴滴实时数仓实践 ​​​​​​​​​​​​​​各大公司实时数仓实践 一、网易实时数仓实践…

Opencv实现提取卡号(数字识别)

直接开始 实行方法 解析命令行参数:使用argparse库来解析命令行输入,确保用户提供了输入图像和模板图像的路径。 读取模板图像:使用cv2.imread()函数读取模板图像的路径,并显示原始图像。 图像预处理: 将图像转换为…

Promises - 从零开始(万字详解)

目录 前言 为何这样设计 回调函数 介绍Promises 使用Promises 创建自己的Promises Promise 链 传递数据 错误处理Promises async / await 结语 ❤️❤️❤️ 前言 在学习JavaScript的过程中往往会面临很多挑战,其中最让人头疼的要数Promises了。想真正理…

【CF补题数学裴蜀定理】 div969 C Dora and C++

Dora and C 分析: 对于两个数x,y 我们想要通过如下操作使得他们的差变得尽可能小 我们要如何操作? 这个操作也就是相当于 d e l ∣ y − x ∣ − k 1 ∗ x − k 2 ∗ y del|y-x|-k_1*x-k_2*y del∣y−x∣−k1​∗x−k2​∗y,让这个差值最小…

【网络安全】IDOR之敏感数据泄露

未经许可,不得转载。 文章目录 正文正文 在测试“添加到收藏夹”功能时,我拦截了发送到服务器的请求,请求体如下: {“uriTemplate”:“asset/{assetId}/favorite”,“version”:“v2”,“type”:“POST”,“req_service”:“pict”,“url”:“asset/VICTIMS_ASS…

Android Google Maps

Android 谷歌地图 前言正文一、设置Google Cloud 项目二、项目配置① 设置SDK② 配置API密钥③ 配置AndroidManifest.xml 三、添加地图四、定位当前① 请求定位权限② 我的位置控件③ 获取当前位置 五、配置地图① xml配置地图② 代码配置地图③ 地图点击事件④ 管理Marker 六、…

薛定谔的空气墙?一文带你了解其背后的技术原理

封面图 悟空来了都得撞墙? 目前,被称作“村里第一个大学生”的国产3A游戏《黑神话:悟空》发售已经有一段时间了,游戏采用虚幻引擎4技术,仿佛将传统与现代的界限模糊,玩家游玩时沉浸感极强。然而&#xff…

自然语言处理系列五十三》文本聚类算法》文本聚类介绍及相关算法

注:此文章内容均节选自充电了么创始人,CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》(人工智能科学与技术丛书)【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列五十三文本聚类算法》文本聚类介绍及相关算法K…