在小节里面介绍了二进制信号量,计数信号量,互斥量和递归互斥量等功能,其中二进制信号量和计数信号量(也包括队列)常用于任务和任务之间以及任务和中断之间的同步,她们具有以下属性:
- 当等待的事件没有发生的时候可以让等待的任务进入阻塞状态
- 当等待的事件发生之后可以将因为等待事件发生而进入阻塞状态的任务唤醒,如果有多个任务在等待同一个事件发生的话,那么此时被唤醒的是优先级最高的任务,其它任务依然还是处于阻塞状态。
这里即将要介绍的事件组( E v e n t G r o u p s Event\quad Groups EventGroups)也可以用于任务和任务之间以及任务和中断之间的同步,但是和二进制信号量,计数信号量(也包括队列)不同的是:
- 事件组可以用于等待多个事件的发生而进行同步,而不是像二进制信号量和计数信号量(也包括队列)只能用于等待单一的事件而进行同步
- 当等待的事件中的事件发生的时候可以唤醒多个任务而不是像二进制信号量和计数信号量(也包括队列)只能用于唤醒多个任务中优先级最高的那个任务。
事件组以上的特有属性使得事件组非常适合于多个任务的同步,可以将事件的发生广播给多个任务,也允许一个任务等待一个或多个事件的发生来同步。事件组在 F r e e R T O S FreeRTOS FreeRTOS的源码的 e v e n t g r o u p s . c event_groups.c eventgroups.c文件中用一个结构体来定义,如图1所示。当宏 c o n f i g U S E _ 16 _ B I T _ T I C K S configUSE\_16\_BIT\_TICKS configUSE_16_BIT_TICKS被定义为0的时候,变量 u x E v e n t B i t s uxEventBits uxEventBits的低24位可以用来表示24个事件的状态,如果对应的比特位的值为1则表面对应的事件已经发生,反之对应的事件没有发生,变量 u x E v e n t B i t s uxEventBits uxEventBits的高8位用于特殊用途(对应于图2中的那些宏定义,至于其具体的含义需要通过相应的源码来了解其具体含义)。当宏 c o n f i g U S E _ 16 _ B I T _ T I C K S configUSE\_16\_BIT\_TICKS configUSE_16_BIT_TICKS被定义为1的时候,变量 u x E v e n t B i t s uxEventBits uxEventBits的低8位可以用来表示8个事件的状态,如果对应的比特位的值为1则表面对应的事件已经发生,反之对应的事件没有发生,变量 u x E v e n t B i t s uxEventBits uxEventBits的高8位用于特殊用途(对应于图2中的那些宏定义,至于其具体的含义需要通过相应的源码来了解其具体含义)。


在图3的例子中,这里宏 c o n f i g U S E _ 16 _ B I T _ T I C K S configUSE\_16\_BIT\_TICKS configUSE_16_BIT_TICKS被定义为0,比特位1,4,和7对应的事件已经发生而其它比特位对应的事件还没有发生。事件组可以被多个任务或中断接入,任何任务都有权限对事件组结构体中的变量 u x E v e n t B i t s uxEventBits uxEventBits的低8位或低24位的比特位进行置位,任何任务也都有权限对事件组结构体中的变量 u x E v e n t B i t s uxEventBits uxEventBits进行读取。事件组的结构体的 x T a s k s W a i t i n g F o r B i t s xTasksWaitingForBits xTasksWaitingForBits元素是一个用来记录因为在等待事件组的某个或某些事件而被阻塞的任务。

下面来简单的看几个事件组的 A P I API API接口函数,其它的 A P I API API接口函数可以自己去看看图4所示的文档的详细介绍。

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t * pxHigherPriorityTaskWoken )
{
BaseType_t xReturn;
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );