10

vesperW · 5 天前

零内存泄漏!2KB高效实现事件驱动框架,推荐这款开源事件管理器——LwEVT

大家好,我是麦鸽。

在嵌入式系统开发中,事件驱动架构(Event-Driven Architecture)因其高效性和灵活性,已成为处理多任务、异步操作的重要模式。

今天推荐一个开源项目——lwEVTLwEVT(Lightweight Event Manager) ,一款开源事件管理库。

项目主页

项目主页

项目地址:https://github.com/MaJerle/lwevt

这是一个简单的嵌入式系统事件管理器。其主要目的是能够从应用程序的各个模块发送各种事件。

应用程序可以定义自定义类型和可选的数据结构,以便将事件发送给不同的应用程序监听器。

这个有点像 QT 中的信号和槽机制。

LwEVT 核心特性

跨平台轻量化设计

基于 C11 标准实现的 LwEVT 仅需数 KB 非易失性存储空间,完全摆脱硬件架构依赖。

其核心代码经过高度优化,即使在资源受限的 8 位 MCU 上也能流畅运行。

灵活事件类型定义

开发者可通过 lwevt_type_t 自定义事件类型,支持动态注册/注销事件处理器。

每个事件可携带自定义数据结构,例如传感器数据包或系统状态变更信息,实现类型安全的数据传递。

高效内存管理

采用静态内存分配策略,通过编译时预定义事件队列深度和处理器数量,完全规避动态内存分配风险。

非阻塞式事件处理

基于先进先出的队列机制,支持中断上下文安全触发事件。

独特的优先级分级机制允许关键事件(如硬件故障报警)优先处理,确保系统实时性要求。

示例

具体示例可以参考 example;

事件类型

每个应用程序都各不相同,需要使用不同类型的事件及其相关数据。因此,定义 lwevt_types.h 事件文件至关重要; 有以下 2 种方法可以定义事件类型:

  • 基本事件类型 LWEVT_TYPE_BASIC
  • 扩展事件类型,其中 LWEVT_TYPE_EXT 还包括作为事件一部分的数据结构
/* Define basic types */
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_1)
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_2)
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_3)

/* Define extended types */
LWEVT_TYPE_EXT(LWEVT_TYPE_MY_EXT_1, struct { int par1; int par2; } ext1)
LWEVT_TYPE_EXT(LWEVT_TYPE_MY_EXT_2, struct { int par3; int par4; } ext2)
LWEVT_TYPE_EXT(LWEVT_TYPE_MY_EXT_3, struct { int par1; int par2; } ext3)

产生事件

A 模块产生事件,不需要订阅事件,比如按键产生按下的事件;

#include "lwevt/lwevt.h"

void
produce() {
    lwevt_t* evt;

    /* Initialize event management system = must be called only once in the application */
    lwevt_init();
    
    /*
     * Get event handle, set event data and dispatch event
     *
     * Send basic event - without any data
     */
    evt = lwevt_get_handle();
    lwevt_dispatch(LWEVT_TYPE_MY_BASIC_1);

    /*
     * Get event handle, set event data and dispatch event
     *
     * Send extended event - with data
     */
    evt = lwevt_get_handle();
    evt->msg.ext1.par1 = 10;    /* Some value */
    evt->msg.ext1.par2 = 12;    /* Some value */
    lwevt_dispatch(LWEVT_TYPE_MY_EXT_1);
    return0;
}

订阅事件

B 模块订阅事件,涉及调用 lwevt_register()以回调函数为参数的函数。

所有事件都在回调函数 prv_evt_fn 中处理。A 模块事件会触发 B 模块的回调。

#include "lwevt/lwevt.h"

/* Define event functions */
static void
prv_evt_fn(lwevt_t* e) {
    printf("Event type: %u\r\n", (unsigned)e->type);
    switch (e->type) {
        case LWEVT_TYPE_MY_BASIC_1: {
            printf("Basic event type - no data\r\n");
            break;
        }
        case LWEVT_TYPE_MY_EXT_1: {
            printf("Extended event type - with data: par1: %d, par2: %d\r\n",
                (int)e->msg.ext1.par1, (int)e->msg.ext1.par2);
            break;
        }
        default:
            break;
    }
}

int
main() {
    lwevt_t* evt;

    /* Initialize event management system = must be called only once in the application  */
    lwevt_init();

    /* Set 2 custom functions for event */
    lwevt_register(prv_evt_fn);

    /* Do nothing - events are handled in callback function */

    return0;
}

总结

LwEVT 对于低资源占用的嵌入式开发者而言,还是比较使用的,也方便后期项目的扩展和维护。

END

作者:麦鸽
来源:小麦大叔

推荐阅读

欢迎大家点赞留言,更多 Arm 技术文章动态请关注极术社区嵌入式客栈专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

推荐阅读
关注数
2922
内容数
364
分享一些在嵌入式应用开发方面的浅见,广交朋友
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息