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

news/2024/7/21 9:27:02 标签: harmonyos, LiteOS, 事件标志组, 事件标记

一、简介

        事件是一种实现任务间通信的机制,可用于实现任务间的同步。但事件通信只能是事件类型的通信,无数据传输。一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。事件集合用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 thread
    osThreadYield();

    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.niftyadmin.cn/n/294745.html

相关文章

多款智能骑行终端齐登场,移远通信闪亮第31届中国国际自行车展览会

近年来&#xff0c;自行车、电动车市场火爆&#xff0c;随着数字化、智能化的持续深入&#xff0c;更具科技感的骑行工具受到了越来越多年轻一代的青睐。5月5-8日&#xff0c;以" 更安全、更智能、更低碳 " 为主题的第 31 届中国国际自行车展览会在上海新国际博览中心…

高效提升计算质量!瑞典量子计算机首次应用于化学

​ &#xff08;图片来源&#xff1a;网络&#xff09; 量子计算机可以模拟化学过程&#xff0c;从新药开发到新材料的方方面面&#xff0c;它都能带来重大影响&#xff0c;人们对此寄予厚望。在瑞典&#xff0c;查尔姆斯理工大学的研究人员首次使用量子计算机在实际化学中进行…

open3d io操作

目录 1. read_image, write_image 2. read_point_cloud, write_point_cloud 3. 深度相机IO操作 4. Mesh文件读取 1. read_image, write_image 读取jpg. png. bmp等文件 image_io.py import open3d as o3dif __name__ "__main__":img_data o3d.data.JuneauIma…

C++之虚函数原理

对象数据和函数的存储方式 注意说的是对象。 C中的对象存储方式是 每个对象占用的存储空间只是该对象的数据部分&#xff08;虚函数指针和虚基类指针也属于数据部分&#xff09;&#xff0c;函数属于公共部分。 虚函数表 虚函数是通过虚函数表实现的。 C实现虚函数的方法是…

20个JavaScript数组方法的实现

写在前面 我想&#xff0c;大家一定对JavaScript中的数组很熟悉了&#xff0c;我们每天都会用到它的各种方法&#xff0c;比如push、pop、forEach、map……等等。 但是仅仅使用它就足够了吗&#xff1f;如果你想成为出色的程序员&#xff0c;你一定不想停在熟悉使用阶段这里&…

《ChatGPT Prompt Engineering for Developers》课程-提示词原则

编写 Prompt 的原则 本章的主要内容为编写 Prompt 的原则&#xff0c;在本章中&#xff0c;我们将给出两个编写 Prompt 的原则与一些相关的策略&#xff0c;你将练习基于这两个原则来编写有效的 Prompt&#xff0c;从而便捷而有效地使用 LLM。 一、环境配置 本教程使用 Open…

THUPC部分题解

THUPC2023初赛 B. 拧螺丝 考虑如何暴搜&#xff0c;从最终状态只有唯一的 n n n 倒序还原回去&#xff0c;相当于不断执行以下操作直到没有螺丝&#xff1a; 执行以下操作 k k k 次&#xff1a; 找到当前含有最多螺丝的工件&#xff0c;将螺丝数减一 将当前含有最多螺丝的工…

网络无法分配 IP 地址有什么原因?

IP地址是计算机网络中用于唯一标识一台设备的地址&#xff0c;由四部分组成&#xff1a; 网络地址&#xff1a;表示设备所连接的网络的地址&#xff0c;多数情况下是点分十进制表示的。 主机地址&#xff1a;表示设备在网络中的具体物理地址&#xff0c;也是点分十进制表示的。…