一、事件的基本概念

事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,只传递事件类型,无数据传输

可以是一个事件发生就唤醒任务进行事件处理,也可以是几个事件都发生后唤醒任务进行事件处理

事件组:使用8位或者24位的变量存储事件,每一位代表一个事件,任务通过“逻辑与”或者“逻辑或”一个或者多个事件建立关联,形成事件组

事件的“逻辑或”,也称独步型同步,任务感兴趣的所有事件中任一事件发生即可被唤醒

事件的“逻辑与”,也称关联型同步,任务感兴趣的所有事件都发生时才被唤醒

FreeRTOS提供的事件特点:

(1)事件只与任务相关联,事件与事件之间是相互独立的

(2)事件仅用于同步,不提供数据传输

(3)事件无排队行,即多次向任务设置同一事件(如果事件未被读取),等效于只设置了一次

(4)允许多个任务对同一事件进行读写操作

(5)支持超时机制

事件信息标记有3个属性:逻辑与逻辑或是否清除标记

二、事件的应用场景

三、事件的运作机制

1.接收事件:任务根据感兴趣的事件类型接收单个或者多个事件,事件读取模式:等待所有感兴趣事件(逻辑与)、等待感兴趣事件中的任一事件(逻辑或)

2.设置事件:对指定事件写入指定事件类型,即对应事件未置1

3.清除事件:根据写入的参数事件句柄和等待清除的事件类型,对事件对应位进行清零操作

4.事件唤醒机制:当任务因为等待某个或多个事件发生阻塞状态,当事件发生时会被唤醒,如果在接收事件的函数中设置了xClearOnExit,当任务唤醒后,事件标志位清零

第18章 事件_任务控制块

四、事件控制块

第18章 事件_等待事件_02

五、事件函数

1.事件创建函数xEventGroupCreate

创建函数主要进行了事件控制块的内存申请,及初始化(包括事件组变量置0,等待列表初始化),创建成功,则返回事件句柄

第18章 事件_链表_03

2.事件删除函数vEventGroupDelete()

将等待列表中的任务从列表中移除,并添加到就绪列表,最后释放内存

第18章 事件_链表_04

任务从阻塞状态移除,并添加到就绪列表的思想:先获取节点任务控制块,等待列表节点自身删除,任务控制块状态节点xStateListItem删除,即不与任何链表关联,最后任务控制块添加到就绪列表

第18章 事件_等待事件_05

3.事件组置位函数xEventGroupSetBits()

目的:事件组中指定的位置位,阻塞在该位的任务将被解锁,

思路:

(1)将事件组对应位置位

(2)逐项获取等待事件列表中每个节点的等待事件

(3)节点中对应等待的事件进行分析:事件分两部分,高8位是事件标记,低24位为事件类型对应的位;将两部分单独分离保存在uxControlBits和uxBitsWaitedFor,此处需要理解高8位对应的每个位的作用;

第18章 事件_链表_06

等待事件为逻辑或的情况:判断当前事件是否与等待事件对应得上,如果是,则进行匹配标记

等待事件为逻辑与的情况:判断要等待的时间都发生,则进行标记

两种情况都不是,则不做处理,循环获取等待列表中下一个项的等待事件并做分析

(4)等待事件匹配之后,将事件标志信息标记为解锁,并将任务从事件等待列表移除,添加到就绪列表中,判断要等待的事件是否清除标志,如果需要清除事件,在循环检索完所有等待事件后才进行清除事件标志

第18章 事件_链表_07

第18章 事件_任务控制块_08


4.中断版本事件组置位函数xEventGroupSetBitsFromISR()

FreeRTOS中不允许不确定的操作在中断和临界段中发生,因此xEventGroupSetBitsFromISR是给守护任务发送一个消息,让置位事件组的操作在守护任务中完成

第18章 事件_链表_09

5.等待事件函数xEventGroupWaitBits()

设计思想:

(1)先判断事件组中的事件是否满足当前等待的事件,如果满足则返回,并根据退出清除标志位对事件标志位进行复位清除

(2)事件组中没有满足的事件,并且不等待,直接返回

(3)事件组中没有满足的事件,并且设置了等待时间,需要根据等待函数的参数对事件标记信息进行赋值:包括事件退出清除标记xClearOnExit,事件的逻辑与或者逻辑或的标记xWaitForAllBits

(4)将当前任务添加到事件等待列表中,且根据延时将任务添加到等待延时列表,这里迁出了任务控制块的一个成员变量事件节点:xEventListItem,用于挂载到事件组控制块的事件等待链表中,也就是这个变量使得任务与事件等待链表建立了关联

第18章 事件_链表_10


第18章 事件_任务控制块_11

(5)接触调度器挂起之后,会进行任务切换,当任务再度被调度的时候,有两种情况:一是任务等待的事件被置位;另外一种情况是等待延时到时;

任务控制块中xEventListItem节点的值包含了eventUNBLOCKED_DUE_TO_BIT_SET,则认为是事件已经被置位,再判断事件满足情况,

第18章 事件_链表_12

调用等待函数,先判断要等待的事件是否发生,如果已发生,根据xClearOnExit决定是否清除事件相应标志位,并返回事件标志位的值;如果事件没有发生,把任务添加到等待列表,把任务感兴趣的时间标志值(高8位)和等待选项(低24位)用列表项的值表示,知道事件发生或者等待事件超时

6.清除事件组指定位函数xEventGroupClearBits()与xEventGroupClearBits()FromISR

第18章 事件_链表_13


学习心得:

1.理解事件控制块的内容,主要包括一个32位变量用作保存事件信息高8位用于记录事件标记信息低24位用于记录事件的类型,每种事件对应一个比特位;另外包括一个事件等待链表,用于保存等待事件的任务链表的链表项或者说节点,是任务控制块中的xEventListItem这个成员变量

2.理解任务控制块中添加了一个列表项的成员变量xEventListItem,该成员变量将任务事件等待链表进行了关联,其中链表项(或者说节点)的值就是事件信息,包括事件类型事件标记信息

3.事件创建,申请内存,初始化事件,初始化事件等待链表

4.删除事件的时候,需要将等待链表中的节点删除,同时需要将事件对应等待链表中的任务从阻塞状态恢复到就绪状态,最后释放内存

5.事件置位,就是跟事件控制块的第一个成员变量赋值,并根据赋值后的事件变量的值,去循环查找等待事件链表中的任务等待的对应事件,如过事件满足,则任务从等待事件链表中移除,从阻塞状态恢复到就绪状态

6.等待事件:主要是将任务添加到等待链表中,等待有事件置位的时候能有任务执行,添加到链表中的链表项(或者说节点)的值是根据等待函数的参数进行配置高8位为事件标志记录包括“逻辑与”“逻辑或”事件、任务执行后事件清除标志、任务可执行标志低8位为事件的值