Event handling refactoring

This change separates definitions in esp_event.h and functions in event.c into several parts:
- event structure definitions (esp_event.h)
- default implementations of event handlers (event_default_handlers.c)
- default implementation of event loop (event_loop.c, esp_event_loop.h)

Purpose of this change is to allow applications choose their own poison:
- full control of event loop at the expense of more bootstrap code
- pre-defined event task firing event callbacks, but less code in app_main.c
This commit is contained in:
Ivan Grokhotkov 2016-09-26 01:17:32 +08:00
parent cc8dd46da2
commit 53de9f115f
4 changed files with 211 additions and 124 deletions

View file

@ -19,6 +19,7 @@
#include "esp_err.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "esp_task.h"
#include "freertos/FreeRTOS.h"
@ -29,14 +30,7 @@
#include "tcpip_adapter.h"
#include "esp_log.h"
#define ESP32_WORKAROUND 1
#if CONFIG_WIFI_ENABLED
static const char* TAG = "event";
static bool event_init_flag = false;
static xQueueHandle g_event_handler = NULL;
static system_event_cb_t g_event_handler_cb;
static void *g_event_ctx;
const char* TAG = "event";
#define WIFI_API_CALL_CHECK(info, api_call, ret) \
do{\
@ -175,15 +169,6 @@ esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event)
return ESP_OK;
}
static esp_err_t esp_wifi_post_event_to_user(system_event_t *event)
{
if (g_event_handler_cb) {
return (*g_event_handler_cb)(g_event_ctx, event);
}
return ESP_OK;
}
static esp_err_t esp_system_event_debug(system_event_t *event)
{
if (event == NULL) {
@ -274,7 +259,7 @@ static esp_err_t esp_system_event_debug(system_event_t *event)
return ESP_OK;
}
static esp_err_t esp_system_event_handler(system_event_t *event)
esp_err_t esp_event_process_default(system_event_t *event)
{
if (event == NULL) {
ESP_LOGE(TAG, "Error: event is null!");
@ -290,72 +275,7 @@ static esp_err_t esp_system_event_handler(system_event_t *event)
}
} else {
ESP_LOGE(TAG, "mismatch or invalid event, id=%d", event->event_id);
}
return esp_wifi_post_event_to_user(event);
}
static void esp_system_event_task(void *pvParameters)
{
system_event_t evt;
esp_err_t ret;
while (1) {
if (xQueueReceive(g_event_handler, &evt, portMAX_DELAY) == pdPASS) {
ret = esp_system_event_handler(&evt);
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "post event to user fail!");
}
}
}
}
system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx)
{
system_event_cb_t old_cb = g_event_handler_cb;
g_event_handler_cb = cb;
g_event_ctx = ctx;
return old_cb;
}
esp_err_t esp_event_send(system_event_t *event)
{
portBASE_TYPE ret;
ret = xQueueSendToBack((xQueueHandle)g_event_handler, event, 0);
if (pdPASS != ret) {
if (event) {
ESP_LOGE(TAG, "e=%d f", event->event_id);
} else {
ESP_LOGE(TAG, "e null");
}
return ESP_FAIL;
}
return ESP_OK;
}
void *esp_event_get_handler(void)
{
return (void *)g_event_handler;
}
esp_err_t esp_event_init(system_event_cb_t cb, void *ctx)
{
if (event_init_flag) {
return ESP_FAIL;
}
g_event_handler_cb = cb;
g_event_ctx = ctx;
g_event_handler = xQueueCreate(CONFIG_SYSTEM_EVENT_QUEUE_SIZE, sizeof(system_event_t));
xTaskCreatePinnedToCore(esp_system_event_task, "eventTask", ESP_TASKD_EVENT_STACK, NULL, ESP_TASKD_EVENT_PRIO, NULL, 0);
return ESP_OK;
}
#endif

View file

@ -0,0 +1,118 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "esp_err.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "esp_task.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "tcpip_adapter.h"
#include "esp_log.h"
#include "sdkconfig.h"
static const char* TAG = "event";
static bool s_event_init_flag = false;
static QueueHandle_t s_event_queue = NULL;
static system_event_cb_t s_event_handler_cb = NULL;
static void *s_event_ctx = NULL;
static esp_err_t esp_wifi_post_event_to_user(system_event_t *event)
{
if (s_event_handler_cb) {
return (*s_event_handler_cb)(s_event_ctx, event);
}
return ESP_OK;
}
static void esp_system_event_task(void *pvParameters)
{
system_event_t evt;
esp_err_t ret;
while (1) {
if (xQueueReceive(s_event_queue, &evt, portMAX_DELAY) == pdPASS) {
ret = esp_event_process_default(&evt);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "default event handler failed!");
}
ret = esp_wifi_post_event_to_user(&evt);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "post event to user fail!");
}
}
}
}
system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx)
{
system_event_cb_t old_cb = s_event_handler_cb;
s_event_handler_cb = cb;
s_event_ctx = ctx;
return old_cb;
}
esp_err_t esp_event_send(system_event_t *event)
{
portBASE_TYPE ret;
ret = xQueueSendToBack(s_event_queue, event, 0);
if (pdPASS != ret) {
if (event) {
ESP_LOGE(TAG, "e=%d f", event->event_id);
} else {
ESP_LOGE(TAG, "e null");
}
return ESP_FAIL;
}
return ESP_OK;
}
QueueHandle_t esp_event_loop_get_queue(void)
{
return s_event_queue;
}
esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx)
{
if (s_event_init_flag) {
return ESP_FAIL;
}
s_event_handler_cb = cb;
s_event_ctx = ctx;
s_event_queue = xQueueCreate(CONFIG_SYSTEM_EVENT_QUEUE_SIZE, sizeof(system_event_t));
xTaskCreatePinnedToCore(esp_system_event_task, "eventTask",
ESP_TASKD_EVENT_STACK, NULL, ESP_TASKD_EVENT_PRIO, NULL, 0);
s_event_init_flag = true;
return ESP_OK;
}

View file

@ -105,30 +105,6 @@ typedef struct {
system_event_info_t event_info; /**< event information */
} system_event_t;
/**
* @brief Application specified event callback function
*
* @param void *ctx : reserved for user
* @param system_event_t *event : event type defined in this file
*
* @return ESP_OK : succeed
* @return others : fail
*/
typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event);
/**
* @brief Set application specified event callback function
*
* @attention 1. If cb is NULL, means application don't need to handle
* If cb is not NULL, it will be call when an event is received, after the default event callback is completed
*
* @param system_event_cb_t cb : callback
* @param void *ctx : reserved for user
*
* @return system_event_cb_t : old callback
*/
system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx);
/**
* @brief Send a event to event task
*
@ -142,28 +118,20 @@ system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx);
esp_err_t esp_event_send(system_event_t *event);
/**
* @brief Get the event handler
* @brief Default event handler for system events
*
* @attention : currently this API returns event queue handler, by this event queue,
* users can notice when WiFi has done something like scanning done, connected to AP or disconnected from AP.
* This function performs default handling of system events.
* When using esp_event_loop APIs, it is called automatically before invoking the user-provided
* callback function.
*
* @param null
* Applications which implement a custom event loop must call this function
* as part of event processing.
*
* @return void * : event queue pointer
* @param event pointer to event to be handled
* @return ESP_OK if an event was handled successfully
*/
void *esp_event_get_handler(void);
esp_err_t esp_event_process_default(system_event_t *event);
/**
* @brief Init the event module
* Create the event handler and task
*
* @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb
* @param void *ctx : reserved for user
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_event_init(system_event_cb_t cb, void *ctx);
#ifdef __cplusplus
}

View file

@ -0,0 +1,81 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_EVENT_LOOP_H__
#define __ESP_EVENT_LOOP_H__
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "esp_event.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Application specified event callback function
*
* @param void *ctx : reserved for user
* @param system_event_t *event : event type defined in this file
*
* @return ESP_OK : succeed
* @return others : fail
*/
typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event);
/**
* @brief Initialize event loop
* Create the event handler and task
*
* @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb
* @param void *ctx : reserved for user
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx);
/**
* @brief Set application specified event callback function
*
* @attention 1. If cb is NULL, means application don't need to handle
* If cb is not NULL, it will be call when an event is received, after the default event callback is completed
*
* @param system_event_cb_t cb : callback
* @param void *ctx : reserved for user
*
* @return system_event_cb_t : old callback
*/
system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx);
/**
* @brief Get the queue used by event loop
*
* @attention : currently this API is used to initialize "q" parameter
* of wifi_init structure.
*
* @return QueueHandle_t : event queue handle
*/
QueueHandle_t esp_event_loop_get_queue(void);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_EVENT_LOOP_H__ */