4.5 事件
基本概念
多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步。事件可以提供一对多、多对多的同步操作。一对多同步模型:一个任务等待多个事件的触发;多对多同步模型:多个任务等待多个事件的触发。
任务可以通过创建事件控制块来实现对事件的触发和等待操作。Huawei LiteOS的事件仅用于任务间的同步,不提供数据传输功能。
Huawei LiteOS提供的事件具有如下特点:
事件不与任务相关联,事件相互独立,一个32位的变量,用于标识该任务发生的事件类型,其中每一位表示一种事件类型(0表示该事件类型未发生、1表示该事件类型已经发生),一共31种事件类型(第25位保留)。
事件仅用于任务间的同步,不提供数据传输功能。
多次向任务发送同一事件类型,等效于只发送一次。
允许多个任务对同一事件进行读写操作。
支持事件读写超时机制。
事件控制块
:用于标识该任务发生的事件类型,其中每一位表示一种事件类型(0表示该事件类型未发生、1表示该事件类型已经发生),一共31种事件类型,第25位系统保留。
事件读取模式
在读事件时,可以选择读取模式。读取模式如下:
所有事件(LOS_WAITMODE_AND):读取掩码中所有事件类型,只有读取的所有事件类型都发生了,才能读取成功。
任一事件(LOS_WAITMODE_OR): 读取掩码中任一事件类型,读取的事件中任意一种事件类型发生了,就可以读取成功。
运作机制
读事件时,可以根据入参事件掩码类型uwEventMask读取事件的单个或者多个事件类型。事件读取成功后,如果设置LOS_WAITMODE_CLR会清除已读取到的事件类型,反之不会清除已读到的事件类型,需显式清除。可以通过入参选择读取模式,读取事件掩码类型中所有事件还是读取事件掩码类型中任意事件。
写事件时,对指定事件写入指定的事件类型,可以一次同时写多个事件类型。写事件会触发任务调度。
清除事件时,根据入参事件和待清除的事件类型,对事件对应位进行清0操作。
事件唤醒任务示意图
使用场景
事件可应用于多种任务同步场合,能够一定程度替代信号量。
功能
Huawei LiteOS系统中的事件模块为用户提供下面几个接口。
开发流程
使用事件模块的典型流程如下:
调用事件初始化LOS_EventInit接口,初始化事件等待队列。
读事件LOS_EventRead,可以选择读取模式。
清除事件LOS_EventClear,清除指定的事件类型。
Event错误码
对事件存在失败的可能性操作,包括事件初始化,事件销毁,事件读写,时间清除。
序号 | 定义 | 实际值 | 描述 | 参考解决方案 |
---|---|---|---|---|
1 | LOS_ERRNO_EVENT_SETBIT_INVALID | 0x02001c00 | 事件ID的第25个bit不能设置为1,因为该位已经作为错误码使用 | 事件ID的第25bit置为0 |
2 | LOS_ERRNO_EVENT_READ_TIMEOUT | 0x02001c01 | 读超时 | 增加等待时间或者重新读取 |
3 | LOS_ERRNO_EVENT_EVENTMASK_INVALID | 0x02001c02 | 入参的事件ID是无效的 | 传入有效的事件ID参数 |
4 | LOS_ERRNO_EVENT_READ_IN_INTERRUPT | 0x02001c03 | 在中断中读取事件 | 启动新的任务来获取事件 |
5 | LOS_ERRNO_EVENT_FLAGS_INVALID | 0x02001c04 | 读取事件的mode无效 | 传入有效的mode参数 |
6 | LOS_ERRNO_EVENT_READ_IN_LOCK | 0x02001c05 | 任务锁住,不能读取事件 | 解锁任务,再读取事件 |
7 | LOS_ERRNO_EVENT_PTR_NULL | 0x02001c06 | 传入的参数为空指针 | 传入非空入参 |
错误码定义: 错误码是一个32位的存储单元,31~24位表示错误等级,23~16位表示错误码标志,15~8位代表错误码所属模块,7~0位表示错误码序号,如下
例如:
平台差异性
在系统初始化之前不能调用读写事件接口。如果调用,则系统运行会不正常。
在中断中,可以对事件对象进行写操作,但不能读操作。
在锁任务调度状态下,禁止任务阻塞与读事件。
LOS_EventClear 入参值是:要清除的指定事件类型的反码(~uwEvents)。
事件掩码的第25位不能使用,原因是为了区别LOS_EventRead接口返回的是事件还是错误码。
实例描述
示例中,任务Example_TaskEntry创建一个任务Example_Event,Example_Event读事件阻塞,Example_TaskEntry向该任务写事件。
在任务Example_TaskEntry创建任务Example_Event,其中任务Example_Event优先级高于Example_TaskEntry。
在任务Example_Event中读事件0x00000001,阻塞,发生任务切换,执行任务Example_TaskEntry。
在任务Example_TaskEntry向任务Example_Event写事件0x00000001,发生任务切换,执行任务Example_Event。
Example_Event得以执行,直到任务结束。
编程示例
可以通过打印的先后顺序理解事件操作时伴随的任务切换。
代码实现如下:
结果验证
编译运行得到的结果为: