ESP32 Default Event Loop

ESP-IDF has an Event Loop Library. This library allows you to create an Event Loop and declare Events to which other components of your code can register handlers. A handler is a function that gets executed when a particular event occurs. Following this pattern we can get a taste of Event Driven Programming in general. 

A default event loop is already prepared by the IDF; it is responsible for generating major events like

  • WIFI_EVENT
  • IP_EVENT
  • IP_EVENT_STA_GOT_IP

You only need to call a function that will create the default event loop.

After that, you don’t have to create/run any freertos task to run the default event loop. the default Loop runs internally

You can register to the default event loop for events like WIFI_EVENT and handle the event according to your needs. You can also create your own events and post them to the default event loop. Other code components of yours can register by the events created by you.

In this way, the default event loop can generate/dispatch major system Events as well as user-created ones. I guess This is sufficient for most of the application design, but if you really need an event loop other than the default you can create one, but then you will also have to run it by a freeRtos Task.

To distinguish between default & User event loop the API provided by the esp_event library is slightly different for both the cases

Default Event Loops User Event Loops
esp_event_loop_create_default()                       esp_event_loop_create()
esp_event_loop_delete_default() esp_event_loop_delete()
esp_event_handler_register() esp_event_handler_register_with()
esp_event_handler_unregister() esp_event_handler_unregister_with()
esp_event_post() esp_event_post_to()

EVENTS

An Event consists of 2 identifiers

  • The Event Base
  • The Event ID

There can be multiple event ID under 1 Event Base

The esp_event library has Macros to declare and define events

Now we will follow the following example code to know how to use the default event loop

https://github.com/espressif/esp-idf/tree/master/examples/system/esp_event/default_event_loop

In The example, a timer is made using esp_timer API and 3 event sources are created related to the timer. The events are

  • An event is generated when timer is raised
  • An event is generated when timer period expires
  • An event is generated when the time is stopped

first, declare Event in the event_source.h header file

// event_source.h
// Declare an event base
ESP_EVENT_DECLARE_BASE(TIMER_EVENTS); // declaration of the timer events family

enum {               // declaration of the specific events under the timer event family
    TIMER_EVENT_STARTED,       // raised when the timer is first started
    TIMER_EVENT_EXPIRY,        // raised when a period of the timer has elapsed
    TIMER_EVENT_STOPPED        // raised when the timer has been stopped
};

Then define the event in main.c implementation file

/* Event source periodic timer related definitions */
ESP_EVENT_DEFINE_BASE(TIMER_EVENTS);

Create the default event loop as

// Create the default event loop
ESP_ERROR_CHECK(esp_event_loop_create_default());

To register an Event to the default event loop we have to use the following function

esp_err_t esp_event_handler_register(
esp_event_base_t  event_base,
                  int32_t event_id,
                  esp_event_handler_t event_handler,
                  void* event_handler_arg
                );

For example, to register the event of timer start the event base & Event ID is passed as follows

// Register the specific timer event handlers.
ESP_ERROR_CHECK(esp_event_handler_register(
                                 TIMER_EVENTS, 
                                 TIMER_EVENT_STARTED, 
                                 timer_started_handler, 
                                 NULL));

To Post an Event to the default loop you have to use the following function. Remember you have to post your events to the default loop, default loop will then dispatch the event to the listening subscribers

esp_err_t esp_event_post(
                    esp_event_base_t      event_base,
                    int32_t               event_id,
                    void*                   event_data,
                    size_t                   event_data_size,
                    TickType_t               ticks_to_wait
                    );

So the example code starts the timer and posts this very starting event to the default loop

ESP_ERROR_CHECK(esp_timer_start_periodic(TIMER, TIMER_PERIOD));
ESP_ERROR_CHECK(esp_event_post(
                               TIMER_EVENTS, 
                               TIMER_EVENT_STARTED, 
                               NULL, 
                               0, 
                               portMAX_DELAY)
                               );

As soon as this event is got by the default loop, it dispatches the event to the corresponding handler which was registered before this event

// Handler which executes when the timer started event gets executed by the loop.
static void timer_started_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data)
{
    ESP_LOGI(TAG, "%s:%s: timer_started_handler", base, get_id_string(base, id));
}

The handler basically prints a log about the event

So this is how you can use the default event loop to design an event-driven application

Reference

https://github.com/espressif/esp-idf/tree/master/examples/system/esp_event/default_event_loop

0 comments:

Post a Comment

Categories

Pages

Firmware Engineer

My photo
Works on Firmware, Embedded Linux, Smart Metering, RTOS, IoT backend

Contact Form

Name

Email *

Message *

Copyrighted by Hassin. Powered by Blogger.