自学内容网 自学内容网

立志最细,FreeRtos中的任务通知(Task Notification)详解!!!

目录

基本概念

任务通知特性

函数原型

简化版函数

专业版函数


             前言:本篇参考,韦东山开发文档,连接放在最后

基本概念

        在FreeRtos操作系统里面,任务通知(Task Notification)是一种专门用在任务间的任务通信机制,被用在任务间的发送信号或者传输数据,特点是效率高,占用内存和cpu非常少

        虽然在FreeRtos中队列(Queue)信号量(Semaphore)事件组(Event Group)都可以实现任务间的通信(唤醒),但是没有使用任务通知,占用内存小和速度快,队列(Queue)信号量(Semaphore)事件组(Event Group)来通知任务的时候,只是将阻塞列表里面的第一个阻塞的任务唤醒,但是不知道这个任务是哪个任务。

任务通知特性

        使用任务通知效率更高相对于,队列,事件,信号量,更加节省内存,不需要创建结构体,不能发送数据给ISR,数据只能被任务独享,发送数据只能被目标人物访问,无法缓冲数据,任务通知只有一个任务通知值,只能保持一个数据,无法广播发送给多个任务,只能实现发送给一个任务。

        tskTaskControlBlock简称tskTCB,是任务通知控制块(Task Control Block)的结构体,包含任务的各种状态信息,成员属性有 ulNotifiedValue 和 ucNotifyState

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;

        ulNotifiedValue 任务通知的数值的取值范围,这个成员属性用来存储任务通知的数据,因为是 uint32_t 类型 取值范围在 0x000000 ~ 0xffffff 之间。

        ucNotifyState这个成员属性类型代表着任务通知的状态,能取值的状态类型有三种,taskNOT_WAITING_NOTIFICATION任务不处于等待通知状态

taskWAITING_NOTIFICATION任务等待通知状态

taskNOTIFICATION_RECEIVED任务接受通知状态,也称为peding状态

        如果任务状态为 taskNOT_WAITING_NOTIFICATION 期间有任务通知,并不会转换状态为taskNOTIFICATION_RECEIVED 保持状态,只有任务状态为taskWAITING_NOTIFICATION,这个时候有任务通知,才会转变任务状态为 taskNOTIFICATION_RECEIVED。

函数原型

        任务通知函数分为,简化版,专业版,后者参数更多实现功能更多,同样的前者,实现的是简化版的功能。

简化版专业版
发出通知

xTaskNotifyGive()

vTaskNotifyGiveFromISR()

xTaskNotify()

xTaskNotifyFromISR()

取出通知ulTaskNotifyTake()xTaskNotifyWait()

简化版函数

        简化版函数在任务中给其他任务发送任务通知时,使用 xTaskNotifyGive() ,在ISR(中断)中使用 vTaskNotifyGiveFromISR() 函数,效果为如下所示。

BaseType_t xTaskNotifyGive(TaskHandle_t xTaskToNotify);
void vTaskNotifyGiveFromISR(TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken);

· 使得通知值加一,也就是 ulNotifiedValue 的数值加1

·使 ucNotifyState 的值改变为 taskNOTIFICATION_RECEIVED 也是 pending状态

       这里需要注意的是,当任务的状态为 taskNOT_WAITING_NOTIFICATION 发送的通知会被记录在通知值当中,但任务自身状态不会改变为,taskNOTIFICATION_RECEIVED 只有当任务调用ulTaskNotifyTake() 或者 xTaskNotifyWait() 函数,这个时候自身状态才会转变为 Peding 状态。

        简化版函数使用 ulTaskNotifyTake() 用来接受任务通知,当调用函数时,作用如下所示。

·使任务状态从taskNOT_WAITING_NOTIFICATION变为 taskWAITING_NOTIFICATION1

·当任务在 taskWAITING_NOTIFICATION 接到通知,可以获取通知值进行处理

uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit, TickType_t xTicksToWait);

        参数中,BaseType_t xClearCountOnExit 类型为 BaseType_t 作用为 指示在任务退出等待状态时是否清除通知计数值 

值为 pdTRUE在任务接收到通知并退出等待状态后,清除通知计数(即将通知值重置为0)。

值为 pdFALSE保留通知计数。即使任务接收到通知,计数仍然保持不变。

这里需要注意的是,当设置参数的值为pdTRUE,会将 ulNotifiedValue 的数值清除为 0,如果设置为 pdFALSE,这里是不会改变  ulNotifiedValue 里面的数值的。

        同样的参数里面  xTicksToWait 就是设置等待时间,设置为 0 不等待立刻返回,同样的设置为portMAX_DELAY:一直等待

专业版函数

        xTaskNotify/xTaskNotifyWait 这两个函数相对于简单版来说,提供了更多的参数去选择,下满是函数原型。

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

        这里专业版函数,多出来一个 eAction 参数,参数有着不同的取值,有着不同的效果,表格如下

eAction取值参数效果
eNoAction更新状态为peding,未使用ulValue
eSetBits通知值 = 原来的通知值 | ulValue
eIncrement通知值 = 原来的通知值 + 1
eSetValueWithoutOverwrite不覆盖。
eSetValueWithOverwrite覆盖。

        同样的 xTaskNotifyFromISR 函数和 xTaskNotify 很相似,多出来 pxHigherPriorityTaskWoken这个参数,用来指示ISR是否唤醒了一个优先级更高的任务,如果该任务优先级高于当前正在运行的任务,FreeRtos会在ISR结束的时候进行上下文切换,确保最高优先级的任务能够尽快运行。

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

        专业版的等待函数,也多了很多的参数,具体参数详解如下所示

ulBitsToClearOnEntry :指定任务在等待状态,需要清除的通知位

ulBitsToClearOnExit:指定任务在等待期间要等待通知的位,当指定位被改变时,才会唤醒

pulNotificationValue:参数用来传入,任务发送的通知值

xTicksToWait:函数最大的等待时间,0不等待,portMAX_DELAY 陷入阻塞一直等待。

                                        欢迎指正,希望对你,有所帮助!!!

FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)_哔哩哔哩_bilibili


原文地址:https://blog.csdn.net/weixin_62292999/article/details/143006922

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!