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

news/2024/11/1 14:27:42/

一、简介

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

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

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

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

 二、运行机制

        读事件时,可以根据入参事件掩码类型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/60531.html

相关文章

grep命令与正则表达式,快速学习正则表达式

1.了解grep命令常用操作 命令格式 grep [options] pattern [files]pattern&#xff1a;要查找的字符串或正则表达式。files&#xff1a;要查找的文件名&#xff0c;可以同时查找多个文件&#xff0c;如果省略 files 参数&#xff0c;则默认从标准输入中读取数据。 常用选项 …

FreeRTOS 任务通知

文章目录 一、任务通知简介二、发送任务通知1. 函数 xTaskNotify()2. 函数 xTaskNotifyFromISR()3. 函数 xTaskNotifyGive()4. 函数 vTaskNotifyGiveFromISR()5. 函数 xTaskNotifyAndQuery()6. 函数 xTaskNotifyAndQueryFromISR() 三、任务通知通用发送函数1. 任务级任务通知通…

运算符重载和重载函数

1.运算符重载的意义 C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是具有特殊函数名的函数&#xff0c;也具有其返回值类型&#xff0c;函数名字以及参数列表&#xff0c;其返回值类型与参数列表与普通的函数类似。 函数名字为&#xff1a;关键字operator后面…

汇编语言学习笔记四

字符 字符是以ASCII码的形式存储的&#xff0c;一个字符对应着8为二进制数&#xff0c;2位16进制数。 所以可以得到对应的字符地址。 assume ds:data data segmentdb hellodb world data endsand or指令 根据ASCII码&#xff0c;字符的大写和小写相差一个0010 0000&#xff…

c++——入门(下)

6. 引用 6.1 引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间&#xff0c;它和它引用的变量共用同一块内存空间。 类型& 引用变量名(对象名) 引用实体&#xff1b; void TestRef() {int a 1…

Linux基础IO【重定向及缓冲区理解】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 文章目录 &#x1f307;前言&#x1f3d9;️正文1、文件描述符1.1、先描述&#xff0c;再组织1.2、files_struct1.3、分配规则…

阿里云g8i服务器Intel Xeon(Sapphire Rapids) Platinum 8475B

阿里云服务器ECS通用型实例规格族g8i采用2.7 GHz主频的Intel Xeon(Sapphire Rapids) Platinum 8475B处理器&#xff0c;3.2 GHz睿频&#xff0c;g8i实例采用阿里云全新CIPU架构&#xff0c;可提供稳定的算力输出、更强劲的I/O引擎以及芯片级的安全加固。阿里云百科分享阿里云服…

【设计模式】策略模式

目录 一、定义二、结构三、优点四、缺点五、使用场景六、代码示例 一、定义 1.该模式定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替换&#xff0c;且算法的变化不会影响使用算法的客户 2.策略模式属于对象行为模式&#xff0c;它通过对算法进…