Difficulty getting ESP32 S2 Timer interrupt to run.

Stellershime
Posts: 10
Joined: Thu Feb 04, 2021 8:55 pm

Difficulty getting ESP32 S2 Timer interrupt to run.

Postby Stellershime » Thu Feb 18, 2021 3:02 am

Code: Select all

/*
 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;
    }
  }
}
I've been trying to get the timer interrupt for the esp32 s2 working with the repeated timer example but it seems like that the esp32S2 is not going into the interrupts. I've tried using the ESP-IDF API with the timer_config_t struct and timer_init() function but they seemed to be undefined. Do i have to include some header files? I didn't run into this problem when I was messing with the GPIO/WDT/Sleep APIs.

Code: Select all

timer_config_t TIMER_SEL;
void setup(){
  timer_config_t TIMER_SEL;
    Serial.begin(115200);
    //timer_init(TIMER_GROUP_0,TIMER_0,TIMER_SEL);
 /* int count;
  gpio_set_direction(GPIO_NUM_11,GPIO_MODE_INPUT_OUTPUT);
 gpio_set_level(GPIO_NUM_11,HIGH);
 count=gpio_get_level(GPIO_NUM_11);
 Serial.println(count);
 gpio_set_level(GPIO_NUM_11,LOW);
 count=gpio_get_level(GPIO_NUM_11);
 Serial.println(count);
  // put your setup code here, to run once:
*/
}

void loop() {
  // put your main code here, to run repeatedly:

}

Code: Select all

GPI:1:1: error: 'timer_config_t' does not name a type; did you mean 'gpio_config_t'?
 timer_config_t TIMER_SEL;
 ^~~~~~~~~~~~~~
 gpio_config_t
C:\Users\Henry Wang\Documents\Arduino\GPI\GPI.ino: In function 'void setup()':
GPI:3:3: error: 'timer_config_t' was not declared in this scope
   timer_config_t TIMER_SEL;
   ^~~~~~~~~~~~~~
C:\Users\Henry Wang\Documents\Arduino\GPI\GPI.ino:3:3: note: suggested alternative: 'gpio_config_t'
   timer_config_t TIMER_SEL;
   ^~~~~~~~~~~~~~
   gpio_config_t
exit status 1
'timer_config_t' does not name a type; did you mean 'gpio_config_t'?
This is built using the IDF V4.2 branch of espressif/arduino-esp32.

Stellershime
Posts: 10
Joined: Thu Feb 04, 2021 8:55 pm

Re: Difficulty getting ESP32 S2 Timer interrupt to run.

Postby Stellershime » Fri Feb 19, 2021 8:08 pm

For any one interested, I've managed to create a working(?) timer interrupt example using esp-idf API for the arduino esp32 s2 using the V4.2 branch.

Do note that this is a very unprofessional work, you can use it as you like, and whatever nonsense I need to say so that nobody gets into trouble with licensing. After all just some basic code.

Code: Select all

/*First iteration of usable timer interrupt
increments a counter in the interrupt service routine and displays it on serial monitor.
Checkout esp 32 s2 programming guide on Timer and interrupt sections for more details
2/19/2021

by Henry Wang & Steven Yan
*/

#include "C:/Program Files (x86)/Arduino/hardware/expressif/esp32/tools/sdk/esp32s2/include/hal/include/hal/timer_types.h"// find this two header files in the tools/sdk/esp32s2/** directories, should be in similar places
#include "C:/Program Files (x86)/Arduino/hardware/expressif/esp32/tools/sdk/esp32s2/include/driver/include/driver/timer.h"// possibly usable just by including last two path names?
#include <stdio.h>
#include "esp_types.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/periph_ctrl.h"
#include "driver/timer.h"
#define TIMER_DIVIDER         80  //  Hardware timer clock divider
#define TIMER_SCALE           (TIMER_BASE_CLK / TIMER_DIVIDER)  // convert counter value to seconds
#define TIMER_INTERVAL0_SEC   (3.4179) // sample test interval for the first timer
#define TIMER_INTERVAL1_SEC   (5.78)   // sample test interval for the second timer
//#define TEST_WITHOUT_RELOAD   0        // testing will be done without auto reload
//#define TEST_WITH_RELOAD      1        // testing will be done with auto reload
int interrupt_counter=0;
timer_config_t config = {
  .alarm_en=TIMER_ALARM_EN,//enable timer alarm
  .counter_en=TIMER_START,//starts counting counter once timer_init called
  .intr_type=TIMER_INTR_MAX,
  .counter_dir=TIMER_COUNT_UP,//counts from 0 to counter value
  .auto_reload=TIMER_AUTORELOAD_EN,// reloads counter automatically
  .divider=TIMER_DIVIDER   
    };
    timer_idx_t timer_idx = TIMER_0;
    // if you want to use this, redefine int types to proper types, listed below in API guide. Don't use example code blindly,there is a certain level of abstraction.
    //The example code on the api guide works I think, but you would have to redefine the types on some variables. This is basic code where you can start.
    /*xQueueHandle timer_queue;
    typedef struct {
    int type;  // the type of timer's event
    int timer_group;
    int timer_idx;
    uint64_t timer_counter_value;
} timer_event_t;
*/
void IRAM_ATTR timer_group0_isr(void *para) { 
   uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0);// gets interrupt flag
   if (timer_intr & TIMER_INTR_T0) {// if interrupt status is bit 0, timer 0 interrupt triggered, TIMER_INTR_T0 defined in API at bottom
        interrupt_counter++;// how many times interrupt has occured
        timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);//clear interrupt flag for timer_group0, timer_0
        //timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE);
        //timer_group_set_alarm_value_in_isr(TIMER_GROUP_0, timer_idx, timer_counter_value);// probably dont need to set this if auto reload is enabled.
    } else if (timer_intr & TIMER_INTR_T1) {// if interrupt status is bit 1, timer 1 interrupr triggered
        timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1);
    } 
    timer_group_enable_alarm_in_isr(TIMER_GROUP_0, timer_idx);// might have to reset alarm enable everytime interrupt triggers?( to be confirmed)
  
}

void setup() {
  Serial.begin(115200);
  timer_init(TIMER_GROUP_0,TIMER_0,&config);// call init before setting counters
  timer_set_counter_value(TIMER_GROUP_0, timer_idx ,0x00000000ULL);// sets counter value to 0, counters up to alarm value because .counter_dir counts up
  timer_set_alarm_value(TIMER_GROUP_0, timer_idx, TIMER_INTERVAL0_SEC * TIMER_SCALE);// sets alarm value to 3.4~ seconds, uses macro above.
    /* Timer's counter will initially start from value below.
       Also, if auto_reload is set, this value will be automatically reload on alarm */
    /* Configure the alarm value and the interrupt on alarm. */
    
    timer_enable_intr(TIMER_GROUP_0, timer_idx);// enable interrupts for timer_group0 timer 0.
    timer_isr_register(TIMER_GROUP_0, timer_idx, timer_group0_isr,
                       (void *) timer_idx, ESP_INTR_FLAG_IRAM, NULL);// registers the isr handle.
    //timer_start(TIMER_GROUP_0, timer_idx);// if .counter_en set to timer start in timer_config_t, do not need to call this. it will start right after timer_init
    
}
void loop() {
  Serial.println(interrupt_counter);
  // put your main code here, to run repeatedly:
}

Who is online

Users browsing this forum: No registered users and 42 guests