FreeRTOS任务通知

FreeRTOS任务通知

FreeRTOS 从 V8.2.0 版本开始提供任务通知这个功能,每个任务都有一个 32 位的通知值,在大多数情况下,任务通知可以替代二值信号量、计数信号量、事件组, 也可以替代长度为 1 的队列(可以保存一个 32 位整数或指针值) 。
按照 FreeRTOS 官方的说法,使用任务通知比通过信号量等 ICP 通信方式解除阻塞的任务要快 45%,并且更加省 RAM 内存空间(使用 GCC 编译器, -o2 优化级别) ,任务通知的使用无需创建队列。 想要使用任务通知,必须将 FreeRTOSConfig.h 中的宏定义 configUSE_TASK_NOTIFICATIONS 设置为 1,其实
FreeRTOS 默认是为 1 的, 所以任务通知是默认使能的。
FreeRTOS 提供以下几种方式发送通知给任务 :
发送通知给任务, 如果有通知未读,不覆盖通知值。
发送通知给任务,直接覆盖通知值。
发送通知给任务,设置通知值的一个或者多个位 ,可以当做事件组来使用。
发送通知给任务,递增通知值,可以当做计数信号量使用
通过对以上任务通知方式的合理使用,可以在一定场合下替代 FreeRTOS 的信号量,队列、事件组等。
但也有以下限制 :
只能有一个任务接收通知消息, 因为必须指定接收通知的任务。
只有等待通知的任务可以被阻塞, 发送通知的任务,在任何情况下都不会因为发失败而进入阻塞态。
FreeRTOS 的每个任务都有一个 32 位的通知值,任务控制块中的成员变量 ulNotifiedValue就是这个通知值。只有在任务中可以等待通知,而不允许在中断中等待通知。如果任务在等待的通知暂时无效,任务会根据用户指定的阻塞超时时间进入阻塞状态,我们可以将等待通知的任务看作是消费者;其它任务和中断可以向等待通知的任务发送通知,发送通知的任务和中断服务函数可以看作是生产者,当其他任务或者中断向这个任务发送任务通知,任务获得通知以后,该任务就会从阻塞态中解除,这与 FreeRTOS 中内核的其他通信机制一致。

任务通知的函数接口

发送任务通知函数 xTaskGenericNotify()
FreeRTOS 的风格,
这里的任务通知发送函数也是利用宏定义来进行扩展的,所有的函数都是一个宏定义, 在任务中发送任务通知的函数均是调用 xTaskGenericNotify()函数进行发送通知

xTaskGenericNotify()函数是一个通用的任务通知发送函数,在任务中发送通知的 API函 数 , 如 xTaskNotifyGive() 、 xTaskNotify() 、xTaskNotifyAndQuery() , 都 是 以xTaskGenericNotify()为原型的,只不过指定的发送方式不同而已

xTaskNotifyGive()
xTaskNotifyGive()是一个宏,宏展开是调用函数 xTaskNotify( ( xTaskToNotify ), ( 0 ),eIncrement ), 即向一个任务发送通知,并将对方的任务通知值加 1。该函数可以作为二值信号量和计数信号量的一种轻量型的实现,速度更快, 在这种情况下对象任务在等待任务通 知 的 时 候 应 该 是 使 用 函 数 ulTaskNotifyTake()而 不 是 xTaskNotifyWait() 。xTaskNotifyGive() 不 能 在 中 断 里 面 使 用 , 而 是 使 用 具 有 中 断 保 护 功 能 的vTaskNotifyGiveFromISR()来代替。

vTaskNotifyGiveFromISR()
vTaskNotifyGiveFromISR()是 vTaskNotifyGive()的中断保护版本。 用于在中断中向指定任务发送任务通知,并更新对方的任务通知值(加 1 操作) ,在某些场景中可以替代信号量操作,因为这两个通知都是不带有通知值的。

xTaskNotify()
xTaskNotify()用于在任务中直接向另外一个任务发送一个事件, 接收到该任务通知的任务有可能解锁
xTaskNotify()函数在发送任务通知的时候会指定一个通知值, 并且用户可以指定通知值发送的方式。
注意: 该函数不能在中断里面使用, 而是使用具体中断保护功能的版本函数xTaskNotifyFromISR()。
xTaskNotifyFromISR()
xTaskNotifyFromISR()是 xTaskNotify()的中断保护版本,真正起作用的函数是中断发送任务通知通用函数xTaskGenericNotifyFromISR(),而xTaskNotifyFromISR()是一个宏定义,用于在中断中向指定的任务发送一个任务通知, 该任务通知是带有通知值并且用户可以指定通知的发送方式, 不返回上一个任务在的通知值。

中断中发送任务通知通用函数xTaskGenericNotifyFromISR()
xTaskGenericNotifyFromISR() 是 一 个 在 中 断 中 发 送 任 务 通 知 的 通 用 函 数 xTaskNotifyFromISR(),xTaskNotifyAndQueryFromISR()等函数都是以其为基础,采用宏定义的方式实现。

xTaskNotifyAndQuery()
xTaskNotifyAndQuery()与 xTaskNotify()很像,都是调用通用的任务通知发送函数xTaskGenericNotify() 来 实 现 通 知 的 发 送 , 不 同 的 是 多 了 一 个 附 加 的 参 数pulPreviousNotifyValue 用于回传接收任务的上一个通知值,xTaskNotifyAndQuery()函数不能用在中断中,而是必须使用带中断保护功能的xTaskNotifyAndQuery()FromISR 来代替。

xTaskNotifyAndQueryFromISR()
xTaskNotifyAndQueryFromISR()是 xTaskNotifyAndQuery ()的中断版本,用于向指定的任务发送一个任务通知, 并返回对象任务的上一个通知值, 该函数也是一个宏定义, 真正实现发送通知的是 xTaskGenericNotifyFromISR()

获取任务通知函数

任务通知在某些场景可以替代信号量、消息队列、事件等。获取任务通知函数只能用在任务中,没有带中断保护版本,因此只有两个 API 函数: ulTaskNotifyTake()和xTaskNotifyWait ()。前者是为代替二值信号量和计数信号量而专门设计的,它和发送通知API 函数 xTaskNotifyGive()、 vTaskNotifyGiveFromISR()配合使用;后者是全功能版的等待通知,可以根据不同的参数实现轻量级二值信号量、计数信号量、事件组和长度为 1 的队列。
所有的获取任务通知 API 函数都带有指定阻塞超时时间参数,当任务因为等待通知而进入阻塞时,用来指定任务的阻塞时间,这些超时机制与 FreeRTOS 的消息队列、信号量、事件等的超时机制一致。

ulTaskNotifyTake()
lTaskNotifyTake()作为二值信号量和计数信号量的一种轻量级实现,速度更快。 如果FreeRTOS 中使用函数 xSemaphoreTake() 来获取信号量, 这个时候则可以试试使用函数ulTaskNotifyTake()来代替
xTaskNotifyTake()在退出的时候处理任务的通知值的时候有两种方法,一种是在函数退出时将通知值清零,这种方法适用于实现二值信号量;另外一种是在函数退出时将通知值减 1,这种方法适用于实现计数信号量
当一个任务使用其自身的任务通知值作为二值信号量或者计数信号量时, 其他任务应该使用函数 xTaskNotifyGive()或者 xTaskNotify( ( xTaskToNotify ), ( 0 ), eIncrement )来向其发送信号量。 如果是在中断中,则应该使用他们的中断版本函数。

xTaskNotifyWait()
xTaskNotifyWait()函数用于实现全功能版的等待任务通知,根据用户指定的参数的不同,可以灵活的用于实现轻量级的消息队列队列、二值信号量、计数信号量和事件组功能,并带有超时等待。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值