第九章 任务通知

1、任务通知理论

1.1 任务通知的核心

任务通知
理解任务通知的核心在于TCB结构体中有这两项:
TCB结构体ucNotifyState有3种取值:

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

1.2 使用流程

使用流程:使用ucNotifyState来切换任务状态(阻塞、就绪),使用ulNotifiedValue来传递信息。

  • 任务A被创建出来时,ucNotifyState为taskNOT_WAITING_NOTIFICATION
  • 它想等待通知的话
    • 调用ulTaskNotifyTake xTaskNotifyWait ,进入taskWAITING_NOTIFICATION
    • 表示在等待通知,任务进入阻塞状态
  • 任务B可以调用这两个函数来通知A:xTaskNotifyGive xTaskNotify
    • 任务A的ucNotifyState就变为taskNOTIFICATION_RECEIVED
    • 表示收到了通知,待处理
  • 任务A从阻塞状态变为就绪态,它运行时
    • ulTaskNotifyTake xTaskNotifyWait 得到数值并返回
    • 返回之前把ucNotifyState恢复为taskNOT_WAITING_NOTIFICATION

1.3 怎么传递信息

函数原型如下:

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, 
                            uint32_t ulBitsToClearOnExit, 
                            uint32_t *pulNotificationValue, 
                            TickType_t xTicksToWait );

任务通知函数(1)

发送函数作用接收函数作用
xTaskNotifyGiveval++ulTaskNotifyTakeval-- 或 val = 0
xTaskNotifyxTaskNotifyWait
不使用val,只起通知作用可以在函数进入时清除val的某些位
可以在函数退出前清除val的某些位
可以取得val的值
val |= (bits)
val++
val = xxx
不覆盖,
当ucNotifyState表示在等待才起效
val = xxx
覆盖

eNotifyAction参数说明:

eNotifyAction取值说明
eNoAction仅仅是更新通知状态为"pending",未使用ulValue。
这个选项相当于轻量级的、更高效的二进制信号量。
eSetBits通知值 = 原来的通知值 | ulValue,按位或。
相当于轻量级的、更高效的事件组。
eIncrement通知值 = 原来的通知值 + 1,未使用ulValue。
相当于轻量级的、更高效的二进制信号量、计数型信号量。
相当于xTaskNotifyGive()函数。
eSetValueWithoutOverwrite不覆盖。
如果通知状态为"pending"(表示有数据未读),
则此次调用xTaskNotify不做任何事,返回pdFAIL。
如果通知状态不是"pending"(表示没有新数据),
则:通知值 = ulValue。
eSetValueWithOverwrite覆盖。
无论如何,不管通知状态是否为"pending",
通知值 = ulValue。

2. 任务通知使用_轻量级信号量

函数对比:

信号量使用任务通知实现信号量
创建SemaphoreHandle_t xSemaphoreCreateCounting(
UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount );
GivexSemaphoreGive( SemaphoreHandle_t xSemaphore );BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
TakexSemaphoreTake(
SemaphoreHandle_t xSemaphore,
TickType_t xBlockTime
);
uint32_t ulTaskNotifyTake(
BaseType_t xClearCountOnExit,
TickType_t xTicksToWait
);

信号量:give N次,take N次
任务通知:

  • pdTrue:val = 0 ,take 1次
  • pdFalse:val-- , take N次(与信号量相同)

3. 任务通知使用_轻量级队列

函数对比:

队列使用任务通知实现队列
创建QueueHandle_t xQueueCreate(
UBaseType_t uxQueueLength,
UBaseType_t uxItemSize
);
发送BaseType_t xQueueSend(
QueueHandle_t xQueue,
const void * pvItemToQueue,
TickType_t xTicksToWait
);
BaseType_t xTaskNotify(
TaskHandle_t xTaskToNotify,
uint32_t ulValue,
eNotifyAction eAction
);
接收BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait
);
BaseType_t xTaskNotifyWait(
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t *pulNotificationValue,
TickType_t xTicksToWait
);

轻量级队列(任务通知):

  • 覆盖:多次发送,接收的是最后一次数据
  • 不覆盖:多次发送,只有最开始那次成功

4. 任务通知使用_轻量级事件组

假设有3个任务:

  • 任务1做事件1
  • 任务2做事件2
  • 任务3等待事件1、事件2都发生

可以使用事件组来编写程序,也可以使用任务通知来编写程序。

函数对比:

事件组使用任务通知实现事件组
创建EventGroupHandle_t xEventGroupCreate( void )
设置事件EventBits_t xEventGroupSetBits(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet
);
BaseType_t xTaskNotify(
TaskHandle_t xTaskToNotify,
uint32_t ulValue,
eNotifyAction eAction
);
等待事件EventBits_t xEventGroupWaitBits(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait
);
BaseType_t xTaskNotifyWait(
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t *pulNotificationValue,
TickType_t xTicksToWait
);

轻量级任务组(任务通知):一旦设置事件,一定会唤醒目标任务,无法指定哪些事件(无法实现真正的任务组)

队列、信号量、事件组与任务通知的区别

使用队列、信号量、事件组时,我们都要事先创建对应的结构体,双方通过中间的结
构体通信:
队列、信号量、事件组

使用任务通知时,任务结构体 TCB 中就包含了内部对象,可以直接接收别人发过来的
“通知”:(多对一的关系)
任务通知

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值