FreeRTOS任务通知

FreeRTOS任务通知

FreeRTOS 新增了任务通知(Task Notifictions)这个功能,可以使用任务通知来代替信号量、消息队列、事件标志组等这些东西。使用任务通知的话效率会更高,任务通知在 FreeRTOS 中是一个可选的功能,
使用队列、信号量、事件标志组时都需另外创建一个结构体,通过中间的结构体进行间接通信!过程如下图所示:

在这里插入图片描述
要使用任务通知的话就需要将宏configUSE_TASK_NOTIFICATIONS 定义为 1。FreeRTOS 的每个任务都有一个 32 位的通知值,任务控制块中的成员变量 ulNotifiedValue就是这个通知值。过程如下图所示:
在这里插入图片描述

任务通知是一个事件,假如某个任务通知的接收任务因为等待任务通知而阻塞的话,向这个接收任务发送任务通知以后就会解除这个任务的阻塞状态。也可以更新接收任务的任务通知值,任务通知可以通过如下方法更新接收任务的通知值:
不覆盖接收任务的通知值(如果上次发送给接收任务的通知还没被处理)。
覆盖接收任务的通知值。
更新接收任务通知值的一个或多个 bit
增加接收任务的通知值
所以根据以上四种情况可以在一些情况下合理替代队列、二值信号量、计数型信号量、事件标志组。任务通知虽然可以提高速度,并且减少RAM的使用,并且任务通知是有使用限制的:
1:RTOS的任务通知只能有一个接收任务。
2:接收任务可以因为接受任务通知而进入阻塞态,但是发送任务不会因为任务通知发送失败而阻塞。
在这里插入图片描述

在这里插入图片描述
上图为任务结构体存储的部分内容,从上图我们可以RTOS中默认数组的大小就是1,也可以看到一个是 uint32_t 类型,用来表示通知值,一个是 uint8_t 类型,用来表示通知状态。

任务通知值

任务通知值的更新方式有多种类型:
1 计数值(数值累加,类似与信号量)
2 相应位置1(类似事件标志组)
3 任意数值(支持覆写和不覆写,类似队列)

任务通知状态

在这里插入图片描述在这里插入图片描述

任务通知发送函数

任务通知发送函数有以下6个:
在这里插入图片描述
此函数用于发送任务通知,此函数发送任务通知的时候带有通知值,此函数是个宏,真正执行的函数

xTaskGenericNotify()

函数原型如下:

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction )
xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。
ulValue: 任务通知值。
eAction: 任务通知更新的方法,eNotifyAction 是个枚举类型,在文件 task.h 中有如下定义:
返回值: 
pdFAIL: 当参数 eAction 设置为 eSetValueWithoutOverwrite 的时候,如果任务通知值没有
更新成功就返回 pdFAIL。
pdPASS: eAction 设置为其他选项的时候统一返回 pdPASS。

eAction如下图枚举的类型一样,依次为:
eSetBits更新指定的Bit,eIncrement通知值加1,eSetValueWithOverwrite,覆写的方式更新通知值。
eSetValueWithoutOverwrite,不覆写通知值。
在这里插入图片描述

函数 xTaskNotifyFromISR()

此函数用于发送任务通知,是函数 xTaskNotify()的中断版本,此函数是个宏,真正执行的是函数 xTaskGenericNotifyFromISR(),此函数原型如下:

BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, 
BaseType_t * pxHigherPriorityTaskWoken );
参数:
xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。
ulValue: 任务通知值。
eAction: 任务通知更新的方法。
pxHigherPriorityTaskWoken: 记退出此函数以后是否进行任务切换,这个变量的值函数会自动设置的,用户不用
进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退出中断服务
函数之前一定要进行一次任务切换。
返回值: 
pdFAIL: 当参数 eAction 设置为 eSetValueWithoutOverwrite 的时候,如果任务通知值没有
更新成功就返回 pdFAIL。
pdPASS: eAction 设置为其他选项的时候统一返回 pdPASS。

函数 xTaskNotifyGive()

发送任务通知,相对于函数 xTaskNotify(),此函数发送任务通知的时候不带有通知值。此
函数只是将任务通知值简单的加一,此函数是个宏,真正执行的是函数 xTaskGenericNotify(),
此函数原型如下:

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
参数:
xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。
返回值: 
pdPASS: 此函数只会返回 pdPASS。

函数 vTaskNotifyGiveFromISR()

此函数为 xTaskNotifyGive()的中断版本,用在中断服务函数中,函数原型如下:

void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t * pxHigherPriorityTaskWoken );
参数:
xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。
pxHigherPriorityTaskWoken: 记退出此函数以后是否进行任务切换,这个变量的值函数会自动
设置的,用户不用进行设置,用户只需要提供一个变量来保存这
个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之
前一定要进行一次任务切换。
返回值: 
无。

函数 xTaskNotifyAndQuery()

此函数和 xTaskNotify()很类似,此函数比 xTaskNotify()多一个参数,此参数用来保存更新
前的通知值。此函数是个宏,真正执行的是函数 xTaskGenericNotify(),此函数原型如下:

BaseType_t xTaskNotifyAndQuery ( TaskHandle_t xTaskToNotify, 
uint32_t ulValue, 
eNotifyAction eAction 
uint32_t * pulPreviousNotificationValue);
参数:
xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。
ulValue: 任务通知值。
eAction: 任务通知更新的方法。
pulPreviousNotificationValue:用来保存更新前的任务通知值。
返回值: 
pdFAIL: 当参数 eAction 设置为 eSetValueWithoutOverwrite 的时候,如果任务通知值没有
更新成功就返回 pdFAIL。
pdPASS: eAction 设置为其他选项的时候统一返回 pdPASS。

函数 xTaskNotifyAndQueryFromISR()

此函数为 xTaskNorityAndQuery()的中断版本,用在中断服务函数中。此函数同样为宏,真
正执行的是函数 xTaskGenericNotifyFromISR(),此函数的原型如下:

BaseType_t xTaskNotifyAndQueryFromISR ( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t * pulPreviousNotificationValueBaseType_t * pxHigherPriorityTaskWoken );
参数:
xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。
ulValue: 任务通知值。
eAction: 任务通知更新的方法。
pulPreviousNotificationValue:用来保存更新前的任务通知值。
pxHigherPriorityTaskWoken: 记退出此函数以后是否进行任务切换,这个变量的值函数会自动设置的,
用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之
前一定要进行一次任务切换。
返回值: 
pdFAIL: 当参数 eAction 设置为 eSetValueWithoutOverwrite 的时候,如果任务通知值没有
更新成功就返回 pdFAIL。
pdPASS: eAction 设置为其他选项的时候统一返回 pdPASS。

任务通知通用发送函数源码

任务级任务通知通用发送函数在上面中有3 个任务级任务通知发送函数:xTaskNotify()、xTaskNotifyGive()
和 xTaskNotifyAndQuery(),这三个函数最终调用的都是函数 xTaskGenericNotify()!此函数在文件 tasks.c 中有如下定义,缩减后的函数如下:

BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, //任务句柄uint32_t ulValue, //任务通知值eNotifyAction eAction, //任务通知更新方式uint32_t * pulPreviousNotificationValue )//保存更新前的//任务通知值
{TCB_t * pxTCB;BaseType_t xReturn = pdPASS;uint8_t ucOriginalNotifyState;configASSERT( xTaskToNotify );pxTCB = ( TCB_t * ) xTaskToNotify;taskENTER_CRITICAL();{if( pulPreviousNotificationValue != NULL ) (1){//如果提供了一个非NULL指针来接收更新前的通知值,则将当前的通知值保存到该位置*pulPreviousNotificationValue = pxTCB->ulNotifiedValue; (2)}//保存任务通知状态,因为下面会修改这个状态,//后面我们要根据这个状态来确定是否将任务从阻塞态解除。ucOriginalNotifyState = pxTCB->ucNotifyState; (3)pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; (4)switch( eAction ){case eSetBits : (5)pxTCB->ulNotifiedValue |= ulValue;break;case eIncrement : (6)( pxTCB->ulNotifiedValue )++;break;case eSetValueWithOverwrite: (7)pxTCB->ulNotifiedValue = ulValue;break;case eSetValueWithoutOverwrite : (8)if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ){pxTCB->ulNotifiedValue = ulValue;}else{xReturn = pdFAIL;}break;case eNoAction:break;}traceTASK_NOTIFY();//如果任务因为等待任务通知而进入阻塞态的话就需要解除阻塞if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) (9){( void ) uxListRemove( &( pxTCB->xStateListItem ) ); (10)prvAddTaskToReadyList( pxTCB ); (11)/******************************************************************//********************省略相关的条件编译代码************************//******************************************************************/if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) (12){//解除阻塞的任务优先级比当前运行的任务优先级高,所以需要进行//任务切换。taskYIELD_IF_USING_PREEMPTION();}else{mtCOVERAGE_TEST_MARKER();}}else{mtCOVERAGE_TEST_MARKER();}}taskEXIT_CRITICAL();return xReturn; (13)
}

中断级任务通知发送函数

中 断 级 任 务 通 知 发 送 函 数 也 有 三 个 , 分 别 为 : xTaskNotifyFromISR() 、
xTaskNotifyAndQueryFromISR()和 vTaskNotifyGiveFromISR()。其中函数 xTaskNotifyFromISR()
和 xTaskNotifyAndQueryFromISR()最终调用的都是函数 xTaskGenericNotifyFromISR(),此函数
的原型如下:

BaseType_t xTaskGenericNotifyFromISR( 	TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t * pulPreviousNotificationValue, BaseType_t * pxHigherPriorityTaskWoken )参数:
xTaskToNotify: 任务句柄,指定任务通知是发送给哪个任务的。
ulValue: 任务通知值。
eAction: 任务通知更新的方法。
pulPreviousNotificationValue:用来保存更新前的任务通知值。
pxHigherPriorityTaskWoken: 记退出此函数以后是否进行任务切换,这个变量的值函数会自动
设置的,用户不用进行设置,用户只需要提供一个变量来保存这
个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之
前一定要进行一次任务切换。
返回值: 
pdFAIL: 当参数 eAction 设置为 eSetValueWithoutOverwrite 的时候,如果任务通知值没有
更新成功就返回 pdFAIL。
pdPASS: eAction 设置为其他选项的时候统一返回 pdPASS。

获取任务通知

获取任务通知的函数有两个:

ulTaskNotifyTake()获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减一。
当任务通知用作二值信号量或者计数信号量的时候使用此函数来获取信号量。
xTaskNotifyWait()等待任务通知,比 ulTaskNotifyTak()更为强大,全功能版任务通
知获取函数。

函数 ulTaskNotifyTake()

此函数为获取任务通知函数,当任务通知用作二值信号量或者计数型信号量的时候可以使
用此函数来获取信号量,函数原型如下:

uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
参数:
xClearCountOnExit: 参数为 pdFALSE 的话在退出函数 ulTaskNotifyTake()的时候任务通知值
减一,类似计数型信号量。当此参数为 pdTRUE 的话在退出函数的时候
任务任务通知值清零,类似二值信号量。
xTickToWait: 阻塞时间。
返回值:
任何值 : 任务通知值减少或者清零之前的值。

函数 xTaskNotifyWait()

此函数也是用来获取任务通知的,不过此函数比 ulTaskNotifyTake()更为强大,不管任务通知用作二值信号量、计数型信号量、队列和事件标志组中的哪一种,都可以使用此函数来获取任务通知。但是当任务通知用作位置信号量和计数型信号量的时候推荐使用函数ulTaskNotifyTake()。此函数原型如下:

BaseType_t xTaskNotifyWait(  uint32_t ulBitsToClearOnEntry,uint32_t ulBitsToClearOnExit, uint32_t * pulNotificationValue, TickType_t xTicksToWait );参数:
ulBitsToClearOnEntry:当没有接收到任务通知的时候将任务通知值与此参数的取反值进行按
位与运算,当此参数为 0xffffffff 或者 ULONG_MAX 的时候就会将任务
通知值清零。
ulBitsToClearOnExit:如果接收到了任务通知,在做完相应的处理退出函数之前将任务通知值
与此参数的取反值进行按位与运算,当此参数为 0xffffffff 或者ULONG_MAX 的时候就会将任务通知值清零。
pulNotificationValue:此参数用来保存任务通知值。
xTickToWait: 阻塞时间。
返回值:
pdTRUE: 获取到了任务通知。
pdFALSE: 任务通知获取失败。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Facebook的语言学:社交媒体如何影响我们的沟通方式

1. 引言 社交媒体已经成为人们日常生活中不可或缺的一部分,而Facebook作为其中最具影响力的平台之一,不仅改变了人们之间的社交方式,也对我们的语言学产生了深远的影响。本文将深入探讨Facebook的语言学特点,以及它如何塑造和改变…

C++面经(简洁版)

1. 谈谈C和C的认识 C在C的基础上添加类,C是一种结构化语言,它的重点在于数据结构和算法。C语言的设计首要考虑的是如何通过一个过程,对输入进行运算处理得到输出,而对C,首先要考虑的是如何构造一个对象,通…

2-手工sql注入(进阶篇) sqlilabs靶场1-4题

1. 阅读,学习本章前,可以先去看看基础篇:1-手工sql注入(基础篇)-CSDN博客 2. 本章通过对sqlilabs靶场的实战,关于sqlilabs靶场的搭建:Linux搭建靶场-CSDN博客 3. 本章会使用到sqlmap,关于sqlmap的命令&…

stm32f103zet6_串口实现-DHT11-tim1(定时)

1思路 1打开时钟 1.1使用定时器实现us级的计时 1.2在打开串口 1,3在DHT11驱动中修改引脚 stm32cudeMX 配置 1打开时钟 2打开串口 3打开tim1(定时器) 4生成代码 代码设置 1导入DHT11库(tim.h是定时器的文件系统自动生成的) DHT11.c #include "dht11.h" #inc…

PHP算命源码_最新测算塔罗源码_可以运营

功能介绍 八字精批、事业财运、姓名分析、宝宝起名、公司测名、姓名配对、综合详批、姻缘测算、牛年感情、PC版测算、八字合婚、紫微斗数、鼠年运程、月老姻缘、许愿祈福、号码解析、塔罗运势、脱单占卜、感情继续、脱单占卜、塔罗爱情、心理有你、能否复合、暗恋对象、是否分…

5.3 进程间通信管道和共享内存

每次打开一个网页都是一个进程 进行管道之间通信的方式:以前学到的有可以在磁盘上开辟空间进行交互,也可以在内存中开辟缓冲区进行交互。 一定注意可读性 管道就是属于在内存中的一片缓冲区,管道可以在命令行中创建管道mkfifo也可以在vim中…

java技术栈快速复习05_基础运维(linux,git)

Linux知识总览 linux可以简单的理解成和window一样的操作系统。 Linux和Windows区别 Linux是严格区分大小写的;Linux中一切皆是文件;Linux中文件是没有后缀的,但是他有一些约定俗成的后缀;Windows下的软件一般是无法直接运行的Li…

京东JD商品SKU信息API返回值解析:精准掌握商品属性

在电子商务迅猛发展的今天,商家对于商品信息的掌握和管理显得尤为重要。作为电商平台的佼佼者,京东(JD)提供了丰富的API接口,使得商家能够轻松地获取商品的详细信息,包括SKU(Stock Keeping Unit…

2024五一数学建模A题思路代码与论文分析

2024五一数学建模A题完整代码和成品论文获取↓↓↓↓↓ https://www.yuque.com/u42168770/qv6z0d/gyoz9ou5upvkv6nx?singleDoc# 2024五一数学建模A题钢板最优切割路径问题需要建立的模型和算法: 图论 最短路径算法(Dijkstra算法、Floyd算法等) 动态规划 网格化离散建模 …

【USB 3.2 Type-C】 端口实施挑战的集成解决方案 (补充一)

USB 3.2 Type-C 端口集成 补充,上一篇感觉还有没理解到位的一部分; 一、只做正反插的通信,已经差不多够了,但是这并不是完整的TYPE-C,必须要补充上PD; 参考连接: TYPE-C PD浅谈(一)https://w…

删除链表中等于给定值 val 的所有结点(三种方法深入解析)

又见面啦,接下来的链表相关Oj题目我会根据我自己的理解来给大家讲解,包括解析和代码,希望你可以对链表有更加深入的理解!! 题目: 先上链接: OJ题目 给你一个链表的头节点 head 和一个整数 va…

软件工程毕业设计选题100例

文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题,难度适中,适合作为毕业设计,大家参考。 学长整理的题目标准: 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…

计算机网络-408考研

后续更新发布在B站账号:谭同学很nice http://【计算机408备考-什么是计算机网络,有什么特点?】 https://www.bilibili.com/video/BV1qZ421J7As/?share_sourcecopy_web&vd_source58c2a80f8de74ae56281305624c60b13http://【计算机408备考…

RabbitMQ入门教学(浅入浅出)

进程间通信 互联网的通讯时网络的基础,一般情况下互联网的资源数据对储存在中心服务器上,一般情况下个体对个体的访问仅限于局域网下,在公网即可完成资源的访问,如各种网站资源,下载资源,种子等。网络通讯…

40 生产者消费者模型

生产者消费者模型 概念 为何要使用生产者消费者模型,这个是用过一个容器解决生产者和消费的强耦合问题。生产者和消费者之间不需要通讯,通过阻塞队列通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列&#xf…

用Stream流方式合并两个list集合(部分对象属性重合)

一、合并出共有部分 package com.xu.demo.test;import java.util.Arrays; import java.util.List; import java.util.stream.Collectors;public class ListMergeTest1 {public static void main(String[] args) {List<User> list1 Arrays.asList(new User(1, "Alic…

docker 基础命令

docker 安装 更新系统 sudo apt update sudo apt -y dist-upgrade安装docker sudo apt-get -y install ca-certificates curl gnupg lsb-release sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/…

【Elasticsearch】安装配置与使用

1 前期准备 1.1 环境准备 麒麟ARM 64位操作系统 1.2 安装包准备 Elasticsearch下载地址: https://www.elastic.co/cn/downloads/elasticsearch 2 部署elasticsearch 2.1 创建es专用用户 注意&#xff1a;ES不能使用root用户来启动&#xff0c;必须使用普通用户来安装启…

【HTTP上】协议/域名/url/请求和响应/状态码/重定向

文章目录 0.应用层协议0.1HTTP协议 1.域名2.DNS3.访问浏览器4.URL搜索特殊字符如#&~ 5.万维网6.http请求和响应的格式6.1HTTP请求格式6.2HTTP响应格式6.3示例6.3模拟HTTP【框架】6.4查看请求或响应的工具FiddlerPostman 7.网页7.0对访问网页的认识7.1wget7.2新的认识7.3GET…

Java将文件目录转成树结构

在实际开发中经常会遇到返回树形结构的场景&#xff0c;特别是在处理文件系统或者是文件管理系统中。下面就介绍一下怎么将文件路径转成需要的树形结构。 在Java中&#xff0c;将List<String>转换成树状结构&#xff0c;需要定义一个树节点类&#xff08;TreeNode&#…