一、事件的基本概念
事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,只传递事件类型,无数据传输
可以是一个事件发生就唤醒任务进行事件处理,也可以是几个事件都发生后才唤醒任务进行事件处理
事件组:使用8位或者24位的变量存储事件,每一位代表一个事件,任务通过“逻辑与”或者“逻辑或”与一个或者多个事件建立关联,形成事件组
事件的“逻辑或”,也称独步型同步,任务感兴趣的所有事件中任一事件发生即可被唤醒
事件的“逻辑与”,也称关联型同步,任务感兴趣的所有事件都发生时才被唤醒
FreeRTOS提供的事件特点:
(1)事件只与任务相关联,事件与事件之间是相互独立的
(2)事件仅用于同步,不提供数据传输
(3)事件无排队行,即多次向任务设置同一事件(如果事件未被读取),等效于只设置了一次
(4)允许多个任务对同一事件进行读写操作
(5)支持超时机制
事件信息标记有3个属性:逻辑与、逻辑或、是否清除标记
二、事件的应用场景
三、事件的运作机制
1.接收事件:任务根据感兴趣的事件类型接收单个或者多个事件,事件读取模式:等待所有感兴趣事件(逻辑与)、等待感兴趣事件中的任一事件(逻辑或)
2.设置事件:对指定事件写入指定事件类型,即对应事件未置1
3.清除事件:根据写入的参数事件句柄和等待清除的事件类型,对事件对应位进行清零操作
4.事件唤醒机制:当任务因为等待某个或多个事件发生阻塞状态,当事件发生时会被唤醒,如果在接收事件的函数中设置了xClearOnExit,当任务唤醒后,事件标志位清零
四、事件控制块
五、事件函数
1.事件创建函数xEventGroupCreate
创建函数主要进行了事件控制块的内存申请,及初始化(包括事件组变量置0,等待列表初始化),创建成功,则返回事件句柄
2.事件删除函数vEventGroupDelete()
将等待列表中的任务从列表中移除,并添加到就绪列表,最后释放内存
任务从阻塞状态移除,并添加到就绪列表的思想:先获取节点任务控制块,等待列表节点自身删除,任务控制块状态节点xStateListItem删除,即不与任何链表关联,最后任务控制块添加到就绪列表
3.事件组置位函数xEventGroupSetBits()
目的:事件组中指定的位置位,阻塞在该位的任务将被解锁,
思路:
(1)将事件组对应位置位
(2)逐项获取等待事件列表中每个节点的等待事件
(3)节点中对应等待的事件进行分析:事件分两部分,高8位是事件标记,低24位为事件类型对应的位;将两部分单独分离保存在uxControlBits和uxBitsWaitedFor,此处需要理解高8位对应的每个位的作用;
等待事件为逻辑或的情况:判断当前事件是否与等待事件对应得上,如果是,则进行匹配标记
等待事件为逻辑与的情况:判断要等待的时间都发生,则进行标记
两种情况都不是,则不做处理,循环获取等待列表中下一个项的等待事件并做分析
(4)等待事件匹配之后,将事件标志信息标记为解锁,并将任务从事件等待列表移除,添加到就绪列表中,判断要等待的事件是否清除标志,如果需要清除事件,在循环检索完所有等待事件后才进行清除事件标志
4.中断版本事件组置位函数xEventGroupSetBitsFromISR()
FreeRTOS中不允许不确定的操作在中断和临界段中发生,因此xEventGroupSetBitsFromISR是给守护任务发送一个消息,让置位事件组的操作在守护任务中完成
5.等待事件函数xEventGroupWaitBits()
设计思想:
(1)先判断事件组中的事件是否满足当前等待的事件,如果满足则返回,并根据退出清除标志位对事件标志位进行复位清除
(2)事件组中没有满足的事件,并且不等待,直接返回
(3)事件组中没有满足的事件,并且设置了等待时间,需要根据等待函数的参数对事件标记信息进行赋值:包括事件退出清除标记xClearOnExit,事件的逻辑与或者逻辑或的标记xWaitForAllBits
(4)将当前任务添加到事件等待列表中,且根据延时将任务添加到等待延时列表,这里迁出了任务控制块的一个成员变量事件节点:xEventListItem,用于挂载到事件组控制块的事件等待链表中,也就是这个变量使得任务与事件等待链表建立了关联
(5)接触调度器挂起之后,会进行任务切换,当任务再度被调度的时候,有两种情况:一是任务等待的事件被置位;另外一种情况是等待延时到时;
任务控制块中xEventListItem节点的值包含了eventUNBLOCKED_DUE_TO_BIT_SET,则认为是事件已经被置位,再判断事件满足情况,
调用等待函数,先判断要等待的事件是否发生,如果已发生,根据xClearOnExit决定是否清除事件相应标志位,并返回事件标志位的值;如果事件没有发生,把任务添加到等待列表,把任务感兴趣的时间标志值(高8位)和等待选项(低24位)用列表项的值表示,知道事件发生或者等待事件超时
6.清除事件组指定位函数xEventGroupClearBits()与xEventGroupClearBits()FromISR
学习心得:
1.理解事件控制块的内容,主要包括一个32位变量用作保存事件信息,高8位用于记录事件标记信息,低24位用于记录事件的类型,每种事件对应一个比特位;另外包括一个事件等待链表,用于保存等待事件的任务,链表的链表项或者说节点,是任务控制块中的xEventListItem这个成员变量
2.理解任务控制块中添加了一个列表项的成员变量xEventListItem,该成员变量将任务与事件等待链表进行了关联,其中链表项(或者说节点)的值就是事件信息,包括事件类型和事件标记信息
3.事件创建,申请内存,初始化事件,初始化事件等待链表
4.删除事件的时候,需要将等待链表中的节点删除,同时需要将事件对应等待链表中的任务从阻塞状态恢复到就绪状态,最后释放内存
5.事件置位,就是跟事件控制块的第一个成员变量赋值,并根据赋值后的事件变量的值,去循环查找等待事件链表中的任务等待的对应事件,如过事件满足,则任务从等待事件链表中移除,从阻塞状态恢复到就绪状态
6.等待事件:主要是将任务添加到等待链表中,等待有事件置位的时候能有任务执行,添加到链表中的链表项(或者说节点)的值是根据等待函数的参数进行配置,高8位为事件标志记录包括“逻辑与”“逻辑或”事件、任务执行后事件清除标志、任务可执行标志;低8位为事件的值