目录
3.2.2 xTaskGenericNotifyWait()
一. 任务通知的简介
FreeRTOS的每个任务都有一个32位的通知值,任务控制块中的成员变量ulNotifiedValue就是这个通知值。
任务通知是一个事件,假如某个任务通知的接收任务,因为等待任务通知而阻塞的话,则向这个接收任务发送任务通知,就会解除这个任务的阻塞状态。
使用任务通知时,任务结构体TCB中就包含了内部对象,可以直接接收别人发过来的"通知"
1.1 任务通知值的更新方式
① 不覆盖接收任务的通知值 (如果上次发送给接收任务的通知还没有被处理) 。
② 覆盖接收任务的通知值。
③ 更新接收任务通知值的一个或多个bit。
④ 增加接收任务的通知值。
1.2 任务通知的优势及劣势
任务通知的优势 效率更高
使用任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快得多
使用内存更小
使用其他方法时都要先创建对应的结构体,使用任务通知时无需额外创建结构体
任务通知的劣势 无法发送数据给ISR
ISR没有任务结构体,所以无法给ISR发送数据。但是ISR可以使用任务通知的功能,发数据给任务。
无法广播给多个任务
任务通知只能是被指定的一个任务接收并处理
无法缓存多个数据
任务通知是通过更新任务通知值来发送数据的,任务结构体中只有一个任务通知值,只能保持一个数据。
发送受阻不支持阻塞
发送方无法进入阻塞状态等待
二. 任务通知值和任务通知状态
typedef struct tskTaskControlBlock
{
/*.....*/
#if( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue; // uint32_t 类型,用来表示通知值
volatile uint8_t ucNotifyState; // uint8_t 类型,用来表示通知状态
#endif
/*.....*/
} tskTCB;
2.1 任务通知值
任务通知值的更新方式有多种类型:
计数值 (数值累加,类似信号量)相应位置一(类似事件标志组)任意数值 (支持覆写和不覆写,类似队列)
2.2 任务通知状态
任务通知状态共有3种:
任务未等待通知 (任务通知默认的初始化状态)等待通知 (接收方已经准备好了(调用了接收任务通知函数),等待发送方给个通知)等待接收 (发送方已经发送出去(调用了发送任务通知函数),等待接收方接收)
三. 任务通知的相关函数
任务通知API函数主要有两类
①发送通知 ②接收通知
注意
发送通知API函数可以用于任务和中断服务函数中;接收通知API函数只能用在任务中。
3.1 发送通知相关API函数
函数 | 描述 |
xTaskNotify() | 发送通知,带有通知值 |
xTaskNotifyAndQuery() | 发送通知,带有通知值并且保留接收任务的原通知值 |
xTaskNotifyGive() | 发送通知,不带通知值 |
xTaskNotifyFromISR() | 在中断中发送任务通知 |
xTaskNotifyAndQueryFromISR() | |
vTaskNotifyGiveFromISR() |
#define xTaskNotifyAndQuery( xTaskToNotify ,
ulValue ,
eAction ,
pulPreviousNotifyValue
)
xTaskGenericNotify( ( xTaskToNotify ),
( tskDEFAULT_INDEX_TO_NOTIFY ),
( ulValue ),
( eAction ),
( pulPreviousNotifyValue )
)
--------------------------------------------------------------------
#define xTaskNotify ( xTaskToNotify ,
ulValue ,
eAction
)
xTaskGenericNotify( ( xTaskToNotify ) ,
( tskDEFAULT_INDEX_TO_NOTIFY ) ,
( ulValue ) ,
( eAction ) ,
( NULL )
)
--------------------------------------------------------------------
#define xTaskNotifyGive ( xTaskToNotify )
xTaskGenericNotify( ( xTaskToNotify ) ,
( tskDEFAULT_INDEX_TO_NOTIFY ) ,
( 0 ) ,
( eIncrement ),
( NULL )
)
3.1.1 xTaskGenericNotify()
xTaskNotify()、xTaskNotifyAndQuery()、xTaskNotifyGive() 三个宏函数,调用的全都是xTaskGenericNotify() 这个函数。
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue
)
形参 | 描述 |
xTaskToNotify | 接收任务通知的任务句柄 |
uxIndexToNotify | 任务的指定通知(任务通知相关数组成员) |
ulValue | 任务通知值 |
eAction | 通知方式(通知值更新方式) |
pulPreviousNotificationValue | 用于保存更新前的任务通知值(为NULL则不保存) |
typedef enum
{
eNoAction = 0, /* 无操作 */
eSetBits /* 更新指定bit */
eIncrement /* 通知值加一 */
eSetValueWithOverwrite /* 覆写的方式更新通知值 */
eSetValueWithoutOverwrite /* 不覆写通知值 */
} eNotifyAction;
3.2 接收通知相关API函数
函数 | 描述 |
ulTaskNotifyTake() | 获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减一。 当任务通知用作二值信号量或者计数信号量的时候,使用此函数来获取信号量。 |
xTaskNotifyWait() | 获取任务通知,比 ulTaskNotifyTak()更为复杂,可获取通知值和清除通知值的指定位 |
总结
当任务通知用作于信号量时,使用函数获取信号量: ulTaskNotifyTake ()当任务通知用作于 事件标志组或队列 时,使用此函数来获取: xTaskNotifyWait ()
3.2.1 ulTaskNotifyTake()
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
形参 | 描述 |
xClearCountOnExit | 指定在成功接收通知后,将通知值清零或减 1, pdTRUE:把通知值清零;pdFALSE:把通知值减一 |
xTicksToWait | 阻塞等待任务通知值的最大时间 |
返回值 | 描述 |
0 | 接收失败 |
非 0 | 接收成功,返回任务通知的通知值 |
3.2.2 xTaskGenericNotifyWait()
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t *pulNotificationValue,
TickType_t xTicksToWait
)
形参 | 描述 |
uxIndexToWaitOn | 任务的指定通知(任务通知相关数组成员) |
ulBitesToClearOnEntry | 等待前清零指定任务通知值的比特位(旧值对应bit清0) |
ulBitesToClearOnExit | 成功等待后清零指定的任务通知值比特位(新值对应bit清0) |
pulNotificationValue | 用来取出通知值(如果不需要取出,可设为NULL) |
xTicksToWait | 阻塞等待任务通知值的最大时间 |
返回值 | 描述 |
pdTRUE | 等待任务通知成功 |
pdFALSE | 等待任务通知失败 |