ESP32 freertos Core 1 panics

daveyMG
Posts: 2
Joined: Wed Nov 06, 2024 7:50 am

ESP32 freertos Core 1 panics

Postby daveyMG » Wed Nov 06, 2024 8:18 am

I'm using VSCode with Arduino framework and ESP-WROOM-32 devkit.

I'm trying to create a switch debounce that uses a task to handle the debounce delay rather than servicing all of the switch bounce interrupts. After the first switch interrupt, the interrupt is disabled then a semaphore is given to a task that delays for the debounce time then reads the switch state.

The code generally works well but making small changes to the code causes core 1 panic messages. In the vDebounceSwitch task, uncommenting the Serial.print line creates continuous panics. After removing the line the code may panic a few times on the restart but then works correctly.

Similarly, commenting out the attachInterrupt line has the same effect.

So I don't know if I have a fundamental flaw in the coding or my understanding of how the tasks are being processed.

Any comments appreciated.

Code included below along with panic error display.
  1. #include <Arduino.h>
  2.  
  3. #define SWITCH_PIN 5
  4. #define DEBOUNCE_TIME 20 / portTICK_PERIOD_MS
  5.  
  6. bool switchClosed = false;
  7. volatile SemaphoreHandle_t switchSemaphore = xSemaphoreCreateBinary();
  8.  
  9. void IRAM_ATTR handleSwitchISR() {
  10.   BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  11.  
  12.   detachInterrupt(SWITCH_PIN);
  13.   xSemaphoreGiveFromISR(switchSemaphore, &xHigherPriorityTaskWoken);
  14.  
  15.   portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
  16. }
  17.  
  18. void vDebounceSwitch(void * pvParameters){
  19.   for ( ;; ) {
  20.     xSemaphoreTake(switchSemaphore, portMAX_DELAY);
  21.  
  22.     //interrupt has occurred, wait for debounce time
  23.     vTaskDelay(DEBOUNCE_TIME);
  24.  
  25.     //Serial.println("debounced");
  26.  
  27.     //check switch state, pin High is switch Open
  28.     if (digitalRead(SWITCH_PIN)){
  29.      switchClosed = false;
  30.     } else {
  31.       switchClosed = true;
  32.     }
  33.     attachInterrupt(SWITCH_PIN, handleSwitchISR, GPIO_INTR_ANYEDGE);
  34.   }
  35.   vTaskDelete( NULL );
  36. }
  37.  
  38. void vPrintSwitchStatus(void * pvParameters){
  39.  
  40.   bool prevSwitchState = false;
  41.   for ( ;; ) {
  42.     if (prevSwitchState != switchClosed){
  43.       if (switchClosed){
  44.         Serial.println("...OPEN");
  45.       } else {
  46.         Serial.println("CLOSED");
  47.       }
  48.       prevSwitchState = switchClosed;
  49.     }
  50.  
  51.     vTaskDelay(50 / portTICK_PERIOD_MS);
  52.   }
  53.   vTaskDelete( NULL );
  54. }
  55.  
  56.  
  57. void setup() {
  58.  
  59.   Serial.begin(115200);
  60.  
  61.   pinMode(SWITCH_PIN, INPUT_PULLUP);
  62.   attachInterrupt(SWITCH_PIN, handleSwitchISR, GPIO_INTR_ANYEDGE);
  63.  
  64.   xTaskCreate(vDebounceSwitch, "", 1000, NULL, 2, NULL);
  65.   xTaskCreate(vPrintSwitchStatus, "", 1000, NULL, 1 , NULL);
  66.  
  67.   Serial.println("Setup Complete");
  68.   vTaskStartScheduler();
  69.  
  70. }
  71.  
  72. void loop() {}
  73.  

Code: Select all

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4
Setup Complete
Guru Meditation Error: Core  1 panic'ed (Unhandled debug exception).
Debug exception reason: BREAK instr 
Core  1 register dump:
PC      : 0x40083ef8  PS      : 0x00020016  A0      : 0x40080306  A1      : 0x3ffb2770
A2      : 0x00000005  A3      : 0x400ecb94  A4      : 0xb33fffff  A5      : 0x3ffbdb8c  
A6      : 0x3ffb9114  A7      : 0x00000000  A8      : 0x800d3379  A9      : 0x00000000
A10     : 0x00000000  A11     : 0x00000000  A12     : 0xb33fffff  A13     : 0x00060c23  
A14     : 0x00000002  A15     : 0x00000000  SAR     : 0x00000038  EXCCAUSE: 0x00000001
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0xb33fffff  LCOUNT  : 0x00000000 

aliarifat794
Posts: 198
Joined: Sun Jun 23, 2024 6:18 pm

Re: ESP32 freertos Core 1 panics

Postby aliarifat794 » Fri Nov 08, 2024 7:09 am

You can edit your code as shown below. It increases the task stack size. It Adds slight delays before reattaching interrupts and limits the frequency of Serial.print calls and removes vTaskDelete calls which aren’t necessary here.

Code: Select all

#include <Arduino.h>

#define SWITCH_PIN 5
#define DEBOUNCE_TIME 20 / portTICK_PERIOD_MS

bool switchClosed = false;
volatile SemaphoreHandle_t switchSemaphore = xSemaphoreCreateBinary();

void IRAM_ATTR handleSwitchISR() {
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;

  detachInterrupt(SWITCH_PIN);
  xSemaphoreGiveFromISR(switchSemaphore, &xHigherPriorityTaskWoken);

  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void vDebounceSwitch(void * pvParameters) {
  for (;;) {
    xSemaphoreTake(switchSemaphore, portMAX_DELAY);

    // Interrupt has occurred, wait for debounce time
    vTaskDelay(DEBOUNCE_TIME);

    // Uncomment this line carefully. Serial prints can sometimes cause core panics in FreeRTOS.
    // Serial.println("debounced");

    // Check switch state, pin High is switch Open
    switchClosed = digitalRead(SWITCH_PIN) == LOW;
    
    // Short delay before reattaching interrupt to avoid immediate retriggering
    vTaskDelay(10 / portTICK_PERIOD_MS); 
    attachInterrupt(SWITCH_PIN, handleSwitchISR, GPIO_INTR_ANYEDGE);
  }
}

void vPrintSwitchStatus(void * pvParameters) {
  bool prevSwitchState = false;
  for (;;) {
    if (prevSwitchState != switchClosed) {
      if (switchClosed) {
        Serial.println("...OPEN");
      } else {
        Serial.println("CLOSED");
      }
      prevSwitchState = switchClosed;
    }
    vTaskDelay(50 / portTICK_PERIOD_MS);
  }
}

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

  pinMode(SWITCH_PIN, INPUT_PULLUP);
  attachInterrupt(SWITCH_PIN, handleSwitchISR, GPIO_INTR_ANYEDGE);

  // Increase stack size to avoid overflow, 2048 bytes for each task
  xTaskCreate(vDebounceSwitch, "DebounceSwitch", 2048, NULL, 2, NULL);
  xTaskCreate(vPrintSwitchStatus, "PrintSwitchStatus", 2048, NULL, 1, NULL);

  Serial.println("Setup Complete");
}

void loop() {}
If you need more information regarding accessing ESP32 dual core, you can read this: https://www.theengineeringprojects.com/ ... -core.html

daveyMG
Posts: 2
Joined: Wed Nov 06, 2024 7:50 am

Re: ESP32 freertos Core 1 panics

Postby daveyMG » Mon Nov 11, 2024 7:42 am

Thanks for your reply, I changed the code as you suggested but got a different error (TG1WDT_SYS_RESET) on restart. After some process of elimination I found that the reset would only occur with the Serial.println inserted in the Setup code. Commenting out this line resulted in correct operation, even with the print statement in the vDebounceSwitch code.

I tried adding a delay after the println in the setup but the reset would reoccur after the delay period.

Code: Select all

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4
Setup Complete
ets Jul 29 2019 12:21:46

rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4
Setup Complete
ets Jul 29 2019 12:21:46

aliarifat794
Posts: 198
Joined: Sun Jun 23, 2024 6:18 pm

Re: ESP32 freertos Core 1 panics

Postby aliarifat794 » Wed Nov 13, 2024 12:51 pm

The error TG1WDT_SYS_RESET indicates that the Task Watchdog Timer (WDT) on Timer Group 1 is resetting the system. It occurs when a task takes too long to execute.
You can remove or Reduce Serial in Critical Sections:

Code: Select all

// Remove Serial.println from the ISR or debounce task:
void IRAM_ATTR handleSwitchISR() {
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;

  detachInterrupt(SWITCH_PIN);
  xSemaphoreGiveFromISR(switchSemaphore, &xHigherPriorityTaskWoken);

  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

Who is online

Users browsing this forum: Majestic-12 [Bot] and 131 guests