概述
- 事件组的每一位表示一个事件
- 每一位事件的含义由我们决定,比如:Bit0 表示用来串口是否就绪,Bit1表示按键是否被按下
- 值为 1 表示事件发生了,值为 0 表示事件没发生
- 一个或多个任务、ISR 都可以去写这些位;一个或多个任务、ISR 都可以去读这些位
- 可以等待某一位、某些位中的任意一个,也可以等待多位
- 的高8位留给内核使用,只能用其他的位来表示事件
- 如果 configUSE_16_BIT_TICKS 是 1,那么这个整数就是 16 位的,低 8 位用来表示事件 如果 configUSE_16_BIT_TICKS 是 0,那么这个整数就是 32 位的,低 24 位用来表示事件
- 队列、信号量:事件发生时,只会唤醒一个任务,而事件组:事件发生时,会唤醒所有符号条件的任务
- 队列、信号量:是消耗型的资源,队列的数据被读走就没了;信号量被获取后就减少了,而事件组:被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件
函数
创建
/* 创建一个事件组,返回它的句柄。
* 此函数内部会分配事件组结构体
* 返回值: 返回句柄,非 NULL 表示成功
*/
EventGroupHandle_t xEventGroupCreate( void );
/* 创建一个事件组,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticEventGroup_t 结构体,并传入它的
指针
* 返回值: 返回句柄,非 NULL 表示成功
*/
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer
);
删除
对于动态创建的事件组,不再需要它们时,可以删除它们以回收内存
/*
* xEventGroup: 事件组句柄,你要删除哪个事件组
*/
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
设置事件
可以设置事件组的某个位、某些位
有一个或多个任务在等待事件,如果这些事件符合这些任务的期望,那么任务还会被唤醒
/* 设置事件组中的位
* xEventGroup: 哪个事件组
* uxBitsToSet: 设置哪些位?
* 如果 uxBitsToSet 的 bitX, bitY 为 1, 那么事件组中的 bitX, bitY 被设置为 1
* 可以用来设置多个位,比如 0x15 就表示设置 bit4, bit2, bit0
* 返回值: 返回原来的事件值(没什么意义, 因为很可能已经被其他任务修改了) */
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
/* 设置事件组中的位
* xEventGroup: 哪个事件组
* uxBitsToSet: 设置哪些位?
* 如果 uxBitsToSet 的 bitX, bitY 为 1, 那么事件组中的 bitX, bitY 被设置为 1
* 可以用来设置多个位,比如 0x15 就表示设置 bit4, bit2, bit0
* pxHigherPriorityTaskWoken: 有没有导致更高优先级的任务进入就绪态? pdTRUE-有, p
dFALSE-没有
* 返回值: pdPASS-成功, pdFALSE-失败
*/
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t * pxHigherPriorityTaskWoken );
- 值得注意的是,ISR中的函数,比如队列函数xQueueSendToBackFromISR、信号量函数xSemaphoreGiveFromISR,它们会唤醒某个任务,最多只会唤醒1个任务。
- 但是设置事件组时,有可能导致多个任务被唤醒,这会带来很大的不确定性。所以
xEventGroupSetBitsFromISR函数不是直接去设置事件组,而是给一个FreeRTOS后台任务
(daemon task)发送队列数据,由这个任务来设置事件组。 - 如果后台任务的优先级比当前被中断的任务优先级高,xEventGroupSetBitsFromISR会设置*pxHigherPriorityTaskWoken为pdTRUE。
- 如 果 daemon task 成 功 地 把 队 列 数 据 发 送 给 了 后 台 任 务 , 那 么
xEventGroupSetBitsFromISR的返回值就是pdPASS
等待事件
可以等待某一位、某些位中的任意一个,也可以等待多位;等到期望的事件后,还可以清除某些位。
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait );
参数 | 说明 |
---|---|
xEventGroup | 等待哪个事件组 |
uxBitsToWaitFor | 等待哪些位?哪些位要被测试 |
xWaitForAllBits | 怎么测试?是“AND”还是“OR”pdTRUE :等待的位,全部为 1;pdFALSE :等待的位,某一个为 1 即可 |
xClearOnExit | 函数退出前是否要清除事件(该位置0)?pdTRUE :清除 uxBitsToWaitFor 指定的位;pdFALSE :不清除 |
xTicksToWait | 如果期待的事件未发生,阻塞多久。 可设置为 0:判断后即刻返回; 可设置为 portMAX_DELAY :一定等到成功才返回;可设置为期望的 Tick Count,一般用 pdMS_TO_TICKS() 把 ms 转换为 Tick Count |
返回值 | 返回的是事件值。 如果期待的事件发生了,返回的是“非阻塞条件成立”时的事件值; 如果是超时退出,返回的是超时时刻的事件值 |
同步点
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
参数 | 说明 |
---|---|
xEventGroup | 指定是哪个事件组 |
uxBitsToSet | 用于确定要设置哪些事件,即表明完成了哪些事件。例如0x05 (二进制为0101 ),会使事件组的bit0 、bit2 被设置为1 |
uxBitsToWaitFor | 明确等待哪些位。比如0x15 (二进制10101 ),表示要等待bit0 、bit2 、bit4 都为1 |
xTicksToWait | 若期待的事件未发生,设置阻塞时长。可设为0 ,判断后立即返回;可设为portMAX_DELAY ,一直等到成功才返回;也可设为期望的Tick Count,通常用pdMS_TO_TICKS() 将ms转换为Tick Count |
返回值 | 返回事件值。若期待事件发生,返回“非阻塞条件成立”时的事件值;若因超时而退出,返回超时时刻的事件值 |