/**
* 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 = 80; // clock ticks at 10 MHz now
static const uint32_t timer_frequency = 1000000; //
static const uint64_t timer_max_count = 1000000;
static const int adc_pin = A0;
// Globals
static hw_timer_t* timer = NULL;
static volatile uint16_t val;
static SemaphoreHandle_t bin_sem;
//*****************************************************************************
// 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() {
BaseType_t task_woken = pdFALSE;
// Read the data from ADC.
val = analogRead(adc_pin);
/**
* Give semaphore to tell task that the new value is available.
*
* This function will set the second parameter to pdTRUE if giving semaphore
* will caused a task to unblock, and the unblocked task has a priority higher
* than the currently running task.
*/
xSemaphoreGiveFromISR(bin_sem, &task_woken);
// Exit from ISR.
if (task_woken) {
portYIELD_FROM_ISR();
}
}
//*****************************************************************************
// Tasks
void printValues(void* parameter) {
// Loop forever.
while (1) {
// Use semaphore to protect the shared resource.
xSemaphoreTake(bin_sem, portMAX_DELAY);
Serial.println(val);
}
}
//*****************************************************************************
// 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 semaphore.
bin_sem = xSemaphoreCreateBinary();
// Check if the semaphore is created successfully.
if (bin_sem == NULL) {
Serial.println("Could not create semaphore");
ESP.restart();
}
// Create a task
xTaskCreatePinnedToCore(
printValues,
"Print Values",
1024,
NULL,
2,
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
}