FreeRTOS事件组

事件组事件标志和事件

事件“标志”是布尔值(1或0),用于指示事件是否发生。事件“组”是一组事件标志。

事件标志只能为1或0,从而允许将事件标志的状态存储在单个位中,而将事件组中所有事件标志的状态存储在单个变量中;事件组中每个事件标志的状态由EventBits_t类型的变量中的一位表示。因此,事件标志也称为事件“位”。如果将EventBits_t变量中的某个位设置为1,则发生了该位表示的事件。如果将EventBits_t变量中的某个位设置为0,则该位表示的事件尚未发生。

EventBits_t数据类型

事件组中事件位的数量取决于FreeRTOSConfig.h 中的configUSE_16_BIT_TICKS配置的常量:

·如果configUSE_16_BIT_TICKS为1,则每个事件组均包含8个可用事件位。

·如果configUSE_16_BIT_TICKS为0,则每个事件组包含24个可用事件位。

通过多任务

事件组本身就是对象,知道其存在的任何任务或ISR都可以访问。任意数量的任务都可以在同一事件组中设置位,并且任意数量的任务都可以从同一事件组中读取位。

使用事件

FreeRTOS + TCP TCP / IP堆栈的实现提供了一个实际的示例,说明如何使用事件组同时简化设计并最小化资源使用。

TCP套接字必须响应许多不同的事件。事件的示例包括接受事件,绑定事件,读取事件和关闭事件。套接字在任何给定时间可以预期的事件取决于套接字的状态。例如,如果已创建一个套接字,但尚未将其绑定到地址,则它可以期望接收到绑定事件,但不会期望接收到读取事件(如果没有地址,则无法读取数据) 。

FreeRTOS + TCP套接字的状态保存在称为FreeRTOS_Socket_t的结构中。该结构包含一个事件组,该事件组具有为套接字必须处理的每个事件定义的事件位。FreeRTOS + TCP API调用会阻塞以等待一个事件或一组事件,而只是阻塞事件组。

事件组还包含一个“中止”位,无论套接字当时正在等待哪个事件,它都可以中止TCP连接。

使用事件管理事件

xEventGroupCreate()API 函数

FreeRTOS V9.0.0还包括xEventGroupCreateStatic()函数,该函数在编译时静态分配创建事件组所需的内存:必须明确创建事件组才能使用它。

使用EventGroupHandle_t类型的变量引用事件组。xEventGroupCreate()API函数用于创建事件组,并返回EventGroupHandle_t引用其创建的事件组。

函数原型

EventGroupHandle_t xEventGroupCreate(void);

xEventGroupCreate()返回值

参数名称

描述

返回值

如果返回NULL,则创建事件组失败,因为FreeRTOS没有足够的堆内存来分配事件组数据结构。

 

返回的非NULL值表示事件组已成功创建。返回值应存储为句柄到创建的事件组。

xEventGroupSetBits()API 函数

xEventGroupSetBits()API函数设置事件组中的一个或多个位,通常用于通知任务已发生的由一个或多个位表示的事件已发生。

注意:切勿从中断服务程序中调用xEventGroupSetBits(),应在其位置使用中断安全版本xEventGroupSetBitsFromISR()。

函数原型

EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet);

xEventGroupSetBits()参数和返回值

参数名称

描述

xEventGroup

设置位的事件组的句柄。事件组句柄将从用于创建事件组的xEventGroupCreate()的调用中返回。

 

uxBitsToSet

一个位掩码,用于指定要在事件组中设置为1的一个或多个事件位。通过将事件组的现有值与uxBitsToSet中传递的值进行按位或运算,可以更新事件组的值。

例如,将uxBitsToSet设置为0x04(二进制0100)将导致事件组中的事件位3被置位(如果尚未设置),而事件组中的所有其他事件位均保持不变。

 

返回值

返回对xEventGroupSetBits()的调用时事件组的值。请注意,返回的值不一定必须设置uxBitsToSet指定的位,因为这些位可能已由其他任务再次清除。

xEventGroupSetBitsFromISR()API 函数

提供信号量是确定性操作,因为预先知道提供信号量最多可以导致一项任务离开“已阻塞”状态。如果在事件组中设置了位,则无法预先知道有多少任务将离开“已阻塞”状态,因此在事件组中设置位不是确定性操作。

FreeRTOS设计和实现标准不允许在中断服务程序内部或禁用中断时执行不确定性操作。因此,xEventGroupSetBitsFromISR()不会直接在中断服务例程内部设置事件位,而是将操作延迟到RTOS守护程序任务。

函数原型

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

xEventGroupSetBitsFromISR()参数和返回值

参数名称

描述

xEventGroup

设置位的事件组的句柄。事件组句柄将从用于创建事件组的xEventGroupCreate()的调用中返回。

 

uxBitsToSet

一个位掩码,用于指定要在事件组中设置为1的一个或多个事件位。通过将事件组的现有值与uxBitsToSet中传递的值进行按位或运算,可以更新事件组的值。

 

例如,将uxBitsToSet设置为0x05(二进制0101)将导致事件组中的事件位3和事件位0被置位(如果尚未设置),同时保留所有事件组中的其他事件位保持不变。

 

pxHigherPriorityTaskWoken

xEventGroupSetBitsFromISR()不会直接在中断服务例程内部设置事件位,而是通过在计时器命令队列上发送命令来将操作推迟到RTOS守护程序任务。如果守护程序任务处于“已阻塞”状态,以等待数据在计时器命令队列中可用,则写入计时器命令队列将导致守护程序任务退出“已阻塞”状态。

如果守护程序任务的优先级高于当前正在执行的任务(被中断的任务)的优先级,则内部将设置xEventGroupSetBitsFromISR()pxHigherPriorityTask唤醒为pdTRUE。

如果xEventGroupSetBitsFromISR()将此值设置为pdTRUE,则应在退出中断之前执行上下文切换。这将确保中断直接返回到守护程序任务,因为守护程序任务将是最高优先级的就绪状态任务。

 

返回值

有两个可能的返回值:

仅当数据成功发送到计时器命令队列时,才会返回pdPASS。

 

如果由于队列已满而无法将“设置位”命令写入计时器命令队列,将返回pdFALSE。

xEventGroupWaitBits()API 函数

xEventGroupWaitBits()API函数允许任务读取事件组的值,并可选地在“阻塞”状态下等待事件组中的一个或多个事件位被置位(如果尚未设置事件位)。

函数原型

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

调度程序用来确定任务是否将进入Blocked状态以及何时任务将退出Blocked状态的条件称为“解除阻止条件”。解除阻止条件由uxBitsToWaitFor和xWaitForAllBits参数值的组合指定:

·uxBitsToWaitFor指定要测试的事件组中的哪些事件位

·xWaitForAllBits指定是使用按位OR测试还是按位AND测试

如果在调用xEventGroupWaitBits()时满足其取消阻塞条件,则该任务将不会进入“阻塞”状态。

下表中提供了导致任务进入“已阻止”状态或退出“已阻止”状态的条件示例。下表仅显示了事件组的最低有效四位二进制位和uxBitsToWaitFor值(这些位的其他位)两个值假定为零。

uxBitsToWaitFor和xWaitForAllBits参数的影响

现有事件组值

uxBitsToWaitFor值

xWaitForAllBits值

结果行为

0000

0101

pdFALSE

因为在事件组中没有设置位0或位2,所以调用任务将进入阻塞状态,并且在事件组中设置了位0或位2时,它将退出阻塞 状态。

 

0100

 

0101

 

pdTRUE

调用任务将进入阻塞状态,因为在事件组中未同时设置位0和位2,并且在事件组中同时设置了位0和位2时将退出阻塞状态。

 

0100

 

0110

 

pdFALSE

由于xWaitForAllBits为pdFALSE,并且在事件组中已设置uxBitsToWaitFor指定的两位之一,因此调用任务将不会进入“阻塞”状态。

 

0100

 

0110

 

pdTRUE

调用任务将进入阻塞状态,因为xWaitForAllBits为pdTRUE,并且在事件组中仅设置了由uxBitsToWaitFor指定的两位中的一位。在事件组中同时设置了位2和位3时,任务将退出“阻塞”状态。

调用任务使用uxBitsToWaitFor参数指定要测试的位,并且在满足其解锁条件后,调用任务可能需要将这些位清零。可以使用xEventGroupClearBits()API函数清除事件位,但是如果满足以下条件,则使用该函数手动清除事件位将导致应用程序代码中的争用条件:

多个任务使用同一事件组

事件组中的位是由其他任务或中断服务程序设置的。提供xClearOnExit参数可以避免这些潜在的竞争情况。如果xClearOnExit设置为pdTRUE,则对调用任务的测试和清除事件位似乎是原子操作(不可被其他任务或中断中断)。

xEventGroupWaitBits()参数和返回值

参数名称

描述

xEventGroup

包含正在读取的事件位的事件组的句柄。事件组句柄将从用于创建事件组的xEventGroupCreate()的调用中返回。

 

uxBitsToWaitFor

位掩码,指定要在事件组中测试的一个或多个事件位。

 

例如,如果调用任务要等待事件位0和/或事件位2在事件组中被设置,则将uxBitsToWaitFor设置为0x05(二进制0101)。

 

xClearOnExit

如果满足调用任务的解除阻塞条件,并且xClearOnExit设置为pdTRUE,则在调用任务退出xEventGroupWaitBits()API函数之前,将在事件组中将uxBitsToWaitFor指定的事件位清除为0。

 

如果xClearOnExit设置为pdFALSE,则xEventGroupWaitBits()API函数不会修改事件组中事件位的状态。

 

xWaitForAllBits

uxBitsToWaitFor参数指定事件组中要测试的事件位。xWaitForAllBits指定在设置了uxBitsToWaitFor参数指定的一个或多个事件位时,还是仅在设置uxBitsToWaitFor参数指定的所有事件位时,是否应从“已阻塞”状态中删除调用任务。

 

如果xWaitForAllBits设置为pdFALSE,则当uxBitsToWaitFor指定的任何位被置位(或者xTicksToWait参数指定的超时到期)时,进入“阻塞”状态以等待其解除阻塞条件的任务将离开“阻塞”状态。 )。

 

如果xWaitForAllBits设置为pdTRUE,则只有在设置了uxBitsToWaitFor指定的所有位(或xTicksToWait参数指定的超时)后,进入“阻塞”状态以等待其解除阻塞条件的任务才会离开“阻塞”状态过期)。

 

xTicksToWait

任务应保持在“阻塞”状态以等待其解除阻塞条件所需的最长时间。

 

如果xTicksToWait为零,或者在调用xEventGroupWaitBits()时满足解锁条件,则xEventGroupWaitBits()将立即返回。

 

块时间以滴答周期指定,因此它表示的绝对时间取决于滴答频率。宏pdMS_TO_TICKS()可用于将以毫秒为单位的时间转换为以刻度为单位的时间。

 

如果在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend设置为1,则将xTicksToWait设置为portMAX_DELAY将导致任务无限期等待(无超时)。

 

xWaitForAllBits

uxBitsToWaitFor参数指定事件组中要测试的事件位。xWaitForAllBits指定在设置了uxBitsToWaitFor参数指定的一个或多个事件位时,还是仅在设置uxBitsToWaitFor参数指定的所有事件位时,是否应从“已阻塞”状态中删除调用任务。

 

如果xWaitForAllBits设置为pdFALSE,则当uxBitsToWaitFor指定的任何位被置位(或者xTicksToWait参数指定的超时到期)时,进入“阻塞”状态以等待其解除阻塞条件的任务将离开“阻塞”状态。 )。

 

如果xWaitForAllBits设置为pdTRUE,则只有在设置了uxBitsToWaitFor指定的所有位(或xTicksToWait参数指定的超时)后,进入“阻塞”状态以等待其解除阻塞条件的任务才会离开“阻塞”状态过期)。

 

xTicksToWait

任务应保持在“阻塞”状态以等待其解除阻塞条件所需的最长时间。

 

如果xTicksToWait为零,或者在调用xEventGroupWaitBits()时满足解锁条件,则xEventGroupWaitBits()将立即返回。

 

块时间以滴答周期指定,因此它表示的绝对时间取决于滴答频率。宏pdMS_TO_TICKS()可用于将以毫秒为单位的时间转换为以刻度为单位的时间。

 

如果在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend设置为1,则将xTicksToWait设置为portMAX_DELAY将导致任务无限期等待(无超时)。

 

返回值

如果由于满足调用任务的取消阻塞条件而返回xEventGroupWaitBits(),则返回值是满足调用任务的取消阻塞条件时事件组的值(如果xClearOnExit为pdTRUE,则自动清除任何位)。在这种情况下,返回的值也将满足解锁条件。

 

如果由于xTicksToWait参数指定的阻塞时间到期而返回xEventGroupWaitBits(),则返回的值是阻塞时间到期时事件组的值。在这种情况下返回的值将不满足解锁条件。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值