Embedded Software requires Timer functionality for solving many use cases. ESP-IDF is based on FreeRTOS and we use freertos api to design our application. FreeRTOS do provide software timers, but these timers have limitations such as it's smallest possible interval/period can be at best be qual to the RTOS tick period such as 1ms / 10ms . In addition, the software timer callbacks are dispatched from a low priority task. In order to address these issues we can get help from the ESP32 microcontroller itself. The microcontroller has dedicated hardware Timer peripheral as part of the SoC which does not consume any CPU processing and can execute as a higher priority interrupt
Timer Features
ESP-IDF has esp_timer API using which we can get hold of the internal 32bit hardware timer. Let’s see what it provides.
- It is a high resolution timer
- Provides one-shot timer
- Provides periodic timer
- Timer callbacks are dispatched from a high priority esp_timer task
it is recommended to make the code in the callback as small as possible, the callback can dispatch another low priority task using a queue
- Time since boot can be read using esp_timer_get_time()
- Enabling esp_timer profiling feature in menuconfig cause esp_timer_dump() function to print more information
Code-Walkthrough
Now we will go through this example to understand the usage of esp_timer https://github.com/espressif/esp-idf/tree/master/examples/system/esp_timer
The example code creates a periodic timer & a one-shot timer
To create a esp_timer type timer the following configuration type structure is needed to be instantiated
typedef struct { |
So we create one of the type above
const esp_timer_create_args_t periodic_timer_args = { |
Before creating the timer we also need a esp_timer_handle_t type handle with the following structure
struct esp_timer { |
So we create a handle out of the structure type above
esp_timer_handle_t periodic_timer; |
Now we will use the esp_timer_create() function to create the timer
esp_err_t esp_timer_create( |
Now as we have the arguments and handler variable instantiated, we will call The create function which is wrapped by ESP_ERROR_CHECK macro function
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer)); |
Now the timer is created but the timer has not started yet . we need to decide in which mode we want to run it either periodic or one-shot . Let’s run the timer in a periodic way so we use the esp_timer_start_periodic() function.
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 500000)); |
The called function definition is
/*Timer should not be running when this function is called. |
At the esp_timer_create_args_t type periodic_timer_args variable we assigned the callback member to a function named periodic_timer_callback . this is the function which will be called back periodically . we need to implement the callback in our C file but the function signature should be like
typedef void (*esp_timer_cb_t)(void* arg); |
Here is our implementation . we have put a debug msg to better visualize the timer in operation.
static void periodic_timer_callback(void* arg) |
This callback function prints the time since boot , periodically
In a similar way the example code creates one-shot type timer and runs it . you can run and see it’s operation.
Additional Note
If your application is a low power device and relies upon esp32 hardware timer then do take note of the following cases.
- Light sleep does not impact timer period. So after light sleep esp_timer_get_time() function returns accurate time.
- But Note during the light sleep the periodic timer & one shot timer callbacks do not execute since the CPU is not running during the light sleep. After waking up the callbacks get immediately fired up .
Reference
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/esp_timer.html#
0 comments:
Post a Comment