/**
* ESP32 ISR Critical Section Demo
*
* Increment global variable in ISR.
*
* Date: April 16, 2025
* Author: Mike
* License: 0BSD
*/
// Use only core 1 for demo purposes
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
// Settings
static const uint16_t timer_divider = 8; // clock ticks at 10 MHz now
static const uint32_t timer_frequency = 10000000; //
static const uint64_t timer_max_count = 1000000;
// Globals
static hw_timer_t* timer = NULL;
static volatile int isr_counter;
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
//*****************************************************************************
// Interrupt Service Routines (ISRs)
/**
* Use IRAM_ATTR qualifier to make sure the ISR resdie in the internal ram instead of
* flash so that it can be accessed faster.
*/
void IRAM_ATTR onTimer() {
// Protect critical section in an ISR.
portENTER_CRITICAL_ISR(&spinlock);
isr_counter++;
portEXIT_CRITICAL_ISR(&spinlock);
}
//*****************************************************************************
// Tasks
void printValues(void* parameter) {
// Loop forever.
while (1) {
while (isr_counter > 0) {
Serial.println(isr_counter);
// Protect critical section in a task from the ISR.
portENTER_CRITICAL(&spinlock);
isr_counter--;
portEXIT_CRITICAL(&spinlock);
}
// Wait 2 seconds while ISR increments counter a few times.
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
//*****************************************************************************
// Main (runs as its own task with priority 1 on core 1)
void setup() {
// Serial configuration.
Serial.begin(115200);
vTaskDelay(1000 / portTICK_PERIOD_MS);
Serial.println();
Serial.println("---ESP32 Timer Interrupt Demo---");
// Create a task
xTaskCreatePinnedToCore(
printValues,
"Print Values",
1024,
NULL,
1,
NULL,
app_cpu);
// Create and start timer (frequency in Hz)
timer = timerBegin(timer_frequency);
// Check if the timer configuration works.
if (timer == NULL){
Serial.println("ERROR: Timer configuration failed. ");
}
else{
Serial.println("Timer configuration is successful. ");
}
// Provide ISR to timer (timer, function)
// Attach interrupt to timer
timerAttachInterrupt(timer, &onTimer);
// Configure alarm value and autoreload of the timer. (timer, alarm_value, autoreload, reload_count)
timerAlarm(timer, timer_max_count, true, 0);
// Delete setup and loop task.
vTaskDelete(NULL);
}
void loop() {
// Do nothing
}