天天看点

社区新人的RT-Thread学习笔记5——事件集

本文学习RT-Thread的事件集,事件集也是线程间同步的机制之一,一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。将理论讲事件集的工作机制以及相关函数,后面用RTT&正点原子联合出品的潘多拉开发板进行实验。

1、一个线程与多个事件的关系可设置为:其中任意一个事件唤醒线程,或几个事件都到达后才唤醒线程进行后续的处理;同样,事件也可以是多个线程同步多个事件。

2、RT-Thread 定义的事件集有以下特点:(1)事件只与线程相关,事件间相互独立。(2)事件仅用于同步,不提供数据传输功能;(3)事件无排队性,即多次向线程发送同一事件 (如果线程还未来得及读走),其效果等同于只发送一次。

3、每个线程都拥有一个事件信息标记,它有三个属性,分别是 <code>RT_EVENT_FLAG_AND</code>(逻辑与),<code>RT_EVENT_FLAG_OR</code>(逻辑或)以及 <code>RT_EVENT_FLAG_CLEAR</code>(清除标记)。当线程等待事件同步时,可以通过 32 个事件标志和这个事件信息标记来判断当前接收的事件是否满足同步条件。 如下图所示,线程 #1 的事件标志中第 1 位和第 30 位被置位,如果事件信息标记位设为逻辑与,则表示线程 #1 只有在事件 1 和事件 30 都发生以后才会被触发唤醒,如果事件信息标记位设为逻辑或,则事件 1 或事件 30 中的任意一个发生都会触发唤醒线程 #1。如果信息标记同时设置了清除标记位,则当线程 #1 唤醒后将主动把事件 1 和事件 30 清为零,否则事件标志将依然存在(即置 1)。

社区新人的RT-Thread学习笔记5——事件集

事件集工作示意图(来源RT-Thread编程指南)

当创建一个事件集时,内核首先创建一个事件集控制块,然后对该事件集控制块进行基本的初始化。

(1)入口参数:

name:事件集的名称。

flag:事件集的标志,它可以取如下数值:<code>RT_IPC_FLAG_FIFO</code> 或<code>RT_IPC_FLAG_PRIO</code>。

(2)返回值:

RT_NULL:创建失败。

事件对象的句柄:创建成功。

系统不再使用 rt_event_create() 创建的事件集对象时,通过删除事件集对象控制块来释放系统资源。在删除一个事件集对象时,应该确保该事件集不再被使用。在删除前会唤醒所有挂起在该事件集上的线程(线程的返回值是RT_ERROR),然后释放事件集对象占用的内存块。

event:事件集对象的句柄。

RT_EOK:成功。

这里所说的创建静态事件集和《RT-Thread编程指南》所说的初始化事件集是一样的,静态事件集对象的内存是在系统编译时由编译器分配的,一般放于读写数据段或未初始化数据段中。

flag:事件集的标志,它可以取如下数值:<code>RT_IPC_FLAG_FIFO</code> 或 <code>RT_IPC_FLAG_PRIO</code>。

当系统不再使用 <code>rt_event_init()</code> 初始化的事件集对象时,通过脱离事件集对象控制块来释放系统资源,系统首先唤醒所有挂在该事件集等待队列上的线程(线程的返回值是<code>RT_ERROR</code>),然后将该事件集从内核对象管理器中脱离。
发送事件函数可以发送事件集中的一个或多个事件,使用该函数接口时,通过参数 set 指定的事件标志来设定 event 事件集对象的事件标志值,然后遍历等待在 event 事件集对象上的等待线程链表,判断是否有线程的事件激活要求与当前 event 对象事件标志值匹配,如果有,则唤醒该线程。

set:发送的一个或多个事件的标志值。

内核使用 32 位的无符号整数来标识事件集,它的每一位代表一个事件,因此一个事件集对象可同时等待接收 32 个事件,内核可以通过指定选择参数 “逻辑与” 或 “逻辑或” 来选择如何激活线程,使用 “逻辑与” 参数表示只有当所有等待的事件都发生时才激活线程,而使用 “逻辑或” 参数则表示只要有一个等待的事件发生就激活线程。 系统首先根据 set 参数和接收选项 option 来判断它要接收的事件是否发生,如果已经发生,则根据参数 option 上是否设置有 <code>RT_EVENT_FLAG_CLEAR</code> 来决定是否重置事件的相应标志位,然后返回(其中 recved 参数返回接收到的事件);如果没有发生,则把等待的 set 和 option 参数填入线程本身的结构中,然后把线程挂起在此事件上,直到其等待的事件满足条件或等待时间超过指定的超时时间。如果超时时间设置为零,则表示当线程要接受的事件没有满足其要求时就不等待,而直接返回<code>RT_ETIMEOUT</code>。

set:接收线程感兴趣的事件。

option:接收选项。

timeout:指定超时时间。

recved:指向接收到的事件。

RT_ETIMEOUT:超时。

RT_ERROR:错误。

前面讲了RT-Thread事件集的一些理论知识,光说不练都是假把式,那么接下来进行实际的操作。创建一个事件集和两个线程,一个线程用于发送事件,另一个线程用于接收事件,实体RTT&amp;正点原子联合出品潘多拉开发板进行实验,实现事件标志位或触发线程、事件标志位与触发线程,通过按键来发送事件标志位,或触发时蜂鸣器响一下,与触发RGB红灯亮一下。

1、实现代码

2、观察FinSH

(1)当按下KEY0或KEY1时,发送事件标志FLAG3或FLAG5,这个时候蜂鸣器响:

社区新人的RT-Thread学习笔记5——事件集

(2)当按下KEY0和KEY1时,发送事件标志FLAG3和FLAG5,这个时候RGB红灯亮一下:

社区新人的RT-Thread学习笔记5——事件集

RT-Thread

让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。Apache2.0协议,可免费在商业产品中使用,不需要公布源码,无潜在商业风险。

长按二维码,关注我们

下一篇: javaweb