首页 > 其他分享 >FreeRTOS任务通知

FreeRTOS任务通知

时间:2024-05-03 20:23:45浏览次数:25  
标签:eAction 函数 FreeRTOS 通知 xTaskToNotify 信号量 任务

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 * pulPreviousNotificationValue
										BaseType_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: 任务通知获取失败。

标签:eAction,函数,FreeRTOS,通知,xTaskToNotify,信号量,任务
From: https://www.cnblogs.com/bathwind/p/18171561

相关文章

  • FreeRTOS 事件标志组
    FreeRTOS事件标志组使用信号量来完成同步,但是使用信号量来同步的话任务只能与单个的事件或任务进行同步。有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了。事件位用来表明某个事件是否发生,事件位通常用作事件标志,事件标志组是一组事件标志位的集合,......
  • PowerShell 开启 Windows 防火墙并设置阻止程序接收入站连接时向用户显示通知,可以执行
    PowerShell开启Windows防火墙并设置阻止程序接收入站连接时向用户显示通知,可以执行以下命令:powershellCopyCodeSet-NetFirewallProfile-ProfileDomain,Public,Private-DefaultInboundActionBlock-NotifyOnDefaultInboundAction$true这条命令将设置防火墙配置文件......
  • 模拟微任务 判断是否有对应的api
    if(typeofPromise!=='undefined'&&isNative(Promise)){}functionrunMicrotask(func){if(typeofPromise==='function'){Promise.resolve().then(func)return}if(typeofMutationObserver==='functi......
  • 算法训练优化的经验:深入任务与数据的力量
    引言在算法优化的世界中,理解所面对的任务不仅是起点,也是整个优化过程的核心。在这篇博客中,我将分享我在算法训练和优化中的一些经验,以及一个关于场景流估计的项目中应用的案例。我希望这些经验能帮助你在未来的项目中取得更好的成绩。1.深入理解任务和数据理解算法项目的......
  • Python重试任务模块tenacity
    1.简介在实际应用中,经常会碰到在web请求时,因为网络的不稳定,会有请求超时的问题,这时候,一般都是自己去实现重试请求的逻辑,直到得到响应或者超时。虽然这样的逻辑并不复杂,但是代码写起来却不那么优雅,不那么pythonic。tenacity是一个重试库,使用python语言编写,它能够让我们在任务的重......
  • Python-重试任务模块tenacity
     1.软硬件环境windows1164bits python3.6tenacity2.简介在实际应用中,经常会碰到在web请求时,因为网络的不稳定,会有请求超时的问题,这时候,一般都是自己去实现重试请求的逻辑,直到得到响应或者超时。虽然这样的逻辑并不复杂,但是代码写起来却不那么优雅,不那么pythonic。tenaci......
  • Unity游戏框架设计之任务管理器
    Unity游戏框架设计之任务管理器简单介绍在游戏开发中,我们可能会遇到下述需求。当角色的生命值减少时,我们需要让角色播放受伤动画,让系统播放角色受伤音效,将当前的新的生命值更新到UI上等等操作。如果在角色的代码中直接实现上述的操作,则将导致代码的高度耦合,不利于后期的维护和......
  • 博客园商业化之路-开发任务众包平台:召集早期合作开发者
    园子的商业化进入关键阶段,最近在园子里和大家探索商业模式是为接下来的融资做准备,希望大家理解与支持我们采用一种开放的方式分享与探讨园子的商业化过程。到目前首选的商业模式是开发任务众包平台,详见之前发布的博文:博客园商业化之路-商业模式:帮助开发者用代码改变口袋这里的众......
  • webapi动态创建后台任务(使用排队的后台任务)
    很多时候我们都会使用后台定时任务,但有些任务不需要定时执行,只需要请求到来时执行一次,比如请求服务器到某个地方同步数据,但请求不需要等数据同步完成再响应。这时候就可以使用排队的后台任务。基本原理是用一个队列保存任务委托,然后用一个后台定时任务依次执行队列中的委托。MSD......
  • Windows编程系列:如何为任务栏设置背景
    最近在使用upupoo时,发现里面有个任务栏设置的功能,效果还不错 我试了前面为资源管理器设置背景的方法,发现不生效。大意的反编译了一下upupoo的各种dll,但是也没找到具体的实现方法(因为目前对逆向还不是很熟) 在搜索引擎搜索时,找到了OpenShell这个软件,发现里面也实现了这个功......