/**
* ESP32 ISR Critical Section Demo
*
* Increment global variable in ISR.
*
* Date: February 3, 2021
* Author: Shawn Hymel
* 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; //This works at 8000Mhz so 8 will provide 1 second pause
static const uint64_t timer_max_count = 1000000;
static const TickType_t task_delay = 2000 / portTICK_PERIOD_MS;
// Globals
static int totalVariables = 10;
static hw_timer_t *timer = NULL;
static volatile int isr_counter;
static int isr_counter_array1[10]={0};
static int isr_counter_array2[10]={0};
static volatile char inputString;
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
static bool flag =0;
static float average=0;
//*****************************************************************************
// Interrupt Service Routines (ISRs)
// This function executes when timer reaches max (and resets)
void IRAM_ATTR onTimer() {
// Serial.print("ISRcounter");
// Serial.print(isr_counter);
// Serial.println(isr_counter_array1[isr_counter]);
// ESP-IDF version of a critical section (in an ISR)
portENTER_CRITICAL_ISR(&spinlock);
isr_counter++;
if (flag == 0)
{
isr_counter_array1[isr_counter]=isr_counter;
}
if(flag == 1)
{
isr_counter_array2[isr_counter]=isr_counter;
}
if(isr_counter==10)
{
isr_counter=1;
flag == 0 ? memset(isr_counter_array1, 0, totalVariables*sizeof(int)) : memset(isr_counter_array2, 0, totalVariables*sizeof(int));
flag = !flag ;
}
portEXIT_CRITICAL_ISR(&spinlock);
// Vanilla FreeRTOS version of a critical section (in an ISR)
//UBaseType_t saved_int_status;
//saved_int_status = taskENTER_CRITICAL_FROM_ISR();
//isr_counter++;
//taskEXIT_CRITICAL_FROM_ISR(saved_int_status);
}
//*****************************************************************************
// Tasks
// Wait for semaphore and print out ADC value when received
void printValues(void *parameters) {
int i,store=0;
// Loop forever
while (1) {
// Serial.print("ISRcounter - ");
// Serial.print(isr_counter);
// Count down and print out counter value
while(1) {//(flag==0) {
vTaskDelay(100 / portTICK_PERIOD_MS);
Serial.print("ISRcounter");
Serial.println(isr_counter_array1[isr_counter]);
Serial.println("--------------------------------");
if(isr_counter_array2[isr_counter]==0)
{
for (i=0;i<totalVariables;i++)
{
Serial.print(isr_counter_array1[i]);
store += isr_counter_array1[i];
}
Serial.print("store");
Serial.println(store);
Serial.println("-----------------------------------");
average = (float)store / 10.0f;
// ESP-IDF version of a critical section (in a task)
portENTER_CRITICAL(&spinlock);
Serial.print(" Average");
Serial.println(average);
// inputString.pop();
portEXIT_CRITICAL(&spinlock);
}
if(isr_counter_array1[isr_counter]==0)
{
for (i=0;i<totalVariables;i++)
{
Serial.print(isr_counter_array2[i]);
store += isr_counter_array2[i];
}
Serial.print("store");
Serial.println(store);
Serial.println("-----------------------------------");
average = (float)store / (float)totalVariables;
// ESP-IDF version of a critical section (in a task)
portENTER_CRITICAL(&spinlock);
Serial.print(" Average");
Serial.println(average);
// inputString.pop();
portEXIT_CRITICAL(&spinlock);
}
// Vanilla FreeRTOS version of a critical section (in a task)
//taskENTER_CRITICAL();
//isr_counter--;
//taskEXIT_CRITICAL();
store = 0;
}
// Wait 2 seconds while ISR increments counter a few times
vTaskDelay(task_delay);
}
}
//*****************************************************************************
// Main (runs as its own task with priority 1 on core 1)
void setup() {
// Configure Serial
Serial.begin(115200);
// Wait a moment to start (so we don't miss Serial output)
vTaskDelay(1000 / portTICK_PERIOD_MS);
Serial.println();
Serial.println("---FreeRTOS ISR Critical Section Demo---");
// Start task to print out results
xTaskCreatePinnedToCore(printValues,
"Print values",
1024,
NULL,
1,
NULL,
app_cpu);
// Create and start timer (num, divider, countUp)
timer = timerBegin(0, timer_divider, true);
// Provide ISR to timer (timer, function, edge)
timerAttachInterrupt(timer, &onTimer, true);
// At what count should ISR trigger (timer, count, autoreload)
timerAlarmWrite(timer, timer_max_count, true);
// Allow ISR to trigger
timerAlarmEnable(timer);
// Delete "setup and loop" task
vTaskDelete(NULL);
}
void loop() {
// Execution should never get here
}