事件是什么,为什么需要事件?在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;
}