摘要
编写一个简单的事件处理循环,用于单片机裸机编程。考虑到中断函数中不可调用malloc,未采用动态内存分配的形式编写事件链表。
eventloop.h
#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__
typedef enum {
EventTypeNull,
EventTypeHardIrp0,
EventTypeHardIrp1,
EventTypeTimer1,
EventTypeTimer2,
EventTypeTimer3,
}EventType;
/**
* @brief 发送事件到处理循环
*
* @param type 事件类型
* @param handle 事件处理方法
* @param param 事件处理方法传入的参数
* @return int 成功返回0,失败返回负值
*/
int send_event(EventType type, void(*handle)(void *), void *param);
/**
* @brief 开始事件处理循环
*
*/
void event_loop_start(void);
/**
* @brief 初始化事件处理循环
*
* @param depth 堆栈深度
* @return int 成功返回0,失败返回负值
*/
int event_loop_init(int depth);
#endif
eventloop.c
#include "eventloop.h"
#include "stdlib.h"
#include "stdio.h"
typedef struct Event
{
EventType type;
void (*handle)(void *);
void *param;
}Event_t;
typedef struct EventLoop
{
Event_t *event;
int depth;
int ps;
int pe;
}EventLoop_t;
static EventLoop_t loop;
int send_event(EventType type, void(*handle)(void *), void *param)
{
int next = (loop.pe + 1) % loop.depth;
if (next == loop.ps)
return -1;//事件堆栈已满
loop.event[loop.pe].type = type;
loop.event[loop.pe].handle = handle;
loop.event[loop.pe].param = param;
loop.pe = next;
return 0;
}
int event_loop_init(int depth)
{
loop.event = malloc(sizeof(Event_t) * (depth + 1));
if (loop.event == NULL)
return -1;
loop.depth = depth + 1;
loop.ps = 0;
loop.pe = 0;
return 0;
}
void event_loop_start(void)
{
while (1)
{
if (loop.ps != loop.pe)
{
loop.pe = loop.pe == 0 ? loop.depth - 1 : loop.pe - 1;
loop.event[loop.pe].handle(loop.event[loop.pe].param);
}
}
return;
}
test.c
#include "eventloop.h"
#include "stdio.h"
void hardirp_handle(void *param)
{
printf("hardirp handle param == %d\n", (int)param);
}
int main(void)
{
int err = event_loop_init(10);
int i;
for (i = 0; i < 10; i++)
{
send_event(EventTypeHardIrp0, hardirp_handle, (void *)i);
}
event_loop_start();
return 0;
}
代码说明
通过 event_loop_init 函数初始化模块内部封装的事件堆栈,然后在main函数中执行 event_loop_start 即可。test.c中模拟中断调用send_event函数将事件本身和事件处理函数发送到事件处理循环。
可修改 EventLoop_t 结构体和event_loop_start,send_event 函数,添加事件处理优先级属性,优先处理优先级高的事件。
可修改 EventLoop_t 结构体和event_loop_init,event_loop_start函数,增加事件处理等待方式为fifo模式或者优先级等待模式。