FreeRTOS学习:任务通知

任务通知简介

任务通知简单来说就是用来通知任务的,在任务控制块中的结构体成员ulNotifiedValue就是通知值。

  • 通知值为 0 时,表示没有任务通知;当通知值不为 0 时,表示有任务通知,并且通知值就是通知的内容。
  • 使用队列,信号量,事件标志组都需要新创建一个结构体,通过中间结构体进行间接通信,示意图如下,
  • 用任务通知时,任务控制块TCB包含了内部对象,可以直接接收别的任务发来的通知,示意图如下,

任务通知值更新方式

  • 不覆盖接收任务的通知值(队列不覆写)
  • 覆盖接收任务的通知值(队列覆写)
  • 更新接受任务通知值的一个或多个bit(事件标志组)
  • 增加接受任务的通知值(计数型信号量)

备注:我们会发现,任务通知值是可以替代队列,信号量,事件标志位的。 

任务通知优劣势 

优势:

  • 效率高:任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快得多;
  • 内存小:任务通知代替队列、事件标志组或信号量,可以节省大量的内存
     

劣势: 

  • 无法发送数据给中断(ISR):ISR没有任务控制块的结构体,所以无法发送数据,但是任务通知功能可以在任务之间或从中断到任务发送事件或数据。
  • 无法广播多个任务:任务通知只能是被指定的一个接收任务接收并处理。
  • 无法缓存多个数据:任务通知是通过更新任务通知值来发送事件或数据的,一个任务通知值只能保存一次。
  • 发送受阻不支持阻塞:发送方无法进入阻塞状态等待
     

任务通知状态

任务通知状态有以下三种, 

  • 任务未等待通知:任务通知默认初始化状态
  • 等待通知:接收方已经准备好,等待发送方给个通知
  • 等待接收:发送方已经发送数据,等待接收方接收

任务通知相关函数

发送通知函数:

备注:可以看到,发送通知函数可用于任务和中断中,但是接收通知函数只能用在任务中。

发送通知 

发送通知的函数如下,

/*发送通知,带有通知值*/
#define xTaskNotify( xTaskToNotify, ulValue, eAction) 
xTaskGenericNotify( (xTaskToNotify), 
                    (tskDEFAULT_INDEX_TO_NOTIFY), 
                    (ulValue), 
                    (eAction), 
                    NULL)

/*发送通知,且带有通知值并且保留接收任务的原通知值*/
#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue) 
xTaskGenericNotify( (xTaskToNotify), 
                    (tskDEFAULT_INDEX_TO_NOTIFY), 
                    (ulValue), 
                    (eAction), 
                    (pulPreviousNotifyValue))

/*发送通知,但不带有通知值*/
#define xTaskNotifyGive( xTaskToNotify) 
xTaskGenericNotify( (xTaskToNotify), 
                    (tskDEFAULT_INDEX_TO_NOTIFY), 
                    (0), 
                    eIncrement, 
                    NULL)

从上述三个函数我们可以看到,他们其实都是调用同一个函数 xTaskGenericNotify(),只是里面的参数不同而已,下面介绍该函数。

xTaskGenericNotify():

BaseType_t xTaskGenericNotify(  TaskHandle_t xTaskToNotify,
                                UBaseType_t uxIndexToNotify,
                                uint32_t ulValue,
                                eNotifyAction eAction,
                                uint32_t * pulPreviousNotificationValue    );

参数:

  • xTaskToNotify:接收任务通知的任务句柄,也就是指定哪个任务接收通知
  • uxIndexToNotify:任务通知的相关数组成员,固定值0
  • ulValue:任务通知值
  • pulPreviousNotificationValue:用于保存更新前的任务通知值,不保存就用NULL,需要保存就给一块内存
  • eAction:通知值更新方式

接收通知 

ulTaskNotifyTake():

#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait) 

ulTaskGenericNotifyTake(    (tskDEFAULT_INDEX_TO_NOTIFY), 
                            (xClearCountOnExit), 
                            (xTicksToWait)    )

参数:

  • tskDEFAULT_INDEX_TO_NOTIFY:任务的指定通知,也就是任务通知相关数组成员
  • xClearCountOnExit:指定在成功接收后,将通知值清0还是减1,pdTRUE表示清零。
  •  xTicksToWait :阻塞超时时间

返回值为0表示接收失败,反之接收成功。

备注:该函数用于获取任务通知,可以设置在成功获取任务通知的通知值后,可以指定将通知值清零或减 1,当任务通知用作二值信号量或者计数型信号量时可以使用

 xTaskNotifyWait()

#define xTaskNotifyWait(    ulBitsToClearOnEntry, 
                            ulBitsToClearOnExit, 
                            pulNotificationValue, 
                            xTicksToWait) 

xTaskGenericNotifyWait(     tskDEFAULT_INDEX_TO_NOTIFY, 
                            (ulBitsToClearOnEntry), 
                            (ulBitsToClearOnExit), 
                            (pulNotificationValue), 
                            (xTicksToWait))

 参数:

  • tskDEFAULT_INDEX_TO_NOTIFY:任务的指定通知,也就是任务通知相关数组成员
  • ulBitsToClearOnEntry:等待前清零指定任务通知值的比特位,也就是旧值对应的bit清零
  • ulBitsToClearOnExit :成功等待后清零指定任务通知值的比特位,新值清零
  • pulNotificationValue:用来取出通知值,不需要的话,设置为NULL
  • xTicksToWait:阻塞超时时间

 返回值如果是pdTRUE,则等待成功,反之失败

备注:该函数更加复杂,可以获取通知值和清除通知值的指定位,可以模拟事件标志组和队列。 

函数内部实现 

以下是xTaskGenericNotify()的内部流程,

 

以下是ulTaskNotifyTake()的内部流程,

第一步时,当为0也就是没有收到任务通知时,进行下面步骤,

第二步时,收到通知值后,需要判断是否需要在成功读取通知后,将通知值清零,操作如下,

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值