news 2026/2/10 7:22:05

FreeRTOS学习笔记(9)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FreeRTOS学习笔记(9)

消息量

信号量本质上是一个特殊的队列,但是它内部是一个计数装置,通过计数来表明程序的状态,可以理解成一个状态机,

信号量是FreeRTOS中用于"计数"和"同步"的工具,主要解决:1个资源多个任务抢的问题,和1个事件多个任务等的问题。

信号量的使用主要分为创建,读取,释放三个步骤,此外还有一个删除操作

创建信号量

使用信号量之前,要先创建,得到一个句柄;使用信号量时,要使用句柄来表明使用哪个信号量。 对于二进制信号量、计数型信号量,它们的创建函数不一样:

具体的信号量还分为二进制信号量,和计数信号量

他两个大致的区别就是,二进制初始数据只能是1,技术型可以自己设定

此外还有动态和静态之分,动态和静态的区别前面已经说过

这个里就直接搬运韦老师的代码了

/* 创建一个二进制信号量,返回它的句柄。 * 此函数内部会分配信号量结构体 * 返回值: 返回句柄,非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateBinary( void ); /* 创建一个二进制信号量,返回它的句柄。 * 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针 * 返回值: 返回句柄,非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer ); 创建计数型信号量的函数原型如下: /* 创建一个计数型信号量,返回它的句柄。 * 此函数内部会分配信号量结构体 * uxMaxCount: 最大计数值 * uxInitialCount: 初始计数值 * 返回值: 返回句柄,非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount); /* 创建一个计数型信号量,返回它的句柄。 * 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针 * uxMaxCount: 最大计数值 * uxInitialCount: 初始计数值 * pxSemaphoreBuffer: StaticSemaphore_t结构体指针 * 返回值: 返回句柄,非NULL表示成功 */ SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer );

然后是读取函数,这个函数有任务中和中断中两种

在任务中使用在ISR中使用
givexSemaphoreGivexSemaphoreGiveFromISR

xSemaphoreGive的函数原型如下:

BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

xSemaphoreGive函数的参数与返回值列表如下:

参数说明
xSemaphore信号量句柄,释放哪个信号量
返回值pdTRUE表示成功, 如果二进制信号量的计数值已经是1,再次调用此函数则返回失败; 如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败

pxHigherPriorityTaskWoken的函数原型如下:

BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );

xSemaphoreGiveFromISR函数的参数与返回值列表如下:

参数说明
xSemaphore信号量句柄,释放哪个信号量
pxHigherPriorityTaskWoken如果释放信号量导致更高优先级的任务变为了就绪态, 则*pxHigherPriorityTaskWoken = pdTRUE
返回值pdTRUE表示成功, 如果二进制信号量的计数值已经是1,再次调用此函数则返回失败; 如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败

然后是释放

xSemaphoreTake的函数原型如下:

BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );

xSemaphoreTake函数的参数与返回值列表如下:

参数说明
xSemaphore信号量句柄,获取哪个信号量
xTicksToWait如果无法马上获得信号量,阻塞一会: 0:不阻塞,马上返回 portMAX_DELAY: 一直阻塞直到成功 其他值: 阻塞的Tick个数,可以使用*pdMS_TO_TICKS()*来指定阻塞时间为若干ms
返回值pdTRUE表示成功

xSemaphoreTakeFromISR的函数原型如下:

BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );

xSemaphoreTakeFromISR函数的参数与返回值列表如下:

参数说明
xSemaphore信号量句柄,获取哪个信号量
pxHigherPriorityTaskWoken如果获取信号量导致更高优先级的任务变为了就绪态, 则*pxHigherPriorityTaskWoken = pdTRUE
返回值pdTRUE表示成功

最后是删除操作

对于动态创建的信号量,不再需要它们时,可以删除它们以回收内存。

vSemaphoreDelete可以用来删除二进制信号量、计数型信号量,函数原型如下:

/* * xSemaphore: 信号量句柄,你要删除哪个信号量 */ void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );

然后我来给大家将几点注意事项

1.如果你的代码不是事先用CUBEMX生成好的信号量,那么你就需要引用

#include "semphr.h"

头文件

2.一定有释放要不然又溢出风险,这种一般是不会编译报错的,但是运行不出来结果

然后我们在使用信号量可能会出现优先级反转的问题,简单来说,就是低优先级的任务运行比高优先级的任务高,这个原因就是因为,信号量的权限一直在低优先级手里,也就是低优先级没有释放信号量造成的,

大概如图所示

要想完美解决这个问题就要使用到互斥量

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/5 23:10:22

小程序毕设选题推荐:基于微信小程序的网上服装商城系统基于springboot+微信小程序的服装商城的设计与实现小程序【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/2/4 3:46:59

Spark3.0新特性解析:性能提升与功能增强全知道

Spark3.0新特性解析:性能提升与功能增强全知道关键词:Spark3.0、自适应查询执行(AQE)、动态分区裁剪(DPC)、矢量化执行、ANSI SQL、Structured Streaming、数据倾斜 摘要:Spark作为大数据领域的…

作者头像 李华
网站建设 2026/2/8 20:26:39

提示工程架构师带你领略Agentic AI提示工程自我学习能力的灵活性

Agentic AI提示工程:让你的Prompt学会“自我进化”的灵活之道 引言:传统提示工程的“静态困境”与Agentic AI的破局 你是否遇到过这样的困扰? 精心设计的Prompt在面对多样化的用户问题时,常常“水土不服”——比如针对普通用户的…

作者头像 李华
网站建设 2026/2/7 18:20:58

道路抛洒物检测数据集1650张VOC+YOLO格式

道路抛洒物检测数据集1650张VOCYOLO格式数据集格式:VOC格式YOLO格式压缩包内含:3个文件夹,分别存储图片、xml、txt文件JPEGImages文件夹中jpg图片总计:1650Annotations文件夹中xml文件总计:1650labels文件夹中txt文件总…

作者头像 李华
网站建设 2026/2/5 23:10:54

缓存 --- Redis缓存的一致性

缓存 --- Redis缓存的一致性核心问题:更新数据库与缓存的顺序抉择方案一:直接更新缓存(不推荐)方案二:删除缓存(让缓存失效,推荐)进阶优化:解决极端场景下的一致性问题各…

作者头像 李华