鸿蒙南向开发教程 Day 6:事件标志组(Event Flags) 目标掌握 OpenHarmony 轻量系统的事件标志组 API实现多线程间的事件通知与同步前置条件已完成 Day 5 的延时教程一、工程结构app/ ├── BUILD.gn └── 04_event/ # 模块目录 ├── BUILD.gn └── demo.c # 事件标志组测试代码1.1app/BUILD.gnimport(//build/lite/config/component/lite_component.gni) lite_component(app) { features [ 04_event:event_demo, # 引用 04_event 模块 ] }1.204_event/BUILD.gnstatic_library(event_demo) { sources [ demo.c ] include_dirs [ //utils/native/lite/include, //kernel/liteos_m/components/cmsis/2.0, ] }二、完整代码详解2.1 全局变量定义#includestdio.h#includeunistd.h#includeohos_init.h#includecmsis_os2.hosThreadId_tTask1_ID;// Task1 线程 IDosThreadId_tTask2_ID;// Task2 线程 IDosEventFlagsId_tevent_ID;// 事件标志组 ID// 定义三个事件标志位按位独立uint32_tevent1_Flags0x00000001U;// bit 0uint32_tevent2_Flags0x00000002U;// bit 1uint32_tevent3_Flags0x00000004U;// bit 2#defineTASK_STACK_SIZE1024// 线程栈大小#defineTASK_DELAY_TIME1// 延时 1 秒事件标志位设计标志值二进制含义event1_Flags0x00000001U...0001事件 1event2_Flags0x00000002U...0010事件 2event3_Flags0x00000004U...0100事件 3每个事件占用独立的 bit 位可同时设置/等待多个事件。2.2 发送事件线程Task1voidTask1(void){while(1){printf(enter Task 1.......\n);// 设置事件标志 1osEventFlagsSet(event_ID,event1_Flags);printf(send eventFlag1.......\n);sleep(TASK_DELAY_TIME);// 延时 1 秒// 设置事件标志 2osEventFlagsSet(event_ID,event2_Flags);printf(send eventFlag2.......\n);sleep(TASK_DELAY_TIME);// 设置事件标志 3osEventFlagsSet(event_ID,event3_Flags);printf(send eventFlag3.......\n);sleep(TASK_DELAY_TIME);}}执行时序Task1: set bit0 ──sleep(1s)── set bit1 ──sleep(1s)── set bit2 ──sleep(1s)──→ event1 event2 event32.3 接收事件线程Task2voidTask2(void){uint32_tflags0;while(1){// 等待三个事件标志全部置位AND 关系flagsosEventFlagsWait(event_ID,// 事件标志组 IDevent1_Flags|event2_Flags|event3_Flags,// 等待的位掩码osFlagsWaitAll,// 等待模式全部置位osWaitForever// 超时时间永久等待);printf(receive event is OK\n);}}等待模式详解模式值说明osFlagsWaitAny0或等待任一标志置位即唤醒osFlagsWaitAll1与等待所有标志都置位才唤醒本例使用osFlagsWaitAll必须 bit0、bit1、bit2 全部置 1Task2 才会唤醒。2.4 系统入口staticvoidkernel_event_example(void){printf(Enter kernel_event_example()!\n);// 1. 创建事件标志组event_IDosEventFlagsNew(NULL);// NULL 默认属性if(event_ID!NULL){printf(ID %d, Create event_ID is OK!\n,event_ID);}// 2. 配置线程属性osThreadAttr_ttaskOptions;taskOptions.nameTask1;taskOptions.attr_bits0;taskOptions.cb_memNULL;taskOptions.cb_size0;taskOptions.stack_memNULL;taskOptions.stack_sizeTASK_STACK_SIZE;taskOptions.priorityosPriorityNormal;// 3. 创建 Task1发送事件Task1_IDosThreadNew((osThreadFunc_t)Task1,NULL,taskOptions);if(Task1_ID!NULL){printf(ID %d, Create Task1_ID is OK!\n,Task1_ID);}// 4. 创建 Task2接收事件复用 taskOptions 结构体taskOptions.nameTask2;Task2_IDosThreadNew((osThreadFunc_t)Task2,NULL,taskOptions);if(Task2_ID!NULL){printf(ID %d, Create Task2_ID is OK!\n,Task2_ID);}}SYS_RUN(kernel_event_example);// 系统启动入口三、CMSIS-RTOS2 事件标志组 API 详解3.1osEventFlagsNew— 创建事件标志组osEventFlagsId_tosEventFlagsNew(constosEventFlagsAttr_t*attr);参数说明attr属性NULL 为默认返回值事件标志组 IDNULL 表示创建失败。3.2osEventFlagsSet— 设置事件标志uint32_tosEventFlagsSet(osEventFlagsId_tef_id,uint32_tflags);参数说明ef_id事件标志组 IDflags要设置的位掩码特点设置后等待该标志的线程会被唤醒如果条件满足可一次设置多个位osEventFlagsSet(event_ID, flag1 | flag2)3.3osEventFlagsWait— 等待事件标志uint32_tosEventFlagsWait(osEventFlagsId_tef_id,// 事件标志组 IDuint32_tflags,// 等待的位掩码uint32_toptions,// 等待模式 清除选项uint32_ttimeout// 超时时间tickosWaitForever 永久);options 组合选项值说明osFlagsWaitAny0x00000000任一标志置位即唤醒osFlagsWaitAll0x00000001所有标志置位才唤醒osFlagsNoClear0x00000002唤醒后不自动清除标志常用组合osFlagsWaitAny或等待自动清除osFlagsWaitAll与等待自动清除本例使用osFlagsWaitAll | osFlagsNoClear与等待不清除需手动osEventFlagsClear3.4osEventFlagsClear— 清除事件标志uint32_tosEventFlagsClear(osEventFlagsId_tef_id,uint32_tflags);3.5osEventFlagsGet— 获取当前标志值uint32_tosEventFlagsGet(osEventFlagsId_tef_id);3.6osEventFlagsDelete— 删除事件标志组osStatus_tosEventFlagsDelete(osEventFlagsId_tef_id);四、执行流程时序图时间轴 → Task1: [set bit0]────[sleep 1s]────[set bit1]────[sleep 1s]────[set bit2]────[sleep 1s]────→ event1 event2 event3 event_ID 标志位: bit01 bit11 bit21 ───────────────────────────────────────────────────────────────────────────────→ Task2: [wait all bits]←──────────────────────────────────────────→[wakeup!]────────────→ Blocked状态 等待bit0bit1bit2全部置位 receive event is OK关键Task2 在第三次osEventFlagsSet后才唤醒因为前两次 bit0 和 bit1 置位时bit2 还未置位不满足osFlagsWaitAll条件。五、底层实现LiteOS 原生事件CMSIS-RTOS2 的osEventFlagsXxx在 LiteOS-M 中的映射CMSIS-RTOS2LiteOS-M 原生说明osEventFlagsNewLOS_EventCreate创建事件控制块osEventFlagsSetLOS_EventWrite写事件标志osEventFlagsWaitLOS_EventRead读事件标志osEventFlagsClearLOS_EventClear清除事件标志osEventFlagsDeleteLOS_EventDelete删除事件控制块LiteOS-M 使用事件控制块Event Control Block实现内部维护一个 32 位事件标志字。六、编译与验证6.1 编译烧录VSCode 点击Build→Upload串口波特率115200。6.2 预期输出Enter kernel_event_example()! ID 20001xxx, Create event_ID is OK! ID 20001yyy, Create Task1_ID is OK! ID 20001zzz, Create Task2_ID is OK! enter Task 1....... send eventFlag1....... enter Task 1....... send eventFlag2....... enter Task 1....... send eventFlag3....... receive event is OK enter Task 1....... send eventFlag1....... ...Task2 在 Task1 发送完三个事件后才打印 “receive event is OK”验证了osFlagsWaitAll的与等待逻辑。七、总结要点内容事件标志32 位独立位可同时管理多个事件设置事件osEventFlagsSet(id, flags)等待事件osEventFlagsWait(id, flags, mode, timeout)等待模式osFlagsWaitAny或/osFlagsWaitAll与自动清除默认唤醒后自动清除可加osFlagsNoClear保留底层映射LiteOS-MLOS_EventXxx事件控制块八、下一步Day 7 预告信号量Semaphore—— 资源计数与任务同步。