[FreeRTOS 内部实现] 任务通知


一、基础知识

[FreeRTOS 基础知识] 任务通知 概念
[FreeRTOS 内部实现] 创建任务 xTaskCreate函数解析


二、内部机制解析

任务通知结构体

每个任务都会有个TCB结构体,该结构体保存任务的状态。
这个结构体中有两个成员用于任务通知使用。如下图:(结构体还有其他成员,这里省略)

typedef struct tskTaskControlBlock
{
	#if( configUSE_TASK_NOTIFICATIONS == 1 )
		volatile uint32_t ulNotifiedValue;		
		volatile uint8_t ucNotifyState;
	#endif
} tskTCB;

ulNotifiedValue成员 保存该任务通知的值
ucNotifyState成员 保存任务通知的状态

任务通知状态有三种:
taskNOT_WAITING_NOTIFICATION:任务没有在等待通知。
taskWAITING_NOTIFICATION:任务正在等待通知。
taskNOTIFICATION_RECEIVED:任务已经接收到通知。

发送通知函数 xTaskNotify

xTaskNotify(): 向指定任务发送通知,并可选择如何更新接收任务的通知值。

#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL )
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )

参数解析:
TaskHandle_t xTaskToNotify : 目标任务句柄
uint32_t ulValue : 通知值
eNotifyAction eAction :更新方式,包括通知事件不去更新通知值;设置通知值的位;通知值递增;覆盖通知值操作
uint32_t *pulPreviousNotificationValue:更改前的通知值

typedef enum
{
	eNoAction = 0,				/* Notify the task without updating its notify value. */
	eSetBits,					/* Set bits in the task's notification value. */
	eIncrement,					/* Increment the task's notification value. */
	eSetValueWithOverwrite,		/* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */
	eSetValueWithoutOverwrite	/* Set the task's notification value if the previous value has been read by the task. */
} eNotifyAction;

函数内部解析:

BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
	// 1、从参数中获取目标任务TCB结构体
	-> pxTCB = ( TCB_t * ) xTaskToNotify;
	// 2、判断是否返回更新前的通知值
	-> 	if( pulPreviousNotificationValue != NULL )
			*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
	// 3、记录更新前通知状态,并初始化状态
	-> ucOriginalNotifyState = pxTCB->ucNotifyState;
	-> pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
	// 4、根据传入的更新方式参数,决定通知值的变化
	switch( eAction )
	{
		case eSetBits	:
			pxTCB->ulNotifiedValue |= ulValue;
			break;

		case eIncrement	:
			( pxTCB->ulNotifiedValue )++;
			break;

		case eSetValueWithOverwrite	:
			pxTCB->ulNotifiedValue = ulValue;
			break;

		case eSetValueWithoutOverwrite :
			if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
			{
				pxTCB->ulNotifiedValue = ulValue;
			}
			else
			{
				xReturn = pdFAIL;
			}
			break;

		case eNoAction:
			break;
	}
	// 5、如果之前的链表状态是等待
	-> if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
		// (1)从xStateListItem 移除
		( void ) uxListRemove( &( pxTCB->xStateListItem ) );
		// (2)添加到ReadyList
		prvAddTaskToReadyList( pxTCB );

任务通知等待 xTaskNotifyWait

xTaskNotifyWait(): 允许任务等待接收通知,并可以设置在进入和退出时要清零的通知比特位。

BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )

参数解析:
uint32_t ulBitsToClearOnEntry :在函数的入口处,清除哪些位
uint32_t ulBitsToClearOnExit : 在函数的出口处,清除哪些位
uint32_t *pulNotificationValue:用来保存读出的数据
TickType_t xTicksToWait:等待数据时间

函数内部解析:

BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
	->	taskENTER_CRITICAL();	// 关中断
	// 判断当前的任务状态不为taskNOTIFICATION_RECEIVED ,表示说任务现在还没有接收到通知
	-> if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
	   {
	   		pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;		// 把相应的位清零
	   		pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;		// 将标志位设置为等待状态				
	   		// 如果任务需要等待的话,
	   		if( xTicksToWait > ( TickType_t ) 0 )
			{
				// 将当前任务添加到delay链表
				prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
				traceTASK_NOTIFY_WAIT_BLOCK();
			}
		}
	// 任务被唤醒后
	// 任务通知的value值返回
	*pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
	// 如果任务状态不为taskNOTIFICATION_RECEIVED 模式,则返回false
	if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
		xReturn = pdFALSE;
	else
	{
		// 将任务通知值value值清零,返回true
		pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
		xReturn = pdTRUE;
	}
	// 将任务通知改为 不等待通知状态
	pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;

小结:
在这里插入图片描述

相关推荐

  1. FreeRTOS任务通知

    2024-07-13 11:24:04       57 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-13 11:24:04       50 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-13 11:24:04       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-13 11:24:04       43 阅读
  4. Python语言-面向对象

    2024-07-13 11:24:04       54 阅读

热门阅读

  1. prompt第四讲-fewshot

    2024-07-13 11:24:04       17 阅读
  2. Netty Websocket SpringBoot Starter

    2024-07-13 11:24:04       20 阅读
  3. 第五十五章 生成的 WSDL 的详细信息 - types

    2024-07-13 11:24:04       17 阅读
  4. 开发指南044-切片编程

    2024-07-13 11:24:04       23 阅读
  5. 触发器练习

    2024-07-13 11:24:04       19 阅读
  6. Flutter框架时间线梳理

    2024-07-13 11:24:04       23 阅读
  7. ubuntu wifi ap

    2024-07-13 11:24:04       22 阅读
  8. 基于Hadoop的区块链海量数据存储的设计与实现

    2024-07-13 11:24:04       22 阅读
  9. 编程题-栈,链栈

    2024-07-13 11:24:04       18 阅读