Timer

About

The ESP32 SoCs contains from 2 to 4 hardware timers. They are all 64-bit (54-bit for ESP32-C3) generic timers based on 16-bit pre-scalers and 64-bit (54-bit for ESP32-C3) up / down counters which are capable of being auto-reloaded.

ESP32 SoC

Number of timers

ESP32

4

ESP32-S2

4

ESP32-C3

2

ESP32-S3

4

Arduino-ESP32 Timer API

timerBegin

This function is used to configure the timer. After successful setup the timer will automatically start.

hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp);
  • num select timer number.

  • divider select timer divider.

  • resolution select timer resolution.

    • range is 1-14 bits (1-20 bits for ESP32).

This function will return timer structure if configuration is successful. If NULL is returned, error occurs and the timer was not configured.

timerEnd

This function is used to end timer.

void timerEnd(hw_timer_t *timer);
  • timer timer struct.

timerSetConfig

This function is used to configure initialized timer (timerBegin() called).

uint32_t timerGetConfig(hw_timer_t *timer);
  • timer timer struct.

This function will return configuration as uint32_t number. This can be translated by inserting it to struct timer_cfg_t.val.

timerAttachInterrupt

This function is used to attach interrupt to timer.

void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
  • timer timer struct.

  • fn funtion to be called when interrupt is triggered.

  • edge select edge to trigger interrupt (only LEVEL trigger is currently supported).

timerDetachInterrupt

This function is used to detach interrupt from timer.

void timerDetachInterrupt(hw_timer_t *timer);
  • timer timer struct.

timerStart

This function is used to start counter of the timer.

void timerStart(hw_timer_t *timer);
  • timer timer struct.

timerStop

This function is used to stop counter of the timer.

void timerStop(hw_timer_t *timer);
  • timer timer struct.

timerRestart

This function is used to restart counter of the timer.

void timerRestart(hw_timer_t *timer);
  • timer timer struct.

timerWrite

This function is used to set counter value of the timer.

void timerWrite(hw_timer_t *timer, uint64_t val);
  • timer timer struct.

  • val counter value to be set.

timerSetDivider

This function is used to set the divider of the timer.

void timerSetDivider(hw_timer_t *timer, uint16_t divider);
  • timer timer struct.

  • divider divider to be set.

timerSetCountUp

This function is used to configure counting direction of the timer.

void timerSetCountUp(hw_timer_t *timer, bool countUp);
  • timer timer struct.

  • countUp select counting direction (true = increment).

timerSetAutoReload

This function is used to set counter value of the timer.

void timerSetAutoReload(hw_timer_t *timer, bool autoreload);
  • timer timer struct.

  • autoreload select autoreload (true = enabled).

timerStarted

This function is used to get if the timer is running.

bool timerStarted(hw_timer_t *timer);
  • timer timer struct.

This function will return true if the timer is running. If false is returned, timer is stopped.

timerRead

This function is used to read counter value of the timer.

uint64_t timerRead(hw_timer_t *timer);
  • timer timer struct.

This function will return counter value of the timer.

timerReadMicros

This function is used to read counter value in microseconds of the timer.

uint64_t timerReadMicros(hw_timer_t *timer);
  • timer timer struct.

This function will return counter value of the timer in microseconds.

timerReadMilis

This function is used to read counter value in miliseconds of the timer.

uint64_t timerReadMilis(hw_timer_t *timer);
  • timer timer struct.

This function will return counter value of the timer in miliseconds.

timerReadSeconds

This function is used to read counter value in seconds of the timer.

double timerReadSeconds(hw_timer_t *timer);
  • timer timer struct.

This function will return counter value of the timer in seconds.

timerGetDivider

This function is used to get divider of the timer.

uint16_t timerGetDivider(hw_timer_t *timer);
  • timer timer struct.

This function will return divider of the timer.

timerGetCountUp

This function is used get counting direction of the timer.

bool timerGetCountUp(hw_timer_t *timer);
  • timer timer struct.

This function will return true if the timer counting direction is UP (incrementing). If false returned, the timer counting direction is DOWN (decrementing).

timerGetAutoReload

This function is used to get configuration of auto reload of the timer.

bool timerGetAutoReload(hw_timer_t *timer);
  • timer timer struct.

This function will return true if the timer auto reload is enabled. If false returned, the timer auto reload is disabled.

timerAlarmEnable

This function is used to enable generation of timer alarm events.

void timerAlarmEnable(hw_timer_t *timer);
  • timer timer struct.

timerAlarmDisable

This function is used to disable generation of timer alarm events.

void timerAlarmDisable(hw_timer_t *timer);
  • timer timer struct.

timerAlarmWrite

This function is used to configure alarm value and autoreload of the timer.

void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload);
  • timer timer struct.

  • alarm_value alarm value to generate event.

  • autoreload enabled/disabled autorealod.

timerAlarmEnabled

This function is used to get status of timer alarm.

bool timerAlarmEnabled(hw_timer_t *timer);
  • timer timer struct.

This function will return true if the timer alarm is enabled. If false returned, the timer alarm is disabled.

timerAlarmRead

This function is used to read alarm value of the timer.

uint64_t timerAlarmRead(hw_timer_t *timer);
  • timer timer struct.

timerAlarmReadMicros

This function is used to read alarm value of the timer in microseconds.

uint64_t timerAlarmReadMicros(hw_timer_t *timer);
  • timer timer struct.

This function will return alarm value of the timer in microseconds.

timerAlarmReadSeconds

This function is used to read alarm value of the timer in seconds.

double timerAlarmReadSeconds(hw_timer_t *timer);
  • timer timer struct.

This function will return alarm value of the timer in seconds.

Example Applications

There are 2 examples uses of Timer:

Repeat timer example:

/*
 Repeat timer example

 This example shows how to use hardware timer in ESP32. The timer calls onTimer
 function every second. The timer can be stopped with button attached to PIN 0
 (IO0).

 This example code is in the public domain.
 */

// Stop button is attached to PIN 0 (IO0)
#define BTN_STOP_ALARM    0

hw_timer_t * timer = NULL;
volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

volatile uint32_t isrCounter = 0;
volatile uint32_t lastIsrAt = 0;

void ARDUINO_ISR_ATTR onTimer(){
  // Increment the counter and set the time of ISR
  portENTER_CRITICAL_ISR(&timerMux);
  isrCounter++;
  lastIsrAt = millis();
  portEXIT_CRITICAL_ISR(&timerMux);
  // Give a semaphore that we can check in the loop
  xSemaphoreGiveFromISR(timerSemaphore, NULL);
  // It is safe to use digitalRead/Write here if you want to toggle an output
}

void setup() {
  Serial.begin(115200);

  // Set BTN_STOP_ALARM to input mode
  pinMode(BTN_STOP_ALARM, INPUT);

  // Create semaphore to inform us when the timer has fired
  timerSemaphore = xSemaphoreCreateBinary();

  // Use 1st timer of 4 (counted from zero).
  // Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more
  // info).
  timer = timerBegin(0, 80, true);

  // Attach onTimer function to our timer.
  timerAttachInterrupt(timer, &onTimer, true);

  // Set alarm to call onTimer function every second (value in microseconds).
  // Repeat the alarm (third parameter)
  timerAlarmWrite(timer, 1000000, true);

  // Start an alarm
  timerAlarmEnable(timer);
}

void loop() {
  // If Timer has fired
  if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){
    uint32_t isrCount = 0, isrTime = 0;
    // Read the interrupt count and time
    portENTER_CRITICAL(&timerMux);
    isrCount = isrCounter;
    isrTime = lastIsrAt;
    portEXIT_CRITICAL(&timerMux);
    // Print it
    Serial.print("onTimer no. ");
    Serial.print(isrCount);
    Serial.print(" at ");
    Serial.print(isrTime);
    Serial.println(" ms");
  }
  // If button is pressed
  if (digitalRead(BTN_STOP_ALARM) == LOW) {
    // If timer is still running
    if (timer) {
      // Stop and free timer
      timerEnd(timer);
      timer = NULL;
    }
  }
}

Watchdog timer example:

#include "esp_system.h"

const int button = 0;         //gpio to use to trigger delay
const int wdtTimeout = 3000;  //time in ms to trigger the watchdog
hw_timer_t *timer = NULL;

void ARDUINO_ISR_ATTR resetModule() {
  ets_printf("reboot\n");
  esp_restart();
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("running setup");

  pinMode(button, INPUT_PULLUP);                    //init control pin
  timer = timerBegin(0, 80, true);                  //timer 0, div 80
  timerAttachInterrupt(timer, &resetModule, true);  //attach callback
  timerAlarmWrite(timer, wdtTimeout * 1000, false); //set time in us
  timerAlarmEnable(timer);                          //enable interrupt
}

void loop() {
  Serial.println("running main loop");

  timerWrite(timer, 0); //reset timer (feed watchdog)
  long loopTime = millis();
  //while button is pressed, delay up to 3 seconds to trigger the timer
  while (!digitalRead(button)) {
    Serial.println("button pressed");
    delay(500);
  }
  delay(1000); //simulate work
  loopTime = millis() - loopTime;
  
  Serial.print("loop time is = ");
  Serial.println(loopTime); //should be under 3000
}