RT-thread内核之事件
一、事件控制块:在include/rtdef.h中
#ifdef RT_USING_EVENT /** * flag defintions in event */ #define RT_EVENT_FLAG_AND 0x01 /**< logic and */ #define RT_EVENT_FLAG_OR 0x02 /**< logic or */ #define RT_EVENT_FLAG_CLEAR 0x04 /**< clear flag */ /* * event structure */ struct rt_event { struct rt_ipc_object parent; /**< inherit from ipc_object *///从IPC对象派生 rt_uint32_t set; /**< event set */ //保存接收到的事件集 }; typedef struct rt_event *rt_event_t; #endif
二、事件相关接口:在src/ipc.c中
创建事件: rt_event_t rt_event_create(const char *name, rt_uint8_t flag); 调用该函数接口时,系统会从动态内存堆中分配事件对象,然后进行对象的初始化,IPC对象初始化,并把set设置成0。 删除事件: rt_err_t rt_event_delete(rt_event_t event); 在调用rt_event_delete函数删除一个事件对象时,应该确保该事件不再被使用。在删除前会唤醒所有挂起在该事件上的线程(线程的返回值是-RT_ERROR),然后释放事件对象占用的内存块。
初始化事件: rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag); 调用该接口时,需指定静态事件对象的句柄(即指向事件控制块的指针),然后系统会初始化事件对象,并加入到系统对象容器中进行管理。 脱离事件: rt_err_t rt_event_detach(rt_event_t event); 系统首先唤醒所有挂在该事件等待队列上的线程(线程的返回值是- RT_ERROR ),然后将该事件从内核对象管理器中删除。
发送事件: rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set); 通过发送事件服务,可以发送一个或多个事件。使用该函数接口时,通过参数set指定的事件标志来设定event对象的事件标志值,然后遍历等待在event事件对象上的等待线程链表,判断是否有线程的事件激活要求与当前event对象事件标志值匹配,如果有,则唤醒该线程。
发送事件首先会将事件集set保存到事件控制内部,然后遍历事件控制块内所有因等待事件的接收线程,如果条件符合则唤醒它 接收事件: rt_err_t rt_event_recv(rt_event_t event, //事件对象的句柄 rt_uint32_t set, //接收线程感兴趣的事件 rt_uint8_t option, //接收选项 rt_int32_t timeout, //指定超时时间 rt_uint32_t *recved); //指向收到的事件 内核使用32位的无符号整型数来标识事件,它的每一位代表一个事件,因此一个事件对象可同时等待接收32个事件,内核可以通过指定选择参数“逻与”或“逻辑或”来选择如何激活线程,使用“逻辑与”参数表示只有当所有等待的事件都发生时才激活线程,而使用“逻辑或”参数则表示只要有一个等待的事件发生就激活线程。 当用户调用这个接口时,系统首先根据set参数和接收选项来判断它要接收的事件是否发生,如果已经发生,则根据参数option上是否设置有RT_EVENT_FLAG_CLEAR来决定是否重置事件的相应标志位,然后返回(其中recved参数返回收到的事件); 如果没有发生,则把等待的set和option参数填入线程本身的结构中,然后把线程挂起在此事件对象上,直到其等待的事件满足条件或等待时间超过指定的超时时间。如果超时时间设置为零,则表示当线程要接受的事件没有满足其要求时就不等待,而直接返回-RT_TIMEOUT。
接收事件比较简单,如果接收到事件则判断它是否为它关心的事件,如果是,则保存事件,如果不是,则当没有接收到事件情况一起处理。接下来就是没有事件到达的情况,还是老规矩,先判断时间参数是否为0,如果是则直接返回超时,如果不是,则设置一定时器然后启动它,接着重新调度线程,然后根据当前线程的error值是否为RT_EOK来判断是否有新的并且符合条件的事件到达,如果不是,则返回错误码,如果是,则保存事件,最终返回OK。
控制事件: rt_err_t rt_event_control(rt_event_t event, rt_uint8_t cmd, void *arg); 只支持RT_IPC_CMD_RESET这个命令,表示复位事件,将事件集set清0。