FreeRTOS学习笔记十三【事件组】

目的

  • 介绍事件组的实际用途。
  • 事件组相对于其他同步功能的优缺点。
  • 如何设置事件组中的事件位。
  • 如何在阻塞状态中等待在事件组中的事件位。
  • 如何使用事件组来同步一组任务。

简介

嵌入式实时操作系统必须实时响应事件,前面介绍了几种将事件传递给任务的方法,如信号量,队列。它们都具有一下特性:

  • 它们允许在阻塞态下等待单个事件的发送。
  • 它们在事件发送时可以取消阻塞的单个任务(取消的是等待事件优先级最高的任务)。

事件组是FreeRTOS提供另一种事件传递的方法,它与队列和信号量的不同点:

  • 时间组允许任务在阻塞态下等待一个或多个事件。
  • 事件发生时,事件将取消阻塞等待同一事件或事件组合的所有任务。

事件组的这些特性可以用于多个任务同步,将事件广播到多个任务,允许任务在阻塞态下等待一组事件中的任何一个发生,并允许任务在阻塞态等待多个事件以完成多个操作。有时也可以用单个时间组替代多个二值信号量,以减少RAM的使用。
事件组功能是可选的,要使用事件组的功能,需要将event_groups.c添加到项目中。

事件组的特征

事件组、事件标志、事件位

事件标志是一个布尔值(1或0),用于指示事件是否发生。事件组是一组事件标志,事件标志只能是1或0,允许事件标志存储在一个位中,事件组中的所有事件标志的状态存储在单个变量中,其中每个事件标志由EvenBits_t类型的变量中的一个位表示,因此,事件标志也成为事件位。如果EvenBits_t变量中的某个位为1,则表示该位表示的事件以发生。如果EvenBits_t变量中的某个位为0,则表示该位表示的事件未发生。下图显示了各个事件标志位如何映射到EvenBits_t变量中的各个位。
在这里插入图片描述
例如:事件组的值为0x92,即事件位1、4、7为1,因此仅发生由位1、4、7表示的事件,如下图。
在这里插入图片描述
其中,每位的具体意义由应用程序定义,例如:

  • 位0定义为“已接受到网络消息”。
  • 位1定义为“已将消息发送到网络”。
  • 位2定义为“网络中断”。
  • 等等。

一个事件组可表示的位数由FreeRTOSConfig.h中的configUSE_16_BIT_TICKS配置:

  • configUSE_16_BIT_TICKS为1,则每个事件组可以包含8个可用事件位。
  • configUSE_16_BIT_TICKS为0,则每个事件组可以包含24个可用事件位。

多个任务访问事件组

事件组本身也是一个对象,任何直到它句柄的任务或ISR都可以访问它,任意数量的任务都可以在同一事件组中设置位,也可以从同一事件组读取位。

通过事件组管理事件

xEventGroupCreate()

在使用事件组之前必须先创建它,它的API原型如下:

EventGroupHandle_t xEventGroupCreate( void );

返回值:

  • NULL
    创建失败,没有足够的内存空间存放事件组。
  • 非NULL
    创建成功,返回的是事件组的句柄。

xEventGroupSetBits()

xEventGroupSetBits()用于设置事件组中的一个或多个事件位,也可用于通知任务当前已设置的位。注意不要在中断中使用它,中断中应使用中断安全版API,它的原型如下:

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
                                const EventBits_t uxBitsToSet );

参数:

  • xEventGroup
    事件组的句柄。
  • uxBitsToSet
    它是一个位掩码,指定事件组中哪些位设置为1。通过事件组现有值与uxBitsToSet中的值按位或操作来更新事件组的值。例如:uxBitsToSet为0x04,则将事件组中的bit 2(从bit 0开始)设置为1,而其他位不变。

返回值:
返回调用xEventGroupSetBits()时事件组的值,注意,返回的值不一定包含uxBitsToSet设置的位,因为这些位可能被其他任务再次清除。

xEventGroupSetBitsFromISR()

xEventGroupSetBitsFromISR()是xEventGroupSetBits()的中断安全版本。"given"信号量是一种确定性操作,因为事先知道给出信号量可能导致最多一个任务离开阻塞状态。但当在事件组中设置事件位时,事先不知道有多少任务将离开阻塞状态,所以事件组中的设置事件位是不确定性操作。因此FreeRTOS设计和实现标准不允许在中断服务程序内执行不确定性操作,或禁止中断。所以xEventGroupSetBitsFromISR()不直接在中断服务例程中设置事件位,而是将操作推迟到RTOS守护程序任务。它的原型如下:

BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
									  const EventBits_t uxBitsToSet,
									  BaseType_t *pxHigherPriorityTaskWoken );

参数和前面介绍的参数相同,因此这里不再介绍。因为设置事件位的操作被推迟到了守护程序任务,所以这里返回的也不再是调用时的事件组的值。而是pdPASS和pdFALSE。

  • pdPASS
    成功将操作命令发送到定时器命令队列。
  • pdFALSE
    如果定时器命令队列为满,则没有将操作发送到定时器命令队列。

xEventGroupWaitBits()

xEventGroupWaitBits()函数允许任务读取事件组的值,并且事件尚未发生,可以在阻塞状态下选择等待事件组中的一个或多个事件。它的原型如下:

EventBits_t xEventGroupWaitBits( const EventGroupHandle_t xEventGroup,
								 const EventBits_t uxBitsToWaitFor,
								 const BaseType_t xClearOnExit,
								 const BaseType_t xWaitForAllBits,
							 	 TickType_t xTicksToWait );

参数:

  • xEventGroup
    事件组的句柄。
  • uxBitsToWaitFor
    它是一个位掩码,指定要在事件组中测试的事件位(一个或多个)。例如,调用任务想要等待事件组中的事件位0和(或)事件位2被设置,则将uxBitsToWaitFor设置为0x05。
  • xClearOnExit
    如果调用任务满足解除阻塞条件,并且xClearOnExit为pdTRUE,则在xEventGroupWaitBits()退出前,清除uxBitsToWaitFor指定的事件位。如果xClearOnExit为pdFALSE,则xEventGroupWaitBits()函数不会修改事件组的事件位。
  • xWaitForAllBits
    uxBitsToWaitFor指定的是事件组中要测试的位,而当xWaitForAllBits为pdFALSE时uxBitsToWaitFor中任何位被设置就退出函数(超时后也会退出),当xWaitForAllBits为pdTRUE时,uxBitsToWaitFor中设置的所有位被设置才退出函数(超时后也会退出)。
  • xTicksToWait
    最长的超时时间,如果在设定时间内没有达到上面的要求则会退出函数,这个参数和前面介绍的xTicksToWait使用方法一样。

返回值:
如果有事件位被设置,并且满足调用任务解除阻塞条件,则返回的值是满足调用任务退出阻塞态的事件组的值。如果是由于超时退出,则返回的值将不满足调用任务退出阻塞态的事件组的值。

调用程序用于确定任务是否将进入阻塞态以及任务何时将离开阻塞态的条件称为解除阻塞条件。解除阻塞条件由uxBitsToWaitFor和xWaitForAllBits两个参数的组合指定:

  • uxBitsToWaitFor指定要测试的事件组中的哪些事件位
  • xWaitForAllBits指定是使用按位或(任何指定的事件位被设置)测试还是按位与(所有指定的事件位都要全部被设置)测试

如果在调用xEventGroupWaitBits()时满足解除阻塞条件,则任务不会进入阻塞态。下表提供了导致任务进入或退出阻塞态的条件示例,其中只给出了4位,其余的没有给出可以假设为0.

事件组的值 uxBitsToWa
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值