General Purpose Timer
Introduction
The ESP32-C3 chip contains two hardware timer groups. Each group has one general-purpose hardware timer(s). They are all 54-bit generic timers based on 16-bit pre-scalers and 54-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 use interrupt callbacks.
Timer Initialization
The two ESP32-C3 timer groups, with one timer(s) in each, provide the total of two individual timers for use. An ESP32-C3 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:
Clock Source: Select the clock source, which together with the Divider define the resolution of the working timer.
Divider: Sets how quickly the timer’s counter is “ticking”. The setting
divider
is used as a divisor of the clock source that by default is APB_CLK running at 80 MHz. For more information of APB_CLK frequency, please check ESP32-C3 Technical Reference Manual > Reset and Clock [PDF] chapter for more details.Mode: Sets if the counter should be incrementing or decrementing. It can be defined using
counter_dir
by selecting one of the values fromtimer_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 withcounter_en
by selecting one of the values fromtimer_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.
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 |
Change the rate of ticking. To avoid unpredictable results, the timer should be paused when changing the divider. If the timer is running, |
|
Mode |
Set if the counter should be incrementing or decrementing |
|
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 withtimer_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 an interrupt callback for a specific timer can be done by calling timer_isr_callback_add()
and passing in the group ID, timer ID, callback handler and user data. The callback handler will be invoked in ISR context, so user shouldn’t put any blocking API in the callback function.
The benefit of using interrupt callback instead of precessing interrupt from scratch is, you don’t have to deal with interrupt status check and clean stuffs, they are all addressed before the callback got run in driver’s default interrupt handler.
For more information on how to use interrupts, please see the application example below.
Application Example
The 54-bit hardware timer example: peripherals/timer_group.
API Reference
Header File
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num)
Start the counter of hardware timer.
- 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]
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num)
Pause the counter of hardware timer.
- 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]
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider)
Set hardware divider of the source clock to the timer group. By default, the source clock is APB clock running at 80 MHz. For more information, please check Chapter Reset and Clock in Chip Technical Reference Manual.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_isr_callback_add(timer_group_t group_num, timer_idx_t timer_num, timer_isr_t isr_handler, void *arg, int intr_alloc_flags)
Add ISR handle callback for the corresponding timer.
The callback should return a bool value to determine whether need to do YIELD at the end of the ISR.
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.
Note
This ISR handler will be called from an ISR. This ISR handler do not need to handle interrupt status, and should be kept short. If you want to realize some specific applications or write the whole ISR, you can call timer_isr_register(…) to register ISR.
- Parameters
group_num – Timer group number
timer_num – Timer index of timer group
isr_handler – Interrupt handler function, it is a callback 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_isr_callback_remove(timer_group_t group_num, timer_idx_t timer_num)
Remove ISR handle callback for the corresponding timer.
- Parameters
group_num – Timer group number
timer_num – Timer index of timer group
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
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.
Note
If use this function to reigster ISR, you need to write the whole ISR. In the interrupt handler, you need to call timer_spinlock_take(..) before your handling, and call timer_spinlock_give(…) after your handling.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
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.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num)
Deinitializes the timer.
- 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]
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)
Get timer configure value.
- 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.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t intr_mask)
Enable timer group interrupt, by enable mask.
- 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
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t intr_mask)
Disable timer group interrupt, by disable mask.
- 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
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num)
Enable timer interrupt.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num)
Disable timer interrupt.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
void timer_group_intr_clr_in_isr(timer_group_t group_num, timer_idx_t timer_num)
Clear timer interrupt status, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
-
void timer_group_clr_intr_status_in_isr(timer_group_t group_num, timer_idx_t timer_num)
Clear timer interrupt status, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
-
void timer_group_enable_alarm_in_isr(timer_group_t group_num, timer_idx_t timer_num)
Enable alarm interrupt, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
-
uint64_t timer_group_get_counter_value_in_isr(timer_group_t group_num, timer_idx_t timer_num)
Get the current counter value, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
- Returns
Counter value
-
void timer_group_set_alarm_value_in_isr(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_val)
Set the alarm threshold for the timer, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
alarm_val – Alarm threshold.
-
void timer_group_set_counter_enable_in_isr(timer_group_t group_num, timer_idx_t timer_num, timer_start_t counter_en)
Enable/disable a counter, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index.
counter_en – Enable/disable.
-
timer_intr_t timer_group_intr_get_in_isr(timer_group_t group_num)
Get the masked interrupt status, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
- Returns
Interrupt status
-
uint32_t timer_group_get_intr_status_in_isr(timer_group_t group_num)
Get interrupt status, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
- Returns
Interrupt status
-
void timer_group_clr_intr_sta_in_isr(timer_group_t group_num, timer_intr_t intr_mask)
Clear the masked interrupt status, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
intr_mask – Masked interrupt.
-
bool timer_group_get_auto_reload_in_isr(timer_group_t group_num, timer_idx_t timer_num)
Get auto reload enable status, just used in ISR.
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
timer_num – Timer index
- Returns
True Auto reload enabled
False Auto reload disabled
-
esp_err_t timer_spinlock_take(timer_group_t group_num)
Take timer spinlock to enter critical protect.
Note
Deprecated, the recommended way is to use ISR callbacks instead, see timer_group_example_main
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
-
esp_err_t timer_spinlock_give(timer_group_t group_num)
Give timer spinlock to exit critical protect.
Note
Deprecated, the recommended way is to use ISR callbacks instead, see timer_group_example_main
- Parameters
group_num – Timer group number, 0 for TIMERG0 or 1 for TIMERG1
- Returns
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
Type Definitions
-
typedef bool (*timer_isr_t)(void*)
Interrupt handle callback function. User need to retrun a bool value in callback.
Note
If you called FreeRTOS functions in callback, you need to return true or false based on the retrun value of argument
pxHigherPriorityTaskWoken
. For example,xQueueSendFromISR
is called in callback, if the return valuepxHigherPriorityTaskWoken
of any FreeRTOS calls is pdTRUE, return true; otherwise return false.- Return
True Do task yield at the end of ISR
False Not do task yield at the end of ISR
-
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.
Header File
Structures
-
struct timer_config_t
Data structure with timer’s configuration settings.
Public Members
-
timer_alarm_t alarm_en
Timer alarm enable
-
timer_start_t counter_en
Counter enable
-
timer_intr_mode_t intr_type
Interrupt mode
-
timer_count_dir_t counter_dir
Counter direction
-
timer_autoreload_t auto_reload
Timer auto-reload
-
uint32_t divider
Counter clock divider. The divider’s range is from from 2 to 65536.
-
timer_src_clk_t clk_src
Use XTAL as source clock.
-
timer_alarm_t alarm_en
Enumerations
-
enum timer_group_t
Selects a Timer-Group out of 2 available groups.
Values:
-
enumerator TIMER_GROUP_0
Hw timer group 0
-
enumerator TIMER_GROUP_1
Hw timer group 1
-
enumerator TIMER_GROUP_MAX
-
enumerator TIMER_GROUP_0
-
enum timer_idx_t
Select a hardware timer from timer groups.
Values:
-
enumerator TIMER_0
Select timer0 of GROUPx
-
enumerator TIMER_MAX
-
enumerator TIMER_0
-
enum timer_count_dir_t
Decides the direction of counter.
Values:
-
enumerator TIMER_COUNT_DOWN
Descending Count from cnt.high|cnt.low
-
enumerator TIMER_COUNT_UP
Ascending Count from Zero
-
enumerator TIMER_COUNT_MAX
-
enumerator TIMER_COUNT_DOWN
-
enum timer_start_t
Decides whether timer is on or paused.
Values:
-
enumerator TIMER_PAUSE
Pause timer counter
-
enumerator TIMER_START
Start timer counter
-
enumerator TIMER_PAUSE
-
enum timer_intr_t
Interrupt types of the timer.
Values:
-
enumerator TIMER_INTR_T0
interrupt of timer 0
-
enumerator TIMER_INTR_WDT
interrupt of watchdog
-
enumerator TIMER_INTR_NONE
-
enumerator TIMER_INTR_T0
-
enum timer_alarm_t
Decides whether to enable alarm mode.
Values:
-
enumerator TIMER_ALARM_DIS
Disable timer alarm
-
enumerator TIMER_ALARM_EN
Enable timer alarm
-
enumerator TIMER_ALARM_MAX
-
enumerator TIMER_ALARM_DIS
-
enum timer_intr_mode_t
Select interrupt type if running in alarm mode.
Values:
-
enumerator TIMER_INTR_LEVEL
Interrupt mode: level mode
-
enumerator TIMER_INTR_MAX
-
enumerator TIMER_INTR_LEVEL
-
enum timer_autoreload_t
Select if Alarm needs to be loaded by software or automatically reload by hardware.
Values:
-
enumerator TIMER_AUTORELOAD_DIS
Disable auto-reload: hardware will not load counter value after an alarm event
-
enumerator TIMER_AUTORELOAD_EN
Enable auto-reload: hardware will load counter value after an alarm event
-
enumerator TIMER_AUTORELOAD_MAX
-
enumerator TIMER_AUTORELOAD_DIS