Timer

[中文]

Introduction

The ESP32 chip contains two hardware timer groups. Each group has two general-purpose hardware timers. They are all 64-bit generic timers based on 16-bit prescalers and 64-bit up / down counters which are capable of being auto-reloaded.

Functional Overview

The following sections of this document cover the typical steps to configure and operate a timer:

  • Timer Initialization - covers which parameters should be set up to get the timer working, and also what specific functionality is provided depending on the timer configuration.
  • Timer Control - describes how to read a timer’s value, pause or start a timer, and change how it operates.
  • Alarms - shows how to set and use alarms.
  • Interrupts- explains how to enable and use interrupts.

Timer Initialization

The two ESP32 timer groups, with two timers in each, provide the total of four individual timers for use. An ESP32 timer group should be identified using timer_group_t. An individual timer in a group should be identified with timer_idx_t.

First of all, the timer should be initialized by calling the function timer_init() and passing a structure timer_config_t to it to define how the timer should operate. In particular, the following timer parameters can be set:

  • Divider: Sets how quickly the timer’s counter is “ticking”. The setting divider is used as a divisor of the incoming 80 MHz APB_CLK clock.
  • Mode: Sets if the counter should be incrementing or decrementing. It can be defined using counter_dir by selecting one of the values from timer_count_dir_t.
  • Counter Enable: If the counter is enabled, it will start incrementing / decrementing immediately after calling timer_init(). You can change the behavior with counter_en by selecting one of the values from timer_start_t.
  • Alarm Enable: Can be set using alarm_en.
  • Auto Reload: Sets if the counter should auto_reload the initial counter value on the timer’s alarm or continue incrementing or decrementing.
  • Interrupt Type: Select which interrupt type should be triggered on the timer’s alarm. Set the value defined in timer_intr_mode_t.

To get the current values of the timer’s settings, use the function timer_get_config().

Timer Control

Once the timer is enabled, its counter starts running. To enable the timer, call the function timer_init() with counter_en set to true, or call timer_start(). You can specify the timer’s initial counter value by calling timer_set_counter_value(). To check the timer’s current value, call timer_get_counter_value() or timer_get_counter_time_sec().

To pause the timer at any time, call timer_pause(). To resume it, call timer_start().

To reconfigure the timer, you can call timer_init(). This function is described in Section Timer Initialization.

You can also reconfigure the timer by using dedicated functions to change individual settings:

Setting Dedicated Function Description
Divider timer_set_divider() Change the rate of ticking. To avoid unpredictable results, the timer should be paused when changing the divider. If the timer is running, timer_set_divider() pauses it, change the setting, and start the timer again.
Mode timer_set_counter_mode() Set if the counter should be incrementing or decrementing
Auto Reload timer_set_auto_reload() Set if the initial counter value should be reloaded on the timer’s alarm

Alarms

To set an alarm, call the function timer_set_alarm_value() and then enable the alarm using timer_set_alarm(). The alarm can also be enabled during the timer initialization stage, when timer_init() is called.

After the alarm is enabled, and the timer reaches the alarm value, the following two actions can occur depending on the configuration:

  • An interrupt will be triggered if previously configured. See Section Interrupts on how to configure interrupts.
  • When auto_reload is enabled, the timer’s counter will automatically be reloaded to start counting again from a previously configured value. This value should be set in advance with timer_set_counter_value().

Note

  • If an alarm value is set and the timer has already reached this value, the alarm is triggered immediately.
  • Once triggered, the alarm is disabled automatically and needs to be re-enabled to trigger again.

To check the specified alarm value, call timer_get_alarm_value().

Interrupts

Registration of the interrupt handler for a specific timer or a timer group can be done by calling timer_isr_register().

To enable interrupts for a timer group, call timer_group_intr_enable(), for a specific timer call timer_enable_intr(). To disable interrupts for a timer group, call timer_group_intr_disable(), for a specified timer, call timer_disable_intr().

When handling an interrupt within an interrupt serivce routine (ISR), the interrupt status bit needs to be explicitly cleared. To do that, set the TIMERGN.int_clr_timers.tM structure, defined in soc/esp32/include/soc/timer_group_struct.h. In this structure, N is the timer group number [0, 1], M is the timer number [0, 1]. For example, to clear an interrupt status bit for the timer 1 in the timer group 0, call the following:

TIMERG0.int_clr_timers.t1 = 1

For more information on how to use interrupts, please see the application example below.

Application Example

The 64-bit hardware timer example: peripherals/timer_group.

API Reference

Functions

esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *timer_val)

Read the counter value of hardware timer.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • timer_val: Pointer to accept timer counter value.

esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double *time)

Read the counter value of hardware timer, in unit of a given scale.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • time: Pointer, type of double*, to accept timer counter value, in seconds.

esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val)

Set counter value to hardware timer.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • load_val: Counter value to write to the hardware timer.

esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num)

Start the counter of hardware timer.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]

esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num)

Pause the counter of hardware timer.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]

esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir)

Set counting mode for hardware timer.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • counter_dir: Counting direction of timer, count-up or count-down

esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload)

Enable or disable counter reload function when alarm event occurs.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • reload: Counter reload mode.

esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider)

Set hardware timer source clock divider. Timer groups clock are divider from APB clock.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • divider: Timer clock divider value. The divider’s range is from from 2 to 65536.

esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value)

Set timer alarm value.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • alarm_value: A 64-bit value to set the alarm value.

esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *alarm_value)

Get timer alarm value.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • alarm_value: Pointer of A 64-bit value to accept the alarm value.

esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en)

Enable or disable generation of timer alarm events.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • alarm_en: To enable or disable timer alarm function.

esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void *), void *arg, int intr_alloc_flags, timer_isr_handle_t *handle, )

Register Timer interrupt handler, the handler is an ISR. The handler will be attached to the same CPU core that this function is running on.

Note
If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set, the handler function must be declared with IRAM_ATTR attribute and can only call functions in IRAM or ROM. It cannot call other timer APIs. Use direct register access to configure timers from inside the ISR in this case.
Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number
  • timer_num: Timer index of timer group
  • fn: Interrupt handler function.
  • arg: Parameter for handler function
  • intr_alloc_flags: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
  • handle: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.

esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config)

Initializes and configure the timer.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • config: Pointer to timer initialization parameters.

esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)

Get timer configure value.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
  • config: Pointer of struct to accept timer parameters.

esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t intr_mask)

Enable timer group interrupt, by enable mask.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • intr_mask: Timer interrupt enable mask.
    • TIMER_INTR_T0: t0 interrupt
    • TIMER_INTR_T1: t1 interrupt
    • TIMER_INTR_WDT: watchdog interrupt

esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t intr_mask)

Disable timer group interrupt, by disable mask.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • intr_mask: Timer interrupt disable mask.
    • TIMER_INTR_T0: t0 interrupt
    • TIMER_INTR_T1: t1 interrupt
    • TIMER_INTR_WDT: watchdog interrupt

esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num)

Enable timer interrupt.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index.

esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num)

Disable timer interrupt.

Return
  • ESP_OK Success
  • ESP_ERR_INVALID_ARG Parameter error
Parameters
  • group_num: Timer group number, 0 for TIMERG0 or 1 for TIMERG1
  • timer_num: Timer index.

Structures

struct timer_config_t

Data structure with timer’s configuration settings.

Public Members

bool alarm_en

Timer alarm enable

bool counter_en

Counter enable

timer_intr_mode_t intr_type

Interrupt mode

timer_count_dir_t counter_dir

Counter direction

bool auto_reload

Timer auto-reload

uint32_t divider

Counter clock divider. The divider’s range is from from 2 to 65536.

Macros

TIMER_BASE_CLK

Frequency of the clock on the input of the timer groups

Type Definitions

typedef intr_handle_t timer_isr_handle_t

Interrupt handle, used in order to free the isr after use. Aliases to an int handle for now.

Enumerations

enum timer_group_t

Selects a Timer-Group out of 2 available groups.

Values:

TIMER_GROUP_0 = 0

Hw timer group 0

TIMER_GROUP_1 = 1

Hw timer group 1

TIMER_GROUP_MAX
enum timer_count_dir_t

Decides the direction of counter.

Values:

TIMER_COUNT_DOWN = 0

Descending Count from cnt.high|cnt.low

TIMER_COUNT_UP = 1

Ascending Count from Zero

TIMER_COUNT_MAX
enum timer_alarm_t

Decides whether to enable alarm mode.

Values:

TIMER_ALARM_DIS = 0

Disable timer alarm

TIMER_ALARM_EN = 1

Enable timer alarm

TIMER_ALARM_MAX
enum timer_intr_mode_t

Select interrupt type if running in alarm mode.

Values:

TIMER_INTR_LEVEL = 0

Interrupt mode: level mode

TIMER_INTR_MAX
enum timer_autoreload_t

Select if Alarm needs to be loaded by software or automatically reload by hardware.

Values:

TIMER_AUTORELOAD_DIS = 0

Disable auto-reload: hardware will not load counter value after an alarm event

TIMER_AUTORELOAD_EN = 1

Enable auto-reload: hardware will load counter value after an alarm event

TIMER_AUTORELOAD_MAX