鸿蒙Hi3861学习八-Huawei LiteOS-M(事件标记)

news/2024/11/29 5:30:45/

一、简介

        事件是一种实现任务间通信的机制,可用于实现任务间的同步。但事件通信只能是事件类型的通信,无数据传输。一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。事件集合用32位无符号整型变量来表示,每一位代表一个事件

        多任务环境下,任务之间往往需要同步操作。事件可以提供一对多、多对多的同步操作。一对多同步模型:一个任务等待多个事件的触发;多多对同步模型:多个任务等待多个事件的触发。

        任务可以通过创建事件控制块来实现对事件的触发和等待操作。LiteOS的事件仅用于任务间的同步

        更多事件标记的概念可以参考:FreeRTOS学习七(事件标志组)_portmax_delay_t_guest的博客-CSDN博客

Event Flags

 二、运行机制

        读事件时,可以根据入参事件掩码类型uwEventMask读取事件的单个或者多个事件类型。事件读取成功后,如果设置LOS_WAITMODE_CLR会清除已读取到的事件类型,反之不会清除已读到的事件类型,需手动清除。可以通过参数选择读取模式,读取事件掩码类型中所有事件还是读取事件掩码类型中任意事件。

        写事件时,对指定事件写入指定的事件类型,可以一次同时写多个事件类型。写事件会触发任务调度。

        清除事件时,根据入参事件和待清除的事件类型,对事件对应位进行清零操作。

三、API介绍

      osEventFlagsNew

        函数功能:

        创建事件标志。不能在中断中调用

        函数原型:

osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)

        参数:

        attr:属性。自定义内存时才用的到默认设置NULL

        返回值:

        NULL:失败

        其他值:事件标志ID

        实例:

osEventFlagsId_t evt_id; // event flags id
evt_id = osEventFlagsNew(NULL);

      osEventFlagsSet

        函数功能:

        设置事件标志。可以在中断中使用

        函数原型:

uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)

        参数:

        ef_id:事件ID。创建事件标志组osEventFlagsNew时获得

        flags:事件值

        返回值:

        如果设置了最高位,则返回设置后的事件标志或错误代码

        实例:

osEventFlagsId_t evt_id; 
uint32_t rst = osEventFlagsSet(evt_id, 0x10001111);

      osEventFlagsWait

        函数功能:

        等待事件发生。可以在中断中调用。

        函数原型:

uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout)

        参数:

        ef_id:事件ID。创建事件标志组osEventFlagsNew时获得

        flags:待触发的事件值。

        options:指定标志选项

osFlagsWaitAny0,等待任何标志(默认),即满足任意标志即可
osFlagsWaitAll1,等待所有标志,即需要满足所有标志。
osFlagsNoClear2,不清除已经指定等待的标志。需要使用 osEventFlagsClear 手动清除标志。

        timeout:超时时间。osWaitForever 死等

        返回值:

        清除前的事件标志或设置最高位时的错误代码

        实例:

osEventFlagsId_t evt_id; 
uint32_t flags;
flags = osEventFlagsWait(evt_id, 0x000000ff, osFlagsWaitAny, osWaitForever);

      osEventFlagsDelete

        函数功能:

        删除事件标志组。不能在中断中调用

        函数原型:

osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)

        参数:

        ef_id:事件标志ID。创建事件标志组osEventFlagsNew时获得。

        返回值:

        osOK:成功

        其他值:失败

        实例:

osEventFlagsId_t evt_id;
osEventFlagsDelete(evt_id);

四、实例

        这里创建2个任务,任务1设置事件组,任务2等待事件组。其中,任务1设置完事件组后,立刻移交控制权

#define LOG_I(fmt, args...)   printf("<%8ld> - [TIMER]:"fmt"\r\n",osKernelGetTickCount(),##args);
#define LOG_E(fmt, args...)   printf("<%8ld>-[TIMER_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);osEventFlagsId_t evt_id; // event flags id/***** 发送事件 *****/
void Thread_EventSender(void *argument)
{(void)argument;while (1){LOG_I("thread1 send event before");uint32_t rst = osEventFlagsSet(evt_id, 0x80001111);LOG_I("thread1 send event after,rst = 0x%.8x,yield!!",rst);//suspend threadosThreadYield();LOG_I("thread1 send event delay 1S");osDelay(100);}
}/***** 接收事件 *****/
void Thread_EventReceiver(void *argument)
{(void)argument;uint32_t flags;while (1){flags = osEventFlagsWait(evt_id, 0x000000ff, osFlagsWaitAny, osWaitForever);LOG_I("Receive2 Flags is 0x%.8x\n", flags);}
}void Hello_World(void)
{LOG_I("Test event");evt_id = osEventFlagsNew(NULL);if (evt_id == NULL){LOG_E("Falied to create EventFlags!");}osThreadAttr_t attr;attr.attr_bits = 0U;attr.cb_mem = NULL;attr.cb_size = 0U;attr.stack_mem = NULL;attr.stack_size = 1024 * 4;attr.priority = osPriorityNormal;attr.name = "Thread_EventSender";if (osThreadNew(Thread_EventSender, NULL, &attr) == NULL){LOG_E("Falied to create Thread_EventSender!");}attr.name = "Thread_EventReceiver";if (osThreadNew(Thread_EventReceiver, NULL, &attr) == NULL){LOG_E("Falied to create Thread_EventReceiver!");}
}

        看结果:

         从结果可以看到,任务2等待0x000000ff事件。而任务1释放的是0x80001111。此时因为设置的等待类型为osFlagsWaitAny,即满足任意条件即触发。所以,直接触发事件,且读出的事件组为0x00000011。

        任务1和任务2优先级相同,但是任务1在设置完事件后,立马释放了控制权。导致任务2可以获取控制权执行代码。


http://www.ppmy.cn/news/63355.html

相关文章

Java设计模式(七)桥接模式

一、概述 桥接模式是一种结构型设计模式&#xff0c;它将抽象部分与实现部分分离&#xff0c;使它们可以独立变化。桥接模式通过将抽象和实现进行解耦&#xff0c;让它们可以独立地扩展和变化&#xff0c;同时可以在运行时动态地将不同的抽象和实现组合起来。 二、代码 下面…

遗传算法(GA)

理论&#xff1a; 遗传算法是一种通过模拟生物进化的方式来寻找最优解的一类优化算法。这种算法主要依靠遗传、突变和自然选择的机制对问题求解进行高效的迭代搜索。 遗传算法的基本思想是将问题的解表示成一个个个体&#xff0c;然后根据适应度函数的定义来评估每个个体的适…

【设计模式】建造者模式

【设计模式】建造者模式 参考资料&#xff1a; 重学 Java 设计模式&#xff1a;实战建造者模式「各项装修物料组合套餐选配场景」 建造者模式——链式调用 五分钟彻底了解建造者模式 文章目录 【设计模式】建造者模式一、建造者模式介绍1.1、定义1.2、角色概述 二、案例场景模…

Acid burn(★★)

运行程序 先是弹出一个neg 然后是真正的程序界面 有一个输入Serial和Name的判断 还有一个只输入Serial的判断 查壳 没有壳&#xff0c;是Delphi程序 先除去一个Neg 找到Neg弹出的程序&#xff0c;在程序头下个断&#xff0c;运行程序&#xff0c;此时栈顶是调用此功能的…

Gradle使用

下载Gradle Gradle Distributions 配置环境变量 测试是否成功 cmd输入gradle -v 在.gradle目录下创建一个init.gradle allprojects { repositories { maven { url file:///D:/maven/myRepository} ## 这里是本地maven仓库地址,没有就会依次向下设置的地址寻…

将ssh发布密钥添加到服务器的ssh授权密钥中,但是为什么我仍然无法ssh登录到此服务器?

我已经将ssh发布密钥添加到服务器的ssh授权密钥中&#xff0c;但是为什么我仍然无法ssh登录到此服务器&#xff1f; 即使将ssh公钥添加到服务器的授权密钥中&#xff0c;您也可能无法通过SSH登录到服务器&#xff0c;这有几个原因: 1.服务器的authorized_keys文件的权限不正确…

微信小程序商城搭建--后端+前端+小程序端

介绍&#xff1a; 前端技术&#xff1a;React、AntdesignPro、umi、JavaScript、ES6、TypeScript、 小程序 后端技术&#xff1a;Springboot、Mybatis、Spring、Mysql 软件架构&#xff1a; 后端采用Springboot搭配前端React进行开发&#xff0c;完成用户管理、轮播图管理、…

django:django2配置websocket

源码地址&#xff1a; https://gitee.com/liuhaizhang/django2-configuring-websockethttps://gitee.com/liuhaizhang/django2-configuring-websocket python3.9.0 django2.2.1 channels2.2.0 项目结构&#xff1a; test_websocket_django2 -chat -home -test_websocket_dja…