事件是任务之间通信的机制,就像二值信号量,事件主要为了实现同步功能。但是可以实现一对多,即一个任务等待多个事件都满足才发生,或者多个事件中的一个。
事件的逻辑或是独立型同步,逻辑与是关联型同步。
打开事件组的结构体定义,
typedef struct xEventGroupDefinition
{
EventBits_t uxEventBits;
List_t xTasksWaitingForBits;
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxEventGroupNumber;
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ))
uint8_t ucStaticallyAllocated;
#endif
} EventGroup_t;
其中主要关注uxEventBits 和 xTasksWaitingForBits,一个变量和等待列表,而uxEventBits就是一个宏定义,它就是事件组。创建一个事件就像创建一个消息队列一样,是一个内核对象,它其中一个参数叫事件组uxEventBits,每一位的值代表着一个行为的发生与否。而uxEventBits类型是EventBits_t,它是一个宏定义
typedef TickType_t EventBits_t;
因此配置configUSE_16_BIT_TICKS可以决定事件中的位数,毕竟它由TickType_t决定。
事件创立函数xEventGroupCreate()(动态创建,基本上都是用的动态创建)
创建的过程也很简单,就是申请了一块内存,把事件组uxEventBits变量设置为0,初始化等待列表就完了。
事件删除函数vEventGroupDelete(), 就是把阻塞在列表的任务移除,然后调用一个释放内存函数vportFree(),调用事件删除函数时只需要传入事件句柄就可以。
事件置位函数xEventGroupSetBits(),就是在uxEventBits中相应的位置1的。它需要传入事件的句柄,以及置哪个位置置1,而且,它的源码除了置位外,还检查了等待列表的各任务在等什么,是逻辑与还是逻辑或,以及当任务等到了事件时,需不需要清除事件位,最后返回uxEventBits的值,这个值是不断累积的,并不是当前传入的设置值就会完全决定。
在中断中使用的xEventGroupSetBitsFromISR()
等待事件函数xEventGroupWaitBits()
它是需求方在任务的具体执行函数中调用的,它传入5个参数,事件句柄、uxBitsToWaitFor(等待的事件组的值)、xClearOnExit(等到了事件发生时的值需要清除事件标志位不,参数可选pdTRUE或者pdFALSE)、xWaitForALLBITS(是等待所有的事件都发生还是其中一个事件发生就执行,参数可选pdTRUE或者pdFALSE)、xTicksToWait,这个就是老朋友了。它还有一个返回值,是当前uxEventBits的值,不一定等于传入的值。
查看源码可知,首先根据uxBitsToWaitFor参数和xWaitForALLBITS参数判断当前的事件组uxEventBits是不是已经满足条件了,如果满足条件了就可以直接返回,并且查看需不需要清除事件组相应的位,不需要执行任务切换。如果当前的uxEventBits不满足条件,肯定就需要判断xTicksToWait的值,如果为0,说明不需要等待,直接返回当前的uxEventBits,如果不为0,就需要加入等待列表,并进行任务切换,同时还把那些是否需要清除标志位以及是否等待所有事件发生才执行一并保存。当然,等待事件函数没有中断版本,毕竟不能阻塞。在互斥量中,既没有释放信号量的中断版本函数,也没有获取信号量的中断版本,因为互斥量是拥有了才能释放,而且查看源码可知,在互斥量的创建函数下调用了一个互斥量初始化函数prvInitialiseMutex()函数,其中通过一个宏定义
#define pxMutexHolder pcTail
使得指针pcTail原本在消息队列中指向消息空间的结尾,而在互斥量指向的是任务的TCB,而中断没有TCB,因此在互斥量中没有中断版本相关的函数。而在二值信号量和计数信号量,它的底层实现仅仅是把消息控制块中的uxMessagesWaiting进行加减操作,因此而二值和计数信号量量的获取和释放都有中断保护版本,当然,队列也有相应的获取和释放的中断保护版本。
清除事件指定的位函数
xEventGoupClearBits , xEventGoupClearBitsFromISR(),只需要指定事件句柄以及指定哪个位需要清除就可以了,函数源码就是把对uxEventBits变量处理。