主要参考资料:
事件循环库: https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-reference/system/esp_event.html
Event Loop 大白话版: https://www.bilibili.com/video/BV1FD4y1j79J/?spm_id_from=333.999.0.0&vd_source=dd284033cd0c4d1f3f59a2cd40ae4ef9
目录
- 简介
- 使用方法
- ESP32默认事件循环
- 事件循环性能分析
简介
事件循环库允许 ESP32 执行异步编程,这意味着它可以在等待一个操作(如网络请求或文件读写)完成的同时,继续执行其他任务。
在资源受限的嵌入式设备上,传统的多线程或多进程并发模型可能会消耗大量内存和处理能力。
事件循环库通过单线程的协程提供了一种轻量级的并发机制,减少了资源消耗。
使用方法
事件循环库的使用流程:
// 1. 定义事件处理程序
void run_on_event(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data)
{
// 事件处理程序逻辑
}
void app_main()
{
// 2. 用一个类型为 esp_event_loop_args_t 的配置结构体,指定所创建循环的属性。获取一个类型为 esp_event_loop_handle_t 的句柄,用于其他 API 引用循环、执行操作。
esp_event_loop_args_t loop_args = {
.queue_size = ...,
.task_name = ...
.task_priority = ...,
.task_stack_size = ...,
.task_core_id = ...
};
esp_event_loop_handle_t loop_handle;
esp_event_loop_create(&loop_args, &loop_handle);
// 3. 注册在 (1) 中定义的事件处理程序。MY_EVENT_BASE 和 MY_EVENT_ID 指定了一个假设事件:将处理程序 run_on_event 发布到循环中时,执行该处理程序。
esp_event_handler_register_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event, ...);
...
// 4. 将事件发布到循环中。此时,事件排入事件循环队列,在某个时刻,事件循环会执行已注册到发布事件的事件处理程序,例如此处的 run_on_event。为简化过程,此示例从 app_main 调用 esp_event_post_to,实际应用中可从任何其他任务中发布事件。
esp_event_post_to(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, ...);
...
// 5. 注销无用的处理程序。
esp_event_handler_unregister_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event);
...
// 6. 删除无用的事件循环。
esp_event_loop_delete(loop_handle);
}
ESP32默认事件循环
默认事件循环是一种特殊循环,用于处理系统事件(如 Wi-Fi 事件)。用户无法使用该循环的句柄,创建、删除、注册/注销处理程序以及事件发布均通过用户事件循环 API 的变体完成,下表列出了这些变体及其对应用户事件循环。
比较二者签名可知,它们大部分是相似的,唯一区别在于默认事件循环的 API 不需要指定循环句柄。
除了 API 的差异和用于系统事件的特殊分类外,默认事件循环和用户事件循环的行为并无差异。实际上,用户甚至可以将自己的事件发布到默认事件循环中,以节省内存而无需创建自己的循环。
事件循环性能分析
要启动数据收集,统计所有已创建事件循环的数据,请激活配置选项 CONFIG_ESP_EVENT_LOOP_PROFILING,函数 esp_event_dump() 可将收集的统计数据输出到文件流中。