一、事件控制塊:在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。