🛬RTOS原理与实现09:事件标志组实现
2023-6-4
| 2023-7-15
0  |  阅读时长 0 分钟
type
status
password
date
slug
summary
category
URL
tags
icon
notion image

1. 事件标志组的原理与创建

1.1 问题概述

notion image
事件标志组要解决的问题场景就是任务需要等待特定的事件组发生才继续运行,在上图示例中,
  1. ISR设置事件标志,任务等待事件标志
  1. 任务可以设置等待标志与等待条件,
💡
说明:事件标志组的特点就是任务可以等待一组事件的集合

1.2 设计原理

notion image
  1. 每个任务等待特定的事件集合
  1. 如果等待的事件集合与当前事件标志不符合,则在事件控制块上实现等待;否则消费事件并返回
  1. 事件发生时,设置当前事件标志;然后遍历等待队列,如果有匹配的任务则消费事件并唤醒任务
💡
说明:是否消费事件可设置

1.3 设计实现

1.3.1 定义事件标志组类型

说明:目前使用uint32_t类型表示当前事件标志组,每个事件1 bit,最多容纳32个事件

1.3.2 添加tFlagGroupInit函数

说明:flags作为一组初始的事件标志,用于初始化事件标志组

2. 事件标志组的等待与通知

2.1 等待条件

notion image
如上文所述,在事件标志组实现过程中需要区分等待标志与等待条件,其中等待条件又由2个维度组成,
  • 等待标志位置位还是等待标志位清零(set or clear):置1还是清0→触发条件
  • 等待所有标志位满足还是等待任意标志位满足(any or all):任意标志位还是所有标志位→触发条件

2.2 设计原理

2.2.1 等待事件标志(事件条件不满足)

notion image
💡
任务1等待所有标志位置位,而当前条件不满足,所以将任务插入等待队列

2.2.2 等待事件标志(事件条件满足)

notion image
任务1等待所有标志位置位,当前条件满足,所以根据设置消费事件并返回(可以设置消费与否)
💡
说明:所谓消费事件就是将标志恢复为事件发生前的状态,其中,
  • 如果等待标志位置位,则消费事件是将该位清零
  • 如果等待标志位清零,则消费事件是将该位置位

2.2.3 通知事件标志

notion image
当事件发生时,
  1. 没有任务等待,设置相应的事件标志
  1. 有任务等待,设置相应的事件标志;然后遍历等待任务,判断其等待标志与等待条件,如果符合则唤醒任务

2.3 设计实现

2.3.1 任务结构增设事件标志等待字段

2.3.2 等待条件宏定义

说明:通过上述宏定义标识任务等待条件的4种组合,而TFLAGGROUP_CONSUME宏用于标识等待条件满足时是否消费事件

2.3.3 添加tEventWakeUpTask函数

在之前基于事件控制块的组件中(计数信号量 / 邮箱 / 存储块),在条件满足时都是唤醒事件控制块等待队列的队首任务
但是在事件标志组中,需要唤醒符合条件的任务,所以添加该函数用于唤醒等待队列中的指定任务

2.2.4 添加tFlagGroupCheckAndConsume函数

该函数为事件标志组模块的内部函数(但是是核心函数),用于检查当前事件标志组与任务等待的事件标志组是否匹配,如果匹配则根据设置消费事件
说明1:判断条件是否满足
calcFlag中保存的是任务等待的标志的就位情况,所以,
① 如果是等待所有标志,则calcFlag必须等于srcFlag
② 如果是等待任意标志,则只要calcFlag非零即可(即至少有一个标志就位)
说明2:消费事件不影响未发生的事件
如果是等待任意标志,当条件满足时,使用srcFlag消费事件时并不会影响未发生的事件,因为不会改变这些位的值,所以即使使用srcFlag也只会消费已发生的事件
当然,此处也可以使用calcFlag来消费事件,这样语义更好理解(calcFlag相当于srcFlag的子集)

2.2.5 添加tFlagGroupWait函数

说明:currentTask->eventFlags & currentTask->waitEventResult返回的结果由notify接口填充

2.2.6 添加tFlagGroupNoWaitGet函数

2.2.7 添加tFlagGroupNotify函数

说明1:tFlagGroupCheckAndConsume函数的调用参数
由于tFlagGroupCheckAndConsume函数的第3个参数即作为入参(要等待的事件标志组),也作为出参(等待的事件标志检查结果),所以在函数中会修改该参数的值,因此在调用时均先将要等待的事件标志组赋值给局部变量
说明2:此处实现的逻辑是一次唤醒所有符合等待条件的任务,当然,如果第一个唤醒的任务消费了事件,则后续的任务就无法唤醒了

3. 事件标志组的删除与状态查询

3.1 设计原理

3.1.1 事件标志组的删除

notion image
说明:删除事件标志组时,只要删除在事件控制块上等待的任务即可;而被唤醒的任务将得到tErrorDel的返回值。
补充:本课程中如果代码使用了已被删除的组件(e.g. 信号量 / 邮箱 / 内存块 / 事件标志组)是无法判断该组件已经失效的,所有代码仅为说明工作原理

3.2 设计实现

3.2.1 添加tFlagGroupDestroy函数

3.2.2 添加tFlagGroupGetInfo函数

为获取事件标志组的状态,首先定义用于保存事件标志组信息的结构
  • RTOS
  • RTOS原理与实现08:存储块实现RTOS原理与实现10:互斥信号量实现
    Loading...
    目录