liteos事件(六)
1. 概述
1.1 基本概念
事件是一种实现任务间通信的机制,可用于实现任务间的同步,但事件通信只能是事件类型的通信,无数据传输。一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。事件集合用32位无符号整型变量来表示,每一位代表一个事件。
多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步。事件可以提供一对多、多对多的同步操作。一对多同步模型:一个任务等待多个事件的触发;多对多同步模型:多个任务等待多个事件的触发。
任务可以通过创建事件控制块来实现对事件的触发和等待操作。 Huawei LiteOS的事件仅用于任务间的同步,不提供数据传输功能。
Huawei LiteOS提供的事件具有如下特点:
- 事件不与任务相关联,事件相互独立,一个32位的变量,用于标识该任务发生的事件类型,其中每一位表示一种事件类型(0表示该事件类型未发生、 1表示该事件类型已经发生),一共31种事件类型(第25位保留)。
 - 事件仅用于任务间的同步,不提供数据传输功能。
 - 多次向任务发送同一事件类型,等效于只发送一次。
 - 允许多个任务对同一事件进行读写操作。
 - 支持事件读写超时机制。
 
1.2 事件控制块
/**
* @ingroup los_event
* Event control structure
*/
typedef struct tagEvent
{
UINT32 uwEventID; /**标识发生的事件类型位*/
LOS_DL_LIST stEventList; /**读取事件任务链表*/
} EVENT_CB_S, *PEVENT_CB_S;
uwEventID:用于标识该任务发生的事件类型,其中每一位表示一种事件类型(0表示该事件类型未发生、 1表示该事件类型已经发生),一共31种事件类型,第25位系统保留。
1.3 事件读取模式
在读事件时,可以选择读取模式。读取模式如下:
所有事件(LOS_WAITMODE_AND):读取掩码中所有事件类型,只有读取的所有事件类型都发生了,才能读取成功。
任一事件(LOS_WAITMODE_OR): 读取掩码中任一事件类型,读取的事件中任意一种事件类型发生了,就可以读取成功。
清除事件(LOS_WAITMODE_CLR): LOS_WAITMODE_AND|
LOS_WAITMODE_CLR或 LOS_WAITMODE_OR| LOS_WAITMODE_CLR 时表示读取成功后,对应事件类型位会自动清除。
2. 运作机制
读事件时,可以根据入参事件掩码类型uwEventMask读取事件的单个或者多个事件类型。事件读取成功后,如果设置LOS_WAITMODE_CLR会清除已读取到的事件类型,反之不会清除已读到的事件类型,需显式清除。可以通过入参选择读取模式,读取事件掩码类型中所有事件还是读取事件掩码类型中任意事件。
写事件时,对指定事件写入指定的事件类型,可以一次同时写多个事件类型。写事件会触发任务调度。
清除事件时,根据入参事件和待清除的事件类型,对事件对应位进行清0操作。

3. 开发指导
3.1 使用场景
事件可应用于多种任务同步场合,能够一定程度替代信号量。
3.2 功能
Huawei LiteOS系统中的事件模块为用户提供下面几个接口。
| 功能分类 | 接口名 | 描述 | 
|---|---|---|
| 事件初始化 | LOS_EventInit | 初始化一个事件控制块 | 
| 读事件 | LOS_EventRead | 读取指定事件类型,超时时间为相对时间:单位为Tick | 
| 写事件 | LOS_EventWrite | 写指定的事件类型 | 
| 清除事件 | LOS_EventClear | 清除指定的事件类型 | 
| 校验事件掩码 | LOS_EventPoll | 根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期 | 
| 销毁事件 | LOS_EventDestroy | 销毁指定的事件控制块 | 
3.3 开发流程
使用事件模块的典型流程如下:
- 调用事件初始化LOS_EventInit接口,初始化事件等待队列。
 - 写事件LOS_EventWrite,配置事件掩码类型。
 - 读事件LOS_EventRead,可以选择读取模式。
 - 清除事件LOS_EventClear,清除指定的事件类型。
 
3.4 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位表示错误码序号,如下
#define LOS_ERRNO_OS_ERROR(MID, ERRNO) \
(LOS_ERRTYPE_ERROR | LOS_ERRNO_OS_ID | ((UINT32)(MID) << 8) | (ERRNO))
LOS_ERRTYPE_ERROR: Define critical OS errors
LOS_ERRNO_OS_ID: OS error code flag
MID: OS_MOUDLE_ID
LOS_MOD_EVENT: Event module ID
ERRNO: error ID number
例如:
#define LOS_ERRNO_EVENT_READ_IN_LOCK
LOS_ERRNO_OS_ERROR(LOS_MOD_EVENT, 0x05)
3.5 平台差异性
无
4. 注意事项
- 在系统初始化之前不能调用读写事件接口。如果调用,则系统运行会不正常。
 - 在中断中,可以对事件对象进行写操作,但不能读操作。
 - 在锁任务调度状态下,禁止任务阻塞与读事件。
 - LOS_EventClear 入参值是:要清除的指定事件类型的反码(~uwEvents)。
 - 事件掩码的第25位不能使用,原因是为了区别LOS_EventRead接口返回的是事件还是错误码。
 
5. 编程实例
5.1 实例描述
示例中,任务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得以执行,直到任务结束。
 - Example_TaskEntry得以执行,直到任务结束。
 
5.2 编程示例
可以通过打印的先后顺序理解事件操作时伴随的任务切换。
代码实现如下:
#include "los_event.h"
#include "los_task.h"
/*任务PID*/
UINT32 g_TestTaskID01;
/*事件控制结构体*/
EVENT_CB_S example_event;
/*等待的事件类型*/
#define event_wait 0x00000001
/*用例任务入口函数*/
VOID Example_Event()
{
    UINT32 uwRet;
    UINT32 uwEvent;
    /*超时 等待方式读事件,超时时间为100 Tick若100 Tick 后未读取到指定事件,读事件超时,任务直接唤醒*/
    printf("Example_Event wait event 0x%x \n",event_wait);
    uwEvent = LOS_EventRead(&example_event, event_wait, LOS_WAITMODE_AND, 100);
    if(uwEvent == event_wait)
    {
        printf("Example_Event,read event :0x%x\n",uwEvent);
    }
    else
        printf("Example_Event,read event timeout\n");
    return;
}
UINT32 Example_TaskEntry()
{
    UINT32 uwRet;
    TSK_INIT_PARAM_S stTask1;
    /*事件初始化*/
    uwRet = LOS_EventInit(&example_event);
    if(uwRet != LOS_OK)
    {
        printf("init event failed .\n");
        return -1;
    }
    /*创建任务*/
    memset(&stTask1, 0, sizeof(TSK_INIT_PARAM_S));
    stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Event;
    stTask1.pcName = "EventTsk1";
    stTask1.uwStackSize = OS_TSK_DEFAULT_STACK_SIZE;
    stTask1.usTaskPrio = 5;
    uwRet = LOS_TaskCreate(&g_TestTaskID01, &stTask1);
    if(uwRet != LOS_OK)
    {
        printf("task create failed .\n");
        return LOS_NOK;
    }
    /*写用例任务等待的事件类型*/
    printf("Example_TaskEntry write event .\n");
    uwRet = LOS_EventWrite(&example_event, event_wait);
    if(uwRet != LOS_OK)
    {
        printf("event write failed .\n");
        return LOS_NOK;
    }
    /*清标志位*/
    printf("EventMask:%d\n",example_event.uwEventID);
    LOS_EventClear(&example_event, ~example_event.uwEventID);
    printf("EventMask:%d\n",example_event.uwEventID);
    /*删除任务*/
    uwRet = LOS_TaskDelete(g_TestTaskID01);
    if(uwRet != LOS_OK)
    {
        printf("task delete failed .\n");
        return LOS_NOK;
    }
    return LOS_OK;
}
5.3 结果验证
编译运行得到的结果为:
Example_Event wait event 0x1
Example_TaskEntry write event .
Example_Event,read event :0x1
EventMask:1
EventMask:0
												
											liteos事件(六)的更多相关文章
- jQuery 学习之路(4):事件
		
一.文档载入事件 二.事件绑定 三.事件对象 四.浏览器事件 五.表单事件 六.键盘事件 七.鼠标事件
 - JS 点击事件学习总结
		
废话篇: 在我们编写无论什么网页内容的时候我们总是或多或少的要接触到点击事件这一范畴的,写过几个简短的demo和网页之后,感觉自己对电机事件一类的东西了解也更为的清楚了,之前写过很多零零散散的东西现在 ...
 - JAVA之旅(三十一)——JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件
		
JAVA之旅(三十一)--JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件 有段时间没有更新JAVA了,我们今天来说一下JAVA中的图形化界面,也就是GUI ...
 - 从零开始的全栈工程师——js篇2.20(事件对象 冒泡与捕获)
		
一.复习 面向对象 1)单例模式 2)工厂模式 3)构造函数 ①类js天生自带的类 基类object function array number math boolean date regexp st ...
 - jQuery选择器、事件、节点、动画效果
		
一.选择器 基本选择器: 标签选择器: $("h1").css() 类选择器: $(".c").css() id选择器: $(&quo ...
 - 【Activiti学习之五】BPMN事件
		
环境 JDK 1.8 MySQL 5.6 Tomcat 7 Eclipse-Luna activiti 6.0 一.事件定义1.定时器事件(1)timeDate:指定时间触发<timerEven ...
 - 微信小程序事件绑定
		
一 通过实例来认识 (一) 给出代码 我们直接通过一个实例来引入我们想要讲解的内容: <input type="text" bindinput="handleInp ...
 - 深入浅出 Redis client/server交互流程
		
综述 最近笔者阅读并研究redis源码,在redis客户端与服务器端交互这个内容点上,需要参考网上一些文章,但是遗憾的是发现大部分文章都断断续续的非系统性的,不能给读者此交互流程的整体把握.所以这里我 ...
 - SOSO街景地图 API (Javascript)开发教程(1)- 街景
		
SOSO街景地图 Javascript API 干什么用的? 你想在网页里嵌入个地图,就需要它了! 另外,它还支持:地点搜索.周边/附近查询.地图标注.公交/驾车路线规划.地理坐标与地址相互转换.地理 ...
 
随机推荐
- vue $emit子组件传出多个参数,如何在父组件中在接收所有参数的同时添加自定义参数
			
Vue.js 父子组件通信的十种方式 前言 很多时候用$emit携带参数传出事件,并且又需要在父组件中使用自定义参数时,这时我们就无法接受到子组件传出的参数了.找到了两种方法可以同时添加自定义参数的方 ...
 - MySQL 的MAC终端一些指令总结
			
开启MySQL服务 sudo /usr/local/mysql/support-files/mysql.server start 关闭MySQL服务 udo /usr/local/mysql/supp ...
 - [解读REST] 0.REST 相关参考资料
			
Web之父 Tim Berners Lee :https://en.wikipedia.org/wiki/Tim_Berners-Lee 世界上诞生的第一个网站:http://info.cern.ch ...
 - Eclipse下创建Spring MVC web程序--maven版
			
1. 创建一个maven工程: File->New->Other... 2. 创建完成后的结构如下: 3. 配置pom.xml文件,添加spring-webmvc依赖项 <pro ...
 - js中的原型哲学思想
			
https://segmentfault.com/a/1190000005824449 记得当年初试前端的时候,学习JavaScript过程中,原型问题一直让我疑惑许久,那时候捧着那本著名的红皮书,看 ...
 - [持续集成学习篇]【1】[jenkins安装与配置]
			
Guided Tour This guided tour will use the "standalone" Jenkins distribution which requires ...
 - 安装adb工包
			
下载android sdk (很大) 从D:\AndroidSdk\platform-tools目录可以看到: 将adb工具包: adb.exe,AdbWinapi.dll,AdbWinUSBapi. ...
 - SpringMVC对于跨域访问的支持
			
原文地址:http://docs.spring.io/spring/docs/5.0.0.RC2/spring-framework-reference/web.html#mvc-introductio ...
 - webapi同时支持post和get报404错误
			
文章:webapi设置一个Action同时支持get和post请求 这篇文章,有提供方法.参数前加上[FromUri] [AcceptVerbs("GET", "POST ...
 - [LOJ#516]「LibreOJ β Round #2」DP 一般看规律
			
[LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...