esp32-system-api: Event Loop Library
Env
esp-idf: v5.3-stable
数据结构介绍
事件处理函数
当事件到达后,运行的函数名为事件处理函数。
事件处理函数要在事件循环创建完成之后调用注册函数注册进入事件循环。
事件处理函数定义如下:
typedef void (*esp_event_handler_t)(void* event_handler_arg, |
事件循环句柄
事件循环句柄的内存与值由API决定,用户并不参与,所以用户在创建事件循环句柄的时候应该创建为指针,调用esp_event_loop_create函数创建事件循环句柄,经该函数创建的事件循环句柄称为用户事件循环句柄。
事件循环句柄类型:esp_event_loop_handle_t
PS: 这个类型已经为一个指针。
e.g.:
esp_event_loop_handle_t loop_handle; |
事件循环配置项
上面提到事件循环句柄由API创建,那么如果想配置事件循环就要用到事件循环配置项。
事件循环配置项定义如下:
/// Configuration for creating event loops |
配置项解析如下:
- queue_size: 事件循环队列大小,指在
事件没发送到事件处理函数之前,该事件循环最多能容纳的事件数量。 - task_name: 是否选择定义一个
线程去读取事件循环的队列,并且在读取到数据后执行事件处理函数,如果该参数为NULL,则没有专用线程读取事件并执行事件处理函数,需要手动调用esp_event_loop_run函数去读取队列执行事件处理函数,并且下面三个成员配置项无效。 - task_priority:
事件循环专用线程的优先级配置,可使用uxTaskPriorityGet(NULL)函数获取当前线程优先级附加给它。 - task_stack_size: 该
专用线程的堆栈大小,不建议太小,会溢出,3072是一个普遍安全值。 - task_core_id: 该事件循环
专用线程在哪个核心上执行,应该≥0&& <CONFIG_FREERTOS_NUMBER_OF_CORES,该宏在sdkconfig定义了最大核心数。也可以使用tskNO_AFFINITY宏定义不指定任何一个核心,由FreeRTOS指定。
EVENT_BASE与EVENT_ID
每个事件循环都应该有事件处理函数,否则事件循环毫无意义。
在事件处理函数中区别事件的唯一方式就是通过EVENT_BASE与EVENT_ID。
这两个类似于Linux的major与minor。
如EVENT_BASE可以是WIFI_EVENT,EVENT_ID可以是CONNECTED、GOT_IP等。
EVENT_BASE定义方式如下:
ESP_EVENT_DECLARE_BASE(MY_EVENT_BASE); |
EVENT_ID推荐通过enum定义:
enum { |
API
该章节涵盖了常用API以及简介,欲知更详细,请见[1]
esp_event_loop_create: 该函数创建了事件循环,两个入参一个是事件循环句柄,一个是事件循环参数。esp_event_loop_create_default: 该函数创建了默认的事件循环,由于一些事件的推送不能由用户提交到队列,如wifi连接事件,获取ip事件等,所以便有了默认的事件循环,具体见[4]esp_event_loop_delete:删除事件循环,入参是事件循环句柄。esp_event_loop_delete_default: 删除默认事件循环esp_event_handler_register_with: 注册事件处理函数到某个事件循环,需要提供该事件处理函数所处理的EVENT_BASE和EVENT_ID,一个事件处理函数可用不同的EVENT注册多次,也可以使用ESP_EVENT_ANY_ID去处理整个EVENT_BASE下的IDesp_event_handler_unregister_with: 注销某个事件处理函数esp_event_handler_register: 为默认事件循环注册事件处理函数,除了不需要提供事件循环句柄以外,与esp_event_handler_register无异。esp_event_handler_unregister: 为默认事件循环注销事件处理函数,除了不需要提供事件循环句柄以外,与esp_event_handler_register无异。esp_event_post_to: 向指定的事件循环发送事件。esp_event_post: 向默认的事件循环发送事件esp_event_loop_run: 当在事件循环参数内没有配置task_name时,就不用有专有线程去读取队列并且执行事件处理函数,此时需要调用esp_event_loop_run手动读取并调用事件处理函数,该函数两个入参分别为事件循环句柄和运行tick
Example
用户事件循环
专属线程
/* 事件循环句柄 */ |
没有专属线程
/* 事件循环句柄 */ |
Ref
[1]https://docs.espressif.com/projects/esp-idf/zh_CN/v5.3/esp32/api-reference/system/esp_event.html
[2]https://github.com/espressif/esp-idf/tree/v5.3/examples/system/esp_event/user_event_loops
[3]https://github.com/espressif/esp-idf/tree/v5.3/examples/system/esp_event/default_event_loop
[4]https://docs.espressif.com/projects/esp-idf/zh_CN/v5.3/esp32/api-reference/system/esp_event.html#esp-event-default-loops
