1# 小凌派-RK2206开发板OpenHarmonyOS内核开发-事件 2 3## 实验内容 4 5本例程演示如何在小凌派-RK2206开发板上使用鸿蒙LiteOS-M内核接口,进行事件编程开发。例程创建一个事件,两个任务;任务1调用读事件接口等待事件通知,任务2调用写事件接口通知任务1事件到达。 6 7 8 9## 程序设计 10 11事件是一种实现任务间通信的机制,可用于实现任务间的同步,但是仅仅作为事件类型的通信,不提供数据传输功能。一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。事件集合用32位无符号整型变量来表示,每一位代表一个事件。 12 13多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步。事件可以提供一对多、多对多的同步操作。一对多同步模型:一个任务等待多个事件的触发;多对多同步模型:多个任务等待多个事件的触发。任务可以通过创建事件控制块来实现对事件的触发和等待操作。 14 15### API分析 16 17#### LOS_EventInit() 18 19```c 20UINT32 LOS_EventInit(PEVENT_CB_S eventCB); 21``` 22 23**描述:** 24 25事件控制块初始化。 26 27**参数:** 28 29| 名字 | 描述 | 30| :------ | :------------- | 31| eventCB | 事件控制块指针 | 32 33**返回值:** 34 35| 返回值 | 描述 | 36| :----------------------- | :--- | 37| LOS_OK | 成功 | 38| LOS_ERRNO_EVENT_PTR_NULL | 失败 | 39 40#### LOS_EventRead() 41 42```c 43UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeOut); 44``` 45 46**描述:** 47 48读事件(等待事件),任务会根据timeOut(单位:tick)进行阻塞等待; 49未读取到事件时,返回值为0;正常读取到事件时,返回正值(事件发生的集合);其他情况返回特定错误码。 50 51**参数:** 52 53| 名字 | 描述 | 54| :-------- | :------------- | 55| eventCB | 事件控制块指针 | 56| eventMask | 事件掩码 | 57| mode | 事件读取的模式 | 58| timeOut | 超时时间 | 59 60**返回值:** 61 62| 返回值 | 描述 | 63| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--- | 64| LOS_OK | 成功 | 65| LOS_ERRNO_EVENT_SETBIT_INVALID`<br>` LOS_ERRNO_EVENT_EVENTMASK_INVALID `<br>` LOS_ERRNO_EVENT_READ_IN_INTERRUPT `<br>` LOS_ERRNO_EVENT_FLAGS_INVALID `<br>` LOS_ERRNO_EVENT_READ_IN_LOCK `<br>` LOS_ERRNO_EVENT_PTR_NULL | 失败 | 66 67#### LOS_EventWrite() 68 69```c 70UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events); 71``` 72 73**描述:** 74 75写一个特定的事件到事件控制块。 76 77**参数:** 78 79| 名字 | 描述 | 80| :------ | :--------------- | 81| eventCB | 事件控制块指针 | 82| events | 要写入的事件掩码 | 83 84**返回值:** 85 86| 返回值 | 描述 | 87| :-------------------------------------------------------------- | :--- | 88| LOS_OK | 成功 | 89| LOS_ERRNO_EVENT_SETBIT_INVALID`<br>` LOS_ERRNO_EVENT_PTR_NULL | 失败 | 90 91#### LOS_EventClear() 92 93```c 94UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMask); 95``` 96 97**描述:** 98 99根据events掩码,清除事件控制块中的事件。 100 101**参数:** 102 103| 名字 | 描述 | 104| :-------- | :--------------- | 105| eventCB | 事件控制块指针 | 106| eventMask | 要清除的事件掩码 | 107 108**返回值:** 109 110| 返回值 | 描述 | 111| :----------------------- | :--- | 112| LOS_OK | 成功 | 113| LOS_ERRNO_EVENT_PTR_NULL | 失败 | 114 115### 软件设计 116 117**主要代码分析** 118 119在event_example函数中,通过LOS_EventInit函数创建事件,并通过LOS_TaskCreate函数创建两个线程:event_master_thread和event_slave_thread。 120 121```c 122void event_example() 123{ 124 unsigned int thread_id1; 125 unsigned int thread_id2; 126 TSK_INIT_PARAM_S task1 = {0}; 127 TSK_INIT_PARAM_S task2 = {0}; 128 unsigned int ret = LOS_OK; 129 130 ret = LOS_EventInit(&m_event); 131 if (ret != LOS_OK) 132 { 133 printf("Failed to create EventFlags\n"); 134 return; 135 } 136 137 task1.pfnTaskEntry = (TSK_ENTRY_FUNC)event_master_thread; 138 task1.uwStackSize = 2048; 139 task1.pcName = "event_master_thread"; 140 task1.usTaskPrio = 5; 141 ret = LOS_TaskCreate(&thread_id1, &task1); 142 if (ret != LOS_OK) 143 { 144 printf("Failed to create event_master_thread ret:0x%x\n", ret); 145 return; 146 } 147 148 task2.pfnTaskEntry = (TSK_ENTRY_FUNC)event_slave_thread; 149 task2.uwStackSize = 2048; 150 task2.pcName = "event_slave_thread"; 151 task2.usTaskPrio = 5; 152 ret = LOS_TaskCreate(&thread_id2, &task2); 153 if (ret != LOS_OK) 154 { 155 printf("Failed to create event_slave_thread ret:0x%x\n", ret); 156 return; 157 } 158} 159``` 160 161event_slave_thread线程函数中通过LOS_EventRead函数将线程置于阻塞状态,等待事件到达;在event_master_thread函数中通过LOS_EventWrite函数每隔2S写入事件,实现线程的同步,2s后清除事件,重复以上流程。 162 163```c 164void event_master_thread() 165{ 166 unsigned int ret = LOS_OK; 167 168 LOS_Msleep(1000); 169 170 while (1) 171 { 172 printf("%s write event:0x%x\n", __func__, EVENT_WAIT); 173 ret = LOS_EventWrite(&m_event, EVENT_WAIT); 174 if (ret != LOS_OK) { 175 printf("%s write event failed ret:0x%x\n", __func__, ret); 176 } 177 178 /*delay 1s*/ 179 LOS_Msleep(2000); 180 LOS_EventClear(&m_event, ~m_event.uwEventID); 181 } 182} 183 184void event_slave_thread() 185{ 186 unsigned int event; 187 188 while (1) 189 { 190 /* 阻塞方式读事件,等待事件到达*/ 191 event = LOS_EventRead(&m_event, EVENT_WAIT, LOS_WAITMODE_AND, LOS_WAIT_FOREVER); 192 printf("%s read event:0x%x\n", __func__, event); 193 LOS_Msleep(1000); 194 } 195} 196``` 197 198## 编译调试 199 200### 修改 BUILD.gn 文件 201 202修改 `vendor/lockzhiner/lingpi/sample` 路径下 BUILD.gn 文件,指定 `a6_kernel_event` 参与编译。 203 204```r 205"a6_kernel_event", 206``` 207 208在主目录下输入编译命令。 209 210```shell 211hb build -f 212``` 213 214### 运行结果 215 216示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,event_master_thread函数每隔2s写入事件,2s后清除事件;event_slave_thread函数阻塞等待事件达到,事件到达后,每1s打印一次读事件信息。 217 218```r 219event_master_thread write event:0x1 220event_slave_thread read event:0x1 221event_slave_thread read event:0x1 222event_master_thread write event:0x1 223event_slave_thread read event:0x1 224event_slave_thread read event:0x1 225``` 226