FreeRTOS--任务通知方式

一.任务通知(Task Notifications)介绍

        FreeRTOS 每个已经创建的任务都有一个任务控制块( task control block),任务控制块就是一个结构体变量, 用于记录任务的相关信息。 结构体变量中有一个 32 位的变量成员 ulNotifiedValue 是专门用于任务通知的。通过任务通知方式可以实现计数信号量二值信号量事件标志组消息邮箱(消息邮箱就是消息队列长度为 1 的情况)。

        任务通知方式实现的计数信号量, 二值信号量,事件标志组和消息邮箱是通过修改变量ulNotifiedValue 实现的:

 设置接收任务控制块中的变量 ulNotifiedValue 可以实现消息邮箱。

 如果接收任务控制块中的变量 ulNotifiedValue 还没有被其接收到, 也可以用新数据覆盖原有数据, 这就是覆盖方式的消息邮箱。

 设置接收任务控制块中的变量 ulNotifiedValue 的 bit0-bit31 数值可以实现事件标志组。

 设置接收任务控制块中的变量 ulNotifiedValue 数值进行加一或者减一操作可以实现计数信号量和二值信号量。

二、通知任务计数信号量

1.任务计数信号量概念及其作用

        FreeRTOS 计数信号量的另一种实现方式--基于任务通知( Task Notifications)的计数信号量,这里我们将这种方式实现的计数信号量称之为任务计数信号量。 任务计数信号量效率更高,需要的 RAM 空间更小。实际项目中,如果使用计数信号量和任务计数信号量都能实现相应功能,强烈建议使用任务计数信号量

2.任务计数信号量 API 函数

1)函数 xTaskNotifyGive 用于任务中释放信号量( 含任务二值信号量, 任务计数信号量)

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); /* 任务句柄 */ 

返回 :pdPASS 

注意:此函数用于任务代码中调用,不可在中断服务程序中调用!!!

 2)函数 vTaskNotifyGiveFromISR用于中断中释放信号量(含任务二值信号量, 任务计数信号量)

void vTaskNotifyGiveFromISR(

            TaskHandle_t xTaskToNotify, /* 任务句柄 */

            BaseType_t *pxHigherPriorityTaskWoken ); /* 高优先级任务是否被唤醒的状态保存 */

 3)函数 ulTaskNotifyTake 从调用任务的任务控制块中检索通知值,并可选地清除该值

uint32_t ulTaskNotifyTake(

        BaseType_t xClearCountOnExit, /* 选择是否清零用于任务通知的 ulNotifiedValue */

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

参数:

xClearCountOnExit  如果收到 RTOS 任务通知且 xClearCountOnExit 设置为 pdFALSE,则 RTOS 任务的通知值 在 ulTaskNotifyTake() 退出之前递减。 这 等同于 通过成功调用 xSemaphoreTake() 而递减计数信号量的值。

如果收到 RTOS 任务通知且 xClearCountOnExit 设置为 pdTRUE,则 RTOS 任务的通知值 在 ulTaskNotifyTake() 退出之前重设为 0。 这 等同于在成功调用 xSemaphoreTake() 后 将二进制信号量的值保留为 0 (或为空,或为“不可用” )。

xTicksToWait  在阻塞状态下等待接收通知的最长时间, 如果通知在 ulTaskNotifyTake() 被调用时 尚未挂起。

处于阻塞状态的 RTOS 任务不会消耗 任何 CPU 时间。

时间以 RTOS tick 周期为单位。 宏 pdMS_TO_TICKS() 可以 将以毫秒为单位的时间 转换为以 tick 为单位的时间。

 返回:被递减或清除之前的任务通知值的值

三、通知任务二值信号量

1、二值信号量的概念及其作用

        多次调用函数 xTaskNotifyGive ()难免会出现计数值大于 1 的情况,用作任务二值信号量时,我们可以将所有大于 1 的计数理解为一种情况,即二值信号量管理的资源可用。因此, 不管当前的计数是多少,大于 0 的计数在通过函数 ulTaskNotifyTake()获取二值信号量的时候统一清零,这样就实现了二值信号量的功能。实际项目中,如果使用二值信号量和任务二值信号量都能实现相应功能,强烈建议使用任务二值信号量

2.任务二值信号量 API 函数

        函数以及用法与任务计数信号量基本相同。

四、任务事件标志组

1、任务事件标志组的概念及其作用

        任务事件标志组与事件标志组要实现的功能是一样的, 不同的是调用的函数和支持的事件标志个数, 任务事件标志组支持 32 个事件标志设置, 事件标志组,每创建一个支持 24 个事件标志设置。实际项目中,如果使用事件标志组和任务事件标志组都能实现相应功能,强烈建议使用任务事件标志组

2、任务事件标志组 API 函数

1)函数 xTaskNotify
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, /* 任务句柄 */uint32_t ulValue,           /* 更新任务控制块中的变量 ulNotifiedValue */eNotifyAction eAction );   /* 任务通知模式设置 */

参数:

xTaskToNotify  正在通知的 RTOS 任务的句柄。 
ulValue  用于更新目标任务的通知值。 请参阅下面 eAction 参数的说明。
eAction  一种枚举类型,可以采用 下表中记录的值之一来执行相关操作。
eAction 设置已执行的操作
eNoAction目标任务接收事件,但其 通知值未更新。 在这种情况下,不使用 ulValue。

eSetBits目标任务的通知值 使用 ulValue 按位或运算。 例如, 如果 ulValue 设置为 0x01,则将在 目标任务的通知值中设置位 0。 同样,如果 ulValue 为 0x04,则将在 目标任务的通知值中设置位 2。 通过这种方式,RTOS 任务通知机制 可以用作 事件组的轻量级替代方案。

eIncrement目标任务的通知值 自增 1,使得调用 xTaskNotify() 相当于调用 xTaskNotifyGive()。 在这种情况下,不使用 ulValue。
eSetValueWithOverwrite目标任务的通知值 无条件设置为 ulValue。 因此, RTOS 任务通知机制可用作 xQueueOverwrite() 的轻量级替代方案。
eSetValueWithoutOrwrite如果目标任务没有 挂起的通知,则其通知值 将设置为 ulValue。

如果目标任务已经有 挂起的通知,则不会更新其通知值, 因为这样做会覆盖 之前使用的值。 在这种情况下, 调用 xTaskNotify() 失败,返回 pdFALSE。

因此,RTOS 任务通知机制可 在长度为 1 的队列上用作 xQueueSend() 在长度为 的轻量级替代方案。

返回:

        除了 eAction 被设置为 eSetValueWithoutOverwrite 且目标任务的通知值 因目标任务已有挂起的通知而无法更新之外, 在所有情况下均返回 pdPASS

        函数 xTaskNotify 通过设置任务控制块中的变量 ulNotifiedValue 可以在任务代码中实现任务事件标志组,任务计数信号量, 任务消息邮箱和任务二值信号量四种方式的消息通知。

2)函数 xTaskNotifyFromISR   
BaseType_t xTaskNotifyFromISR( 
TaskHandle_t xTaskToNotify,              /* 任务句柄 */
uint32_t ulValue,                        /* 更新任务控制块中的变量 ulNotifiedValue */
eNotifyAction eAction,                   /* 任务通知模式设置 */
BaseType_t *pxHigherPriorityTaskWoken ); /* 高优先级任务是否被唤醒的状态保存 */

        函数 xTaskNotifyFromISR 通过设置任务控制块中的变量 ulNotifiedValue 可以在中断服务程序中实现任务事件标志组,任务计数信号量, 任务消息邮箱和任务二值信号量四种方式的消息通知。

3)函数 xTaskNotifyWait

        函数 xTaskNotifyWait 可以在任务代码中实现任务事件标志组,任务计数信号量, 任务消息邮箱和任务二值信号量四种方式的消息获取。

BaseType_t xTaskNotifyWait(
/* 设置函数执行前清零任务控制块中变量 ulNotifiedValue 那些位 */
uint32_t ulBitsToClearOnEntry,
/*设置函数退出前清零任务控制块中变量 ulNotifiedValue 那些位 */
uint32_t ulBitsToClearOnExit,
/* 保存任务控制块中的变量 ulNotifiedValue 到指针变量 pulNotifiedValue 所指向的存储单元 */
uint32_t *pulNotificationValue,
/* 等待消息通知的最大等待时间 */
TickType_t xTicksToWait );

参数:

ulBitsToClearOnEntry  在 xTaskNotifyWait() 函数入口ulBitsToClearOnEntry 中设置的任何位都将在调用 RTOS 任务通知值中 被清除(在任务等待新通知之前), 前提是在调用 xTaskNotifyWait() 时通知尚未 挂起。

例如,如果 ulBitsToClearOnEntry 为 0x01, 则任务通知值的位 0 将在函数入口 被清除。

将 ulBitsToClearOnEntry 设置为 0xffffffff (ULONG_MAX) 将 清除任务通知值中的所有位,有效 将值清除为 0。

ulBitsToClearOnExit  在 xTaskNotifyWait() 函数退出之前, ulBitsToClearOnExit 中设置的任何位都将在调用 RTOS 任务通知值中 被清除,前提是接收到通知。

在 RTOS 任务通知值保存到 *pulNotificationValue 中 之后清除位 (请参阅下面的 pulNotificationValue 的说明)。

例如,如果 ulBitsToClearOnExit 为 0x03,则位 0 和 位 1 将在函数退出之前 清除。

将 ulBitsToClearOnExit 设置为 0xffffffff (ULONG_MAX) 将 清除任务通知值中的所有位,有效 将值清除为 0。

pulNotificationValue  用于传出 RTOS 任务的通知值。 在由于 ulBitsToClearOnExit 的设置清除任何位之前,复制到 *pulNotificationValue 的值是 RTOS 任务的 通知值 。

如果不需要通知值,则设置 pulNotificationValue 为 NULL。

xTicksToWait  在阻塞状态下等待接收通知的最长时间, 前提是在调用 xTaskNotifyWait() 时通知尚未 挂起。

处于阻塞状态的 RTOS 任务不会消耗 任何 CPU 时间。

时间以 RTOS tick 周期为单位。 宏 pdMS_TO_TICKS() 可以 将以毫秒为单位的时间 转换为以 tick 为单位的时间。

返回:

在调用 xTaskNotifyWait() 时,如果收到通知, 或通知已经挂起,则返回 pdTRUE。

如果调用 xTaskNotifyWait() 在收到通知之前超时, 则返回 pdFALSE。

 五、任务消息邮箱

1、任务消息邮箱的概念及其作用

        我们将消息队列( 消息队列长度固定为 1) 称之为任务消息邮箱。 这种方式实现的消息队列效率更高,需要的 RAM 空间更小。任务消息邮箱是通过任务控制块中的一个 32 位变量 ulNotifiedValue 对数据进行存取;实际项目中,如果使用任务消息邮箱和消息队列都能实现相应功能,强烈建议使用任务消息邮箱

2、任务消息邮箱使用的API与上面相同,参数设置用法不同

1)覆盖方式 xTaskNotify 第三个参数使用 eSetValueWithOverwrite 

2)非覆盖方式 xTaskNotify 第三个参数使用 eSetValueWithoutOverwrite 

六、测试例程

https://gitee.com/hutaooooooo/git_keil/tree/master/freetos_xTaskNotifyCreate

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

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

相关文章

分割链表----一道题目的3种不同的解法

1.题目概述 以这个题目的事例作为例子,我们看一下这个题目到底是什么意思(Leedcode好多小伙伴说看不懂题目是什么意思),就是比如一个x3,经过我们的程序执行之后;大于3的在这个链表的后面,小于3的…

Qt5 框架学习及应用 — 对象树

Qt 对象树 对象树概念Qt为什么使用对象树 ?将对象挂到对象树上 对象树概念 对象树:对于树的概念,相信许多学过数据结构的同学应该都不会陌生。在学习数据结构的时候我们所接触的什么二叉树、多叉树、哈夫曼树、AVL树、再到红黑树、B/B树………

java之web笔记

1.Servlet技术 1.1 JavaWeb概述 在Sun的Java Servlet规范中,对Java Web应用作了这样定义:“JavaWeb应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的Servlet容器中运行。 Java Web应用中可以包含如下内容…

STM32——GPIO篇

技术笔记! 1. 什么是GPIO? GPIO是通用输入输出端口(General-purpose input/output)的英文简写,是所有的微控制器必不可少的外设之一,可以由STM32直接驱动从而实现与外部设备通信、控制以及采集和捕获的功…

数据库和缓存一致性问题

hello,各位小伙伴们大家好,我是颜书凌,下面给大家讲解一下数据库和缓存的一致性问题,话不多说 1、一致性介绍 一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。 强一致性…

基于vmware虚拟机中yum源的配置

1.首先需确保虚拟机中已经连接了光盘映像(如图在虚拟机右下方从左往右第二个) 2.在虚拟机中找到光盘映像文件(默认在/dev的sr0) 3.将光盘文件挂载(挂载后才可读取) 为方便每一次开机之后自动挂载&#xff…

类和对象【四】运算符重载

文章目录 运算符重载的概念运算符重载(函数)返回值类型:任意类型函数名:operator已有操作符 运算符重载(函数)的特点和注意点3个比较特殊的运算符重载赋值运算符()重载返回值类型和返…

未来科技的前沿:深入探讨人工智能的进展、机器学习技术和未来趋势

文章目录 一、人工智能的定义和概述1. 人工智能的基本概念2. 人工智能的发展历史 二、技术深入:机器学习、深度学习和神经网络1. 机器学习2. 深度学习3. 神经网络 三、人工智能的主要目标和功能1. 自动化和效率提升2. 决策支持和风险管理3. 个性化服务和预测未来 本…

vulnhub靶场之FunBox-2

一.环境搭建 1.靶场描述 Boot2Root ! This can be a real life scenario if rockies becomes admins. Easy going in round about 15 mins. Bit more, if you are find and stuck in the rabbit-hole first. This VM is created/tested with Virtualbox. Maybe it works with…

【tcl脚本实践Demo 1】文本生成、匹配、修改、读写

引言 在芯片设计的流程中,各种EDA工具在设计、综合、布局布线、验证、时序分析等等环节都会产出大量的文件信息。这些信息是海量的,如果单纯靠程序员自己查看信息效率很低并且很容易纰漏。所以脚本语言可以很好的解决这个问题,可以利用脚本语言匹配到敏感的信息,完成对信息…

WindowSurfaceController method call stacktrace

WindowSurfaceController: prepareToShowInTransaction showRobustly

python判断大图中包含小图并输出位置总结

python判断大图中包含小图并输出位置总结 没啥可说的,项目遇到了就直接上代码,可以减轻劳动力,花最少得时间实现应用功能。 import cv2 # 读取大图片和小图片的路径 img_big cv2.imread(big_image.png) img_small cv2.imread(small_image…

华为手机 鸿蒙系统-android studio识别调试设备,开启adb调试权限

1.进入设置-关于手机-版本号,连续点击7次 认证:有锁屏密码需要输入密码, 开启开发者配置功能ok 进入开发者配置界面 打开调试功能 重新在androd studio查看可运行running devices显示了, 不行的话,重启一下android …

AI诗歌创作

诗歌作为一种文学形式,能够通过优美的语言和深刻的意境表达情感和思想,触动人心,引发共鸣。然而,如今随着生活节奏的加快和人们对实用性的追求,写诗这一传统艺术渐渐被人们所忽略。幸运的是,随着人工智能技…

一本通-1225:金银岛

【题目描述】 某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同…

Spring Cloud Feign

序言 本文给大家介绍一下 Spring Cloud Feign 的基础概念以及使用方式。 一、远程调用 在传统的单体系统中,我们通常是客户端去请求服务端的接口。但是在分布式的系统中,常常需要一个服务去调用另外一个服务的接口。在服务端如何去调用另外一个服务端…

搭建MongoDB副本集

文章目录 一、什么是MongoDB的副本集二、副本集的架构三、副本集的成员四、部署副本集1、节点划分2、安装MongoDB2.1、下载解压安装包 3、创建主节点3.1、创建存储数据和日志的目录3.2、新建配置文件3.3、启动节点服务 4、创建副本节点4.1、创建存储数据和日志的目录4.2、新建配…

普通电机与变频电机区别

普通电机和变频电机之间的区别: 1. 设计和构造: - 普通电机:设计用于在恒定的电源频率和电压下工作,通常具有固定的转速和功率。 - 变频电机:专门设计用于与变频器配合使用,能够在变化的频率和电压下运行&…

大模型公开可用的模型检查点或 API

文章目录 公开可用的模型检查点或 APILLaMA 变体系列大语言模型的公共 API 公开可用的模型检查点或 API 众所周知,大模型预训练是一项对计算资源要求极高的任务。因此,经过预训练的公开模型检查点(Model Checkpoint)对于推动大语言…

精简函数栈帧:优化创建和销毁过程的完全解析(建议收藏,提升内功)

🌈个人主页:是店小二呀 🌈C语言笔记专栏:C语言笔记 🌈C笔记专栏: C笔记 🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 【前文】一、函数栈帧的概念(stack frame&#xff…