使用信号量来同步的话任务只能与单个的事件或任务进行同步。有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了。FreeRTOS 为此提供了一个可选的解决方法,那就是事件标志组。

概念

  • 事件位:事件位用来表明某个事件是否发生,事件位通常用作事件标志。
  • 事件组:一个事件组就是一组的事件位,事件组中的事件位通过位编号来访问。

    事件标志组和事件位的数据类型

    事件标志组的数据类型为 EventGroupHandle_t,当configUSE_16_BIT_TICKS为1的时候事件标志组可以存储 8 个事件位,当configUSE_16_BIT_TICKS为0的时候事件标志组存储24个事件位。
    事件标志组中的所有事件位都存储在一个无符号的 EventBits_t 类型的变量中,EventBits_t在 event_groups.h 中有如下定义。
    1. typedef TickType_t EventBits_t;
    configUSE_16_BIT_TICKS为0的时候TickType_t是个32位的数据类型,因此EventBits_t也是个32 位的数据类型。EventBits_t类型的变量可以存储 24 个事件位,另外的那高 8 位有其他用。事件位 0 存放在这个变量的 bit0 上,变量的 bit1 就是事件位 1,以此类推。
    17.事件标志组 - 图1

    事件标志组的API

    创建事件标志组

    | 函数 | 描述 | | —- | —- | | xEventGroupCreate() | 使用动态方法创建事件标志组 | | xEventGroupCreateStatic() | 使用静态方法创建事件标志组 |

函数 xEventGroupCreate()
此函数用于创建一个事件标志组,所需要的内存通过动态内存管理方法分配。由于内部处理的原因,事件标志组可用的bit数取决于configUSE_16_BIT_TICKS , 当configUSE_16_BIT_TICKS1 为1的时候事件标志组有 8 个可用的位(bit0~bit7) ,当configUSE_16_BIT_TICKS 为 0 的时候事件标志组有 24 个可用的位(bit0~bit23)。EventBits_t 类型的变量用来存储事件标志组中的各个事件位。

  1. EventGroupHandle_t xEventGroupCreate( void )

参数

  • 无。

返回值

  • NULL: 事件标志组创建失败。
  • 其他值: 创建成功的事件标志组句柄。

函数 xEventGroupCreateStatic()
此函数用于创建一个事件标志组定时器,所需要的内存需要用户自行分配。

  1. EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )

参数

  • pxEventGroupBuffer: 参数指向一个 StaticEventGroup_t 类型的变量,用来保存事件标志组结构体。

返回值

  • NULL: 事件标志组创建失败。
  • 其他值: 创建成功的事件标志组句柄。

设置事件位

FreeRTOS 提供了 4 个函数用来设置事件标志组中事件位(标志),事件位(标志)的设置包括清零和置 1 两种操作

函数 描述
xEventGroupClearBits() 将指定的事件位清零,用在任务中
xEventGroupClearBitsFromISR() 将指定的事件位清零,用在中断服务函数中
xEventGroupSetBits() 将指定的事件位置 1,用在任务中
xEventGroupSetBitsFromISR() 将指定的事件位置 1,用在中断服务函数中

函数 xEventGroupClearBits()
将事件标志组中的指定事件位清零,此函数只能用在任务中,不能用在中断服务函数中。

  1. EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );

参数

  • xEventGroup: 要操作的事件标志组的句柄。
  • uxBitsToClear: 要清零的事件位,比如要清除 bit3 的话就设置为 0X08。可以同时清除多个bit,如设置为 0X09 的话就是同时清除 bit3 和 bit0。

返回值

  • 任何值: 将指定事件位清零之前的事件组值。

函数 xEventGroupClearBitsFromISR()
此函数为函数 xEventGroupClearBits()的中断级版本,也是将指定的事件位(标志)清零。此函数用在中断服务函数中。

  1. BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );

参数

  • xEventGroup: 要操作的事件标志组的句柄。
  • uxBitsToClear: 要清零的事件位,比如要清除 bit3 的话就设置为 0X08。可以同时清除多个bit,如设置为 0X09 的话就是同时清除 bit3 和 bit0。

返回值

  • pdPASS: 事件位清零成功。
  • pdFALSE: 事件位清零失败。

函数 xEventGroupSetBits()
设置指定的事件位为 1,此函数只能用在任务中,不能用于中断服务函数。

  1. EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );

参数

  • xEventGroup: 要操作的事件标志组的句柄。
  • uxBitsToClear: 指定要置 1 的事件位,比如要将 bit3 值 1 的话就设置为 0X08。可以同时将多个 bit 置 1,如设置为 0X09 的话就是同时将 bit3 和 bit0 置 1。

返回值

  • 任何值: 在将指定事件位置 1 后的事件组值。

函数 xEventGroupSetBitsFromISR()
此函数也用于将指定的事件位置 1,此函数是 xEventGroupSetBits()的中断版本,用在中断服务函数中。

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

参数

  • xEventGroup: 要操作的事件标志组的句柄。
  • uxBitsToClear: 指定要置 1 的事件位,比如要将 bit3 值 1 的话就设置为 0X08。可以同时将多个 bit 置 1,如设置为 0X09 的话就是同时将 bit3 和 bit0 置 1。
  • pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换,这个变量的值函数会自动设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之前一定要进行一次任务切换。

返回值

  • pdPASS: 事件位置 1 成功。
  • pdFALSE: 事件位置 1 失败。

获取事件标志组值

我们可以通过 FreeRTOS 提供的 API 函数来查询事件标准组值。

函数 描述
xEventGroupGetBits() 获取当前事件标志组的值(各个事件位的值),用在任务中
xEventGroupGetBitsFromISR() 获取当前事件标志组的值,用在中断服务函数中

函数 xEventGroupGetBits()
此函数用于获取当前事件标志组的值,也就是各个事件位的值。此函数用在任务中,不能用在中断服务函数中。此函数是个宏,真正执行的是函数 xEventGroupClearBits()。

  1. EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup )

参数

  • xEventGroup: 要获取的事件标志组的句柄。

返回值

  • 任何值:当前事件标志组的值。

函数 xEventGroupGetBitsFromISR()
获取当前事件标志组的值,此函数是 xEventGroupGetBits()的中断版本。

  1. EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )

参数

  • xEventGroup: 要获取的事件标志组的句柄。

返回值

  • 任何值: 当前事件标志组的值。

等待指定的事件位

某个任务可能需要与多个事件进行同步,那么这个任务就需要等待并判断多个事件位(标 志),使用函数 xEventGroupWaitBits()可以完成这个功能。调用函数以后如果任务要等待的事件位还没有准备好(置 1 或清零)的话任务就会进入阻塞态,直到阻塞时间到达或者所等待的事件位准备好。

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

参数

  • xEventGroup: 指定要等待的事件标志组。
  • uxBitsToWaitFord:指定要等待的事件位,比如要等待bit0和(或)bit2的时候此参数就是0X05,如果要等待 bit0 和(或)bit1 和(或)bit2 的时候此参数就是 0X07,以此类推。
  • xClearOnExit: 此参数要是为 pdTRUE 的话,那么在退出此函数之前由参数 uxBitsToWaitFor所设置的这些事件位就会清零。如果设置位 pdFALSE 的话这些事件位就不会改变。
  • xWaitForAllBits: 此参数如果设置为 pdTRUE 的话,当 uxBitsToWaitFor 所设置的这些事件位都置 1,或者指定的阻塞时间到的时候函数 xEventGroupWaitBits()才会返回。当此函数为 pdFALSE 的话,只要 uxBitsToWaitFor 所设置的这些事件位其中的任意一个置 1 ,或者指定的阻塞时间到的话函数xEventGroupWaitBits()就会返回。
  • xTicksToWait: 设置阻塞时间,单位为节拍数。

返回值

  • 任何值: 返回当所等待的事件位置 1 以后的事件标志组的值,或者阻塞时间到。根据这个值我们就知道哪些事件位置 1 了。如果函数因为阻塞时间到而返回的话那么这个返回值就不代表任何的含义。