二十二、任务通知详解

文章介绍了任务通知的基本概念,强调其核心是关中断,主要应用于任务间的单个数据传输。与队列、信号量等内核对象不同,任务通知无需链表记录,直接指定任务进行通信,提高了效率并节省内存。然而,它存在限制,如不能用于任务和中断间通信,数据传输量小,不支持广播,且发送方无法阻塞等待。文章详细阐述了通知的三种状态以及相关API的使用方法,并解析了等待通知的任务如何实现休眠唤醒功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、基本概念(核心是关中断)

任务通知,即通知任务,可以实现任务间的数据传输,同时也和前面的内核对象一眼具备休眠唤醒功能。

2、使用场景:一个任务唤醒另一个任务(即任务间的数据传输)

这时候的数据传输有限,即一次只能传输一个数据

3、休眠唤醒功能与前面说到的内核对象的区别

任务通知与前面队列、信号量、互斥量和事件组相比,其休眠与唤醒功能不需要使用像前面使用的链表来记录,任务通知可以明确指定通知哪个任务。

而且这个休眠唤醒功能只有等待通知的任务才具备的。

即在这里没有链表来记录等待读或写的任务了,在提供的API函数中可以直接指定通知(唤醒)哪个任务。

为什么不需要这个链表来维持呢?
主要是因为任务结构体TCB中包含了内部对象,即任务的结构体里面有用于存储通知状态的变量和通知值的变量。

typedef struct tskTaskControlBlock
{
     ......
	 /* configTASK_NOTIFICATION_ARRAY_ENTRIES = 1 */
 	 volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];//用于表示通知的值
	 volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];//用于显示通知的状态
	 ......
} tskTCB;

即在队列、信号量、互斥量和事件组时,我们需要事先创建对应的结构体(队列等),双方通过这个创建的中间体来进行通信,即如下所示:
在这里插入图片描述

而这个任务通知是直接进行通信的:
在这里插入图片描述

4、优势及限制

优势:
1)效率更高:直接通信,不需要中间体来进行中继通信。
2)更节省内存:创建任务时自带内存,无须开辟新的内存来进行存储。

限制:
1)只能任务间进行通信,任务和中断间不可通信。即不能给中断发送数据。
2)数据只能该指定的任务独享:任务通知明确了通信的对象,通知的数据只能被目标对象一个使用。
3)可以传输的数据量小:即一次只能传输一个数据,不像队列等可以缓存多个数据。
4)无法进行广播:因为是直接通信,一次只能通知一个任务,不像事件组可以给多个任务同时发送事件。
5)发送方无法进行阻塞状态:即像前面说到的休眠唤醒功能只有等待通知方才具备,发送方进行任务通知的时候当对方呜啊接收数据的时候,只能立刻返回错误,不能阻塞等待。

5、通知的三种状态

前面说到的任务结构体里面的存储通知状态的变量只有三个值,即三种状态:

1)taskNOT_WAITING_NOTIFICATION:任务没有在等待通知
2)taskWAITING_NOTIFICATION:任务在等待通知
3)taskNOTIFICATION_RECEIVED:任务接收到了通知,也被称为 pending(有数据了,待处理)

##define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* 也是初始状态*/
##define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
##define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )

6、任务通知的两套函数(最好还是使用专业板的)

在这里插入图片描述

(1)API内部原理(发出和通知函数内部原理)

注意只有等待通知的任务才具备休眠唤醒功能。
在这里插入图片描述

(2)专业版

1)发出通知——xTaskNotify

需要发送的通知需要预先使用一个变量存放好,即调用这个函数的时候需要把存放了要发通知的变量作为实参。

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );

在这里插入图片描述

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

2)取出通知——xTaskNotifyWait

取出的通知放到预先定义好的变量内,即调用这个函数需要预先定义好存放通知的变量并在函数调用的时候把这个变量的地址作为实参。

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

在这里插入图片描述

(3)简化版

1)发出通知——xTaskNotifyGive

调用这个函数的时候需要把发送的通知预先放入唤醒缓冲区。
例如:
在这里插入图片描述

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );

在这里插入图片描述

2)取出通知——ulTaskNotifyTake

返回值就是去取出的通知。即通知值

uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );

在这里插入图片描述

7、等待通知的任务休眠唤醒功能的原理

在这里插入图片描述
例如下面图中的两个例子:
1)左边发送方先发了数据,接收方是在已经接收到数据的前提下直接取出了数据。
2)右边是接收方在等待数据(即此时发送方还没开始发送),直到发送方进行任务通知后接收方就被唤醒然后取出通知。
记住成功取出数据后会将通知状态值复位。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值