|____2.10 FreeRTOS 深度解析--事件

事件

  • [1. 事件控制块 EventGroup_t](#1. 事件控制块 EventGroup_t)
  • [2. 常用函数](#2. 常用函数)
    • [2.1 事件创建 xEventGroupCreate()](#2.1 事件创建 xEventGroupCreate())
    • [2.2 事件删除 vEventGroupDelete()](#2.2 事件删除 vEventGroupDelete())
    • [2.3 事件组置位(任务) xEventGroupSetBits() / xEventGroupSetBitsFromISR()(中断)](#2.3 事件组置位(任务) xEventGroupSetBits() / xEventGroupSetBitsFromISR()(中断))
    • [2.4 等待事件 xEventGroupWaitBits()](#2.4 等待事件 xEventGroupWaitBits())
    • [2.5 事件组清位(任务) xEventGroupClearBits() / xEventGroupClearBitsFromISR()(中断)](#2.5 事件组清位(任务) xEventGroupClearBits() / xEventGroupClearBitsFromISR()(中断))

1. 事件控制块 EventGroup_t

  1. 事件组存储在EventBits_t类型的变量中(24 个位用来实现事件标志组)

  2. 所有在等待此事件的任务均会被挂载在等待事件列表xTasksWaitingForBits


2. 常用函数

2.1 事件创建 xEventGroupCreate()

(1)因为事件标志组是FreeRTOS 的内部资源,也是需要RAM 的,所以,在创建的时候,会向系统申请一块内存,大小是事件控制块大小sizeof( EventGroup_t )

(2)如果分配内存成功,那么久对事件控制块的成员变量进行初始化,事件标志组变量清零,因为现在是创建事件,还没有事件发生,所以事件集合中所有位都为0,然后调用 vListInitialise()函数将事件控制块中的等待事件列表进行初始化,该列表用于记录等待在此事件上的任务

2.2 事件删除 vEventGroupDelete()

(1)挂起调度器,因为接下来的操作不知道需要多长的时间,并且在删除的时候,不希望其他任务来操作这个事件标志组,所以暂时把调度器挂起,让当前任务占有CPU

(2)当有任务被阻塞在事件等待列表中的时候,我们就要把任务恢复过来,否则删除了事件的话,就无法对事件进行读写操作,那这些任务可能永远等不到事件(因为任务有可能是一直在等待事件发生的),使用 while 循环保证所有的任务都会被恢复

(3)调用 xTaskRemoveFromUnorderedEventList()函数将任务从等待事件列表中移除,然后添加到就绪列表中,参与任务调度,当然,因为挂起了调度器,所以在这段时间里,即使是优先级更高的任务被添加到就绪列表,系统也不会进行任务调度,所以也就不会影响当前任务删除事件的操作,这也是为什么需要挂起调度器的原因。但是,使用事件删除函数vEventGroupDelete()的时候需要注意,尽量在没有任务阻塞在这个事件的时候进行删除,否则任务无法等到正确的事件,因为删除之后,所有被恢复的任务都只能获得事件的值为0

(4)释放事件的内存,因为在创建事件的时候申请了内存的,在不使用事件的时候就把内核还给系统

(5)恢复调度器,之前的操作是恢复了任务,现在恢复调度器,那么处于就绪态的最高优先级任务将被运行

2.3 事件组置位(任务) xEventGroupSetBits() / xEventGroupSetBitsFromISR()(中断)


(1)断言,判断要设置的事件标志位是否有效,因为一个32 位的事件标志组变量只有24 位是用于设置事件的,而 16 位的事件标志组变量只有8 位用于设置事件,高8 位不允许设置事件,有其他用途

(2)挂起调度器,因为接下来的操作不知道需要多长的时间,因为需要遍历等待事件列表,并且有可能不止一个任务在等待事件,所以在满足任务等待的事件时候,任务允许被恢复,但是不允许运行,只有遍历完成的时候,任务才能被系统调度,在遍历期间,系统也不希望其他任务来操作这个事件标志组,所以暂时把调度器挂起,让当前任务占有CPU

(3)根据用户指定的uxBitsToSet 设置事件标志位

(4)设置这个事件标志位可能是某个任务在等待的事件,就需要遍历等待事件列表中的任务,看看这个事件是否与任务等待的事件匹配

(5)获取要等待事件的标记信息,是逻辑与还是逻辑或

(6)再获取任务的等待事件是什么

(7)如果只需要有任意一个事件标志位满足唤醒任务(也是我们常说的"逻辑或"),那么还需要看看是否有这个事件发生了

(8)判断要等待的事件是否发生了,发生了就需要把任务恢复,在这里记录一下要恢复的任务

(9)如果任务等待的事件都要发生的时候(也是我们常说的"逻辑与"),就需要就要所有判断事件标志组中的事件是否都发生,如果是的话任务才能从阻塞中恢复,同样也需要标记一下要恢复的任务

(10)这里是FreeRTOS 暂时不用的,暂时不用理会

(11)找到能恢复的任务,然后看下是否需要清除标志位,如果需要,就记录下需要清除的标志位,等遍历完队列之后统一处理,注意了,在一找到的时候不能清除,因为后面有可能一样有任务等着这个事件,只能在遍历任务完成之后才能清除事件标志位

(12)运用或运算,标记一下要清除的事件标志位是哪些

(13)将满足事件条件的任务从等待列表中移除,并且添加到就绪列表中

(14)循环遍历事件等待列表,可能不止一个任务在等待这个事件

(15)遍历完毕,清除事件标志位

(16)恢复调度器,之前的操作是恢复了任务,现在恢复调度器,那么处于就绪态的最高优先级任务将被运行

(17)返回用户设置的事件标志位值

2.4 等待事件 xEventGroupWaitBits()

  • 这个函数实现了等待超时机制,当且仅当任务等待的事件发生时,任务才能获取到事件信息。在这段时间中,如果事件一直没发生,该任务将保持阻塞状态以等待事件发生。当其它任务或中断服务程序往其等待的事件设置对应的标志位,该任务将自动由阻塞态转为就绪态。

  • 当任务等待的时间超过了指定的阻塞时间,即使事件还未发生,任务也会自动从阻塞态转移为就绪态。这样子很有效的体现了操作系统的实时性,如果事件正确获取(等待到)则返回对应的事件标志位,由用户判断再做处理,因为在事件超时的时候也会返回一个不能确定的事件值,所以需要判断任务所等待的事件是否真的发生。

当用户调用这个函数接口时,系统首先根据用户指定参数和接收选项来判断它要等待的事件是否发生,如果已经发生,则根据参数 xClearOnExit 来决定是否清除事件的相应标志位,并且返回事件标志位的值,但是这个值并不是一个稳定的值,所以在等待到对应事件的时候,还需我们判断事件是否与任务需要的一致; 如果事件没有发生,则把任务添加到事件等待列表中,把任务感兴趣的事件标志值和等待选项填用列表项的值来表示,直到事件发生或等待时间超时

(1)挂起调度器

**(2)先看下当前事件中的标志位是否已经满足条件了任务等待的事件,prvTestWaitCondition()函数其实就是判断一下用户等待的事件是否与当前事件标志位一致。

(3)满足条件了,就可以直接返回了,注意这里返回的是的当前事件的所有标志位,所以这是一个不确定的值,需要用户自己判断一下是否满足要求。然后把用户指定的等待超时时间xTicksToWait也重置为0,这样子等下就能直接退出函数返回了

(4)看看在退出的时候是否需要清除对应的事件标志位,如果xClearOnExit为pdTRUE则需要清除事件标志位,如果为pdFALSE就不需要清除

(5)当前事件中不满足任务等待的事件,并且用户指定不进行等待,那么可以直接退出,同样也会返回当前事件的所有标志位,所以在使用 xEventGroupWaitBits()函数的时候需要对返回值做判断,保证等待到的事件是任务需要的事件

(6)而如果用户指定超时时间了,并且当前事件不满足任务的需求,那任务就进入等待状态以等待事件的发生

(7)将当前任务添加到事件等待列表中,任务将被阻塞指定时间 xTicksToWait,并且这个列表项的值是用于保存任务等待事件需求的信息标记,以便在事件标志位置位的时候对等待事件的任务进行相应的操作

(8)恢复调度器

(9)在恢复调度器的时候,如果有更高优先级的任务恢复了,那么就进行一次任务的切换

(10)程序能进入到这里说明当前的任务已经被重新调度了,调用 uxTaskResetEventItemValue()返回并重置xEventListItem的值,因为之前事件列表项的值被保存起来了,现在取出来看看是不是有事件发生

(11)如果仅仅是超时返回,那系统就会直接返回当前事件的所有标志位

(12)再判断一次是否发生了事件

(13)如果发生了,那就清除事件标志位并且返回

(14)否则就返回事件所有标志位,然后退出

2.5 事件组清位(任务) xEventGroupClearBits() / xEventGroupClearBitsFromISR()(中断)

相关推荐
一切皆是因缘际会2 小时前
量化阈值拆解|2026端侧AI复盘
人工智能·架构·系统架构
@insist1232 小时前
系统架构设计师-操作系统核心原理与分类体系
分类·数据挖掘·系统架构·软考·系统架构设计师·软件水平考试
慧一居士1 天前
Nginx如何设置图片防盗链
系统架构·安全架构
名字不好奇1 天前
Agent系统架构设计:从执行循环到智能协作
系统架构
@insist1231 天前
系统架构设计师-区块链安全架构原理与安全系统设计实战
安全·系统架构·区块链·软考·软件水平考试
@insist1232 天前
系统架构设计师-从 PDR到 WPDRRC 的模型演进与架构实践
架构·系统架构·软考·系统架构设计师·软件水平考试
@insist1232 天前
系统架构设计师-基于 GB/T 9387.2 标准的网络安全架构
web安全·架构·系统架构·软考·系统架构设计师·软件水平考试
RockHopper20252 天前
解读企业双层活动模型的状态管理原理
系统架构·运行语义·语义操作