1.事件位和事件租简介
(1)事件位(事件标志)
事件位用于指示事件是否已发生。事件位通常称为事件标志。例如,应用程序可以:
- 定义一个位(或标志),当消息设置为 1 时,该位表示“已收到消息并准备进行处理”,当设置为 0 时,定义“没有等待处理的消息”的位(或标志)。
- 定义一个位(或标志),当它设置为 1 时,表示“应用程序已将准备发送到网络的消息排队”;当它设置为 0 时,定义一个位(或标志),即“没有消息排队准备发送到网络”。
- 定义一个位(或标志),当它设置为 1 时,它意味着“是时候将检测信号消息发送到网络上了”,当它设置为 0 时,定义一个表示“现在还不是时候发送另一个检测信号消息”。
(2)事件组
事件组是一组事件位。事件组中的各个事件位由位号引用。扩展上面提供的示例:
- 表示“已收到消息并已准备好进行处理”的事件位可能是事件组中的位号 0。
- 表示“应用程序已将准备发送到网络的消息排队”的事件位可能是同一事件组中的第 1 位。
- 表示“是时候将检测信号消息发送到网络了”的事件位可能是同一事件组中的第 2 位。
(3)事件组和事件位的数据类型
事件组由类型为 EventGroupHandle_t 的变量引用。
如果将configUSE_16_BIT_TICKS设置为 1,则存储在事件组中的位数(或标志)数为 8;
如果configUSE_16_BIT_TICKS设置为 0,则为 24。
对configUSE_16_BIT_TICKS依赖性源于任务内部实现中用于线程本地存储的数据类型。
事件组中的所有事件位都存储在EventBits_t类型的单个无符号变量中。事件位 0 存储在位位置 0,事件位 1 存储在位位置 1,依此类推。
下图表示一个 24 位事件组,该事件组使用三位来保存已描述的三个示例事件。在图像中,仅设置了事件位 2。
RTOS 在实施事件组时必须克服的挑战
在实施事件组时,RTOS 必须克服的两个主要挑战是:
- 避免在用户的应用程序中创建争用条件:
在以下情况下,事件组实现将在应用程序中创建争用条件:
- 目前尚不清楚谁负责清除单个位(或标志)。
- 目前尚不清楚何时要清除位。
- 目前尚不清楚在任务退出测试位值的API函数时是否设置了位或清除了位(可能是另一个任务或中断更改了位的状态)。
- 避免非确定性:
事件组概念意味着非确定性行为,因为它不知道事件组上阻止了多少个任务,因此不知道在设置事件位时需要测试多少个条件或取消阻止多少个任务。
FreeRTOS 质量标准不允许在禁用中断时执行非确定性操作,也不允许在中断服务例程中执行非确定性操作。要确保在设置事件位时不会违反这些严格的质量标准,请执行以下操作:
- RTOS 调度程序的锁定机制用于确保在从 RTOS 任务设置事件位时中断保持启用状态。
- 集中式延迟中断机制用于在尝试从中断服务例程设置事件位时,将位设置为任务的操作推迟。