简介
之前我们讲过实时嵌入式系统需要对事件进行响应,之前的章节我们讲述了将事件处理放置到任务中,任务通过信号量或队列的方式等待执行,它们的主要特征为:
1,他们允许任务进入阻塞态等待事件的发生
2,当事件发生时,他们使一个任务进入就绪态,该任务是所有等待任务中优先级最高的任务。
事件组是另一种将事件传递给任务的方式,与通过信号量与队列传递的方式不同,他们主要特征为:
1,事件组允许任务进入阻塞态等待多个事件之一的混合发生。
2,当事件发生时,事件组使所有等待该事件的任务进入阻塞态。
这种方式对于多重同步任务有很大帮助,并且可降低RAM的适用,因为它可减少大量二进制信号量的适用。当需要使用事件组时,需要编译源文件event_groups.c。
事件组的特性
事件组,事件标志和事件比特(event bits)
一个事件标志就是一个布尔型1或0的量来表示一个事件是否发生。一个事件组就是一系列时间标志的集合。
一个事件标志只能为1或0,并且存储在一个数据位中,因此我们可以用一个类型为EventBits_t的变量中的不同位来表示不同事件,不同事件的标志对应变量中的不同位。当该位为1时表示事件发生,为0时表示没发生。
关于EventBits_t的数据类型
该数据的位数与FreeRTOSConfig.h中的configUSE_16_BIT_TICKS有关,当configUSE_16_BIT_TICKS置为1时,每个事件组包含8个事件位,当置为0时,每个事件组包含24个事件位。
任务对于事件组的权限
所有直到该事件组存在的任务和中断都可获取该事件组,任一数量的任务都可对事件组进行读写操作。
使用事件组管理事件
xEventGroupCreate()
该函数用于创建一个事件组,事件组的类型为EventGroupHandle_t,其函数原型如下所示:
EventGroupHandle_t xEventGroupCreate( void );
返回值:当返回NULL表示内存不足创建失败,否则创建成功。
xEventGroupSetBits()
该函数用于将一个事件组中一个或多个事件位置位,它表明相关事件的发生。
***注意***中断函数中有专门函数xEventGroupSetBitsFromISR()。
函数原型如下:
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet );
参数:
xEventGroup:事件组名称。
uxBitsToSet 需要置位的事件的位置,例如0x04,表示bit3需要置位。可以一次性置位多个,例如0x05。
返回值:事件组的值。
注意 使用uxBitsToSet 置位的值再返回后并不一定为1,因为可能存在其他任务在该函数执行过程中打断了该函数然后再次将事件组内的值复位了。
xEventGroupSetBitsFromISR()
中断专用置位安全函数。当使用信号量或队列时,只有一个任务进入就绪态,而使用事件组会导致所有相关任务进入就绪态,这就导致进入就绪态的任务的个数是不定的,因此在中断结束后是否应该调用任务调度器会变得无法判断,因此中断函数内并不会直接置位事件组,而是将该行为推迟到后台任务中执行(关于后台任务看中断管理二)。该函数函数原型如下:
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t *pxHigherPriorityTaskWoken );
参数:
xEventGroup:事件组名称。
uxBitsToSet:置位的位。
pxHigherPriorityTaskWoken :该函数并不会直接置位事件组,而是在后台任务函数中置位,因此该函数会将该指令经过队列传递给后台任务。根据后台任务的优先级,若后台任务优先级高于此时中断打断的任务,则该参数被置为pdTRUE,否则为pdFALSE。若为pdTRUE则应调用上下文切换开关。
返回值:pdPASS表成功,pdFALSE表队列已满。
xEventGroupWaitBits()
该函数用于任务阻塞读取事件组中的一位或几位置位,只有当所读取的置位后才退出阻塞态。函数原型如下:
EventBits_t xEventGroupWaitBits( const EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait );
uxBitsToWaitFor:表示需要测试那些位。
xWaitForAllBits:表示是只要有一位复合就退出阻塞态,还是uxBitsToWaitFor中的位都置位再退出阻塞态。
xEventGroup:事件组名称。
xClearOnExit:若为pdTRUE,则在该函数退出前会将相关位置为0,若为pdFALSE则不对时间组操作。( 也可通过EventGroupClearBits()清除标志位。)
xTicksToWait :阻塞等待最长时间。
返回值:若相关位已置位,则返回值为事件组复位前的值(xClearOnExit为pdTRUE)。若超时,则返回的值为在阻塞状态花费的时间长。
实例
该实例描述了如何创建事件组,利用中断置位事件组,在任务中置位事件组,阻塞等待事件组置位。
第一次调用xEventGroupWaitBits()时将xWaitForAllBits置为pdFALSE,之后的置为pdTRUE。
相关宏定义:
/* Definitions for the event bits in the event group. */
#define mainFIRST_TASK_BIT ( 1UL << 0UL ) /* Event bit 0, which is set by a task. */
#