1. 程式人生 > >7.IPC之事件//依據RT-Thread核心程式設計的學習記錄(非核心實現)

7.IPC之事件//依據RT-Thread核心程式設計的學習記錄(非核心實現)

事件是什麼,為什麼需要事件?在RT-Thread中的IPC量已經包含了訊號量,互斥量,郵箱,訊息佇列。事件作為IPC量的一種,它的和訊號量和互斥鎖類似,同樣是為執行緒的執行增加限定條件。只不過事件的滿足,擁有更加嚴格的條件。例如:同時滿足1和2,滿足1和2中的某一個,同時滿足1,2,3,6中的條件或者滿足其中某一個。

1.事件的建立

/*靜態事件的建立*/

/*事件控制塊*/

static struct rt_event static_event;

rt_event_init(&static_event,"name",type);

/*動態事件的建立*/

/*事件控制塊*/
static rt_event_t dynamic_event = RT_NULL;

dynamic_event = rt_event_creat("name",type);

事件的建立,建議檢視原始碼的建立例程。講道理學到這裡,應該很容易的開始學著檢視ipc.c檔案了

2.事件的傳送

#define EVENT_FLAG3 (1 << 3)
#define EVENT_FLAG5 (1 << 5)

/*事件的傳送,只有傳送特定事件才能接受*/ 
rt_event_send(&event, EVENT_FLAG3);
/*
 * event structure
 */
struct rt_event
{
    struct rt_ipc_object parent;                        /**< inherit from ipc_object */

    rt_uint32_t          set;                           /**< event set */
};
typedef struct rt_event *rt_event_t;

這個位置set,rt_uint32_t有32位,每一位作為一個事件。所以傳遞得資訊為EVENT_FLAG,這個資料是32位的具體某一位。

3.事件的接收

rt_uint32_t e;

RT_EOK == rt_event_recv(&static_event,                             //時間塊
                        (EVENT_FLAG3 | EVENT_FLAG5),               //事件
                        RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,    //與,後面是復位作用
                        RT_WAITING_FOREVER,                         //一直等待
                        &e);                                        //e是 事件 的值


RT_EOK == rt_event_recv(&static_event, 
                        (EVENT_FLAG3 | EVENT_FLAG5),
                        RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,    //或
                        RT_WAITING_FOREVER, 
                        &e);
/*例程的列印資訊,我也不知道怎麼表示這個e是具體意思,只好把列印結果*/

thread2: send event3

thread1: OR recv event 0x8            //e

thread1: delay 1s to prepare the second event

thread2: send event5

thread2: send event3

thread2 leave.

thread1: AND recv event 0x28          //e

thread1 leave.

事件得接收時rt_event_rev()函式的具體使用方式,看了原始碼看一眼就能清楚。

4.事件的例程

#include <rtthread.h>

#define THREAD_PRIORITY      9
#define THREAD_TIMESLICE     5

#define EVENT_FLAG3 (1 << 3)
#define EVENT_FLAG5 (1 << 5)

/* 事件控制塊 */
static struct rt_event event;

ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;

/* 執行緒1入口函式 */
static void thread1_recv_event(void *param)
{
    rt_uint32_t e;

    /* 第一次接收事件,事件3或事件5任意一個可以觸發執行緒1,接收完後清除事件標誌 */
    if (rt_event_recv(&event, (EVENT_FLAG3 | EVENT_FLAG5),
                      RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                      RT_WAITING_FOREVER, &e) == RT_EOK)
    {
        rt_kprintf("thread1: OR recv event 0x%x\n", e);
    }

    rt_kprintf("thread1: delay 1s to prepare the second event\n");
    rt_thread_mdelay(1000);

    /* 第二次接收事件,事件3和事件5均發生時才可以觸發執行緒1,接收完後清除事件標誌 */
    if (rt_event_recv(&event, (EVENT_FLAG3 | EVENT_FLAG5),
                      RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
                      RT_WAITING_FOREVER, &e) == RT_EOK)
    {
        rt_kprintf("thread1: AND recv event 0x%x\n", e);
    }
    rt_kprintf("thread1 leave.\n");
}


ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;

/* 執行緒2入口 */
static void thread2_send_event(void *param)
{
    rt_kprintf("thread2: send event3\n");
    rt_event_send(&event, EVENT_FLAG3);
    rt_thread_mdelay(200);

    rt_kprintf("thread2: send event5\n");
    rt_event_send(&event, EVENT_FLAG5);
    rt_thread_mdelay(200);

    rt_kprintf("thread2: send event3\n");
    rt_event_send(&event, EVENT_FLAG3);
    rt_kprintf("thread2 leave.\n");
}

int event_sample(void)
{
    rt_err_t result;

    /* 初始化事件物件 */
    result = rt_event_init(&event, "event", RT_IPC_FLAG_FIFO);
    if (result != RT_EOK)
    {
        rt_kprintf("init event failed.\n");
        return -1;
    }

    rt_thread_init(&thread1,
                   "thread1",
                   thread1_recv_event,
                   RT_NULL,
                   &thread1_stack[0],
                   sizeof(thread1_stack),
                   THREAD_PRIORITY - 1, THREAD_TIMESLICE);
    rt_thread_startup(&thread1);

    rt_thread_init(&thread2,
                   "thread2",
                   thread2_send_event,
                   RT_NULL,
                   &thread2_stack[0],
                   sizeof(thread2_stack),
                   THREAD_PRIORITY, THREAD_TIMESLICE);
    rt_thread_startup(&thread2);

    return 0;
}