Why is not my ESP32S responding to external interrupt whilst in an infinite local loop?

1. I am new to ESP32S Platform and trying to understand its interrupt structure by writing/experimenting UNO-styled interrupt sketches.

2. In the following ESP32S Interrupt Experiment, the MCU does not respond to external interrupt when the sketch contains an infinite local loop in the loop() function. Would appreciate if someone guides to the appropriate path.
Hardware Setup:


Figure-1:

Sketch:

#define IRQ18 18
volatile bool flag = false;

void IRAM_ATTR ISR18()
{
  flag = true;
}

void setup()
{
  Serial.begin(115200);
  pinMode(IRQ18, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(IRQ18), ISR18, FALLING);
}

void loop()
{
  if (flag == true)
  {
    Serial.println("Interrupt has occurred.");
    flag = false;
    noInterrupts(); //to prevent recurrent interrupt
  }

  if (digitalRead(4) == LOW)
  {
    Serial.println("Closed key detected.");
    while (true) //local infinite loop
    {
      ;

    }
  }
}

3. In my hardware setup (Fig-1), there is Btn-1 connected with DPin-4 with internal pull-up resistor to feed a status to the MCU. Also, there is Btn-2 connected at DPin-18 to inject interrupt signal to the MCU.

4. Sketch Behavior
(1) I press Btn-1, the MCU detects it and then locked into an empty infinite local loop.

while(true)
{
   ;
}

OUTPUT:

Closed key detected.

2. I press Btn-2 to inject interrupt signal, the MCU is not interrupted as this message: "Interrupt has occurred." does not appear on Serial Monitor.

3. I re-run the sketch by pressing pressing the EN-button of the ESP32S Kit. Open the Serial Monitor. Press Btn-2 to inject interrupt signal, The MCU is interrupted due to IRQ signal at DPin-18, and the MCU is also interrupted by WDT.
OUTPUT:

Interrupt has occured.
Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 

Switching off all interrupts forever on one core is bonkers.

This is just for test purpose as Btn-2 (the interrupting device) bounces and the MCU is interrupted for each bounce. Thinking to install external hardware based (using 74LS123 one-shot) debounce circuit.

I have not yet known how to disable only one local interrupt (the IRQ18) leaving the Global Interrupt Enable Bit active.

why do you need to disable the interrupt?
can't it just be ignored by the code in loop()d

interrupts aren't well suited for detecting button presses which bounce and don't require immediate processing.

if you're using the button to simulate input from some other digital or optical device, bounce won't be an issue

3 Likes

But for test purposes in the demonstration Lab, I use a jumper wire to inject an interrupt request signal and then disable the interrupt logic globally in the sketch to stop recurrent interrupt triggering. Is it ok?

That is a lame excuse for horrible code.

The ESP32 is a very different environment,
you will have to embrace that, if you intend to use it.

sort of a dilemma, trying to demonstrate code using an interrupt that requires additional code because of the source (button switch) being used.

i can understand why you want to disable the interrupt. could try detaching the interrupt, but code wouldn't typically do this. adding code to ignore a 2nd interrupt within some time of a first might be more reasonable

have you consider using a photo transistor. it won't bounce. perhaps a pair < 1inch apart and 2 interrupts measuring the speed of an object passing across them

You'll wait forever on a Serial output with interrupts disabled :frowning:
No wonder that Serial Monitor remains blank.

That's why a Varsity takes four years time to offer an undergraduate degree in Engineering.

First, your code doesn't compile because of a missing '}'.

I'd opine that the interrupt DOES occur but your print state is never reached because the code is locked in your infinite loop. Try the code below:

  1. Press and hold Button1.
  2. Momentarily press Button2.
  3. Release Button1.
  4. Report the results.
const uint8_t buttonTwoPin = 18;
const uint8_t buttonOnePin = 4;
volatile bool flag = false;

void IRAM_ATTR isr() {
  static bool processInterrupt = true;
  if (!processInterrupt) {
    return;
  }
  flag = true;
  processInterrupt = false;
}

void setup() {
  Serial.begin(115200);
  pinMode(buttonTwoPin, INPUT_PULLUP);
  pinMode(buttonOnePin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonTwoPin), isr, FALLING);
}

void loop() {
  if (flag == true)  {
    Serial.println("Interrupt has occurred.");
    flag = false;
  }

  if (digitalRead(buttonOnePin) == LOW)  {
    Serial.println("Closed key detected.");
    while (digitalRead(buttonOnePin) == LOW) {
      ;
    }
  }
}
1 Like

Certainly, it my copy/paste problem! Corrected.

Minor Update:

const uint8_t buttonTwoPin = 18;
const uint8_t buttonOnePin = 4;
volatile bool flag = false;

void IRAM_ATTR isr() {
  static bool processInterrupt = true;
  if (!processInterrupt) {
    return;
  }
  flag = true;
  processInterrupt = false;
}

void setup() {
  Serial.begin(115200);
  pinMode(buttonTwoPin, INPUT_PULLUP);
  pinMode(buttonOnePin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonTwoPin), isr, FALLING);
}

void loop() {
  if (flag == true)  {
    Serial.println("Interrupt has occurred.");
    flag = false;
  }

  if (digitalRead(buttonOnePin) == LOW)  {
    Serial.println("Button Closed");
    while (digitalRead(buttonOnePin) == LOW) {
      ;
    }
    Serial.println("Button Opened");
  }
}

Congratulation! You have detected the flaw of my program/sketch. Once the isr() function is done, the control goes back to the local loop; as a result, my print() command at the beginning of loop() function is not encountered at all. How could be that I overlooked such an obvious reasoning?

For test purposes, I can print the debug message (Interrupt has occurred) in the isr() function.

void IRAM_ATTR ISR18()
{
  Serial.println("Interrupt has occured.");
  noInterrupts(); //to prevent recurrent interrupt
}

OUTPUT:

Closed key detected.
Interrupt has occured.

So much thanks for being focused at my title.

Don't. There's no reason to. Use the code I provided.

1 Like

OUTPUT:

Button Closed
Button Opened

You have something wrong. Sketch slightly modified for pinout of my Adafruit ESP32 Huzzah:

const uint8_t buttonTwoPin = 14;
const uint8_t buttonOnePin = 12;
volatile bool flag = false;

void IRAM_ATTR isr() {
  static bool processInterrupt = true;
  if (!processInterrupt) {
    return;
  }
  flag = true;
  processInterrupt = false;
}

void setup() {
  Serial.begin(115200);
  delay(3000);
  Serial.println("Starting");
  pinMode(buttonTwoPin, INPUT_PULLUP);
  pinMode(buttonOnePin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonTwoPin), isr, FALLING);
}

void loop() {
  if (flag == true)  {
    Serial.println("Interrupt has occurred.");
    flag = false;
  }

  if (digitalRead(buttonOnePin) == LOW)  {
    Serial.println("Button Closed");
    while (digitalRead(buttonOnePin) == LOW) {
      ;
    }
    Serial.println("Button Opened");
  }
}

Output:

Starting
Button Closed
Button Opened
Interrupt has occurred.

I am using ESP32 Dev Module of IDE 1.8.19 and following these steps:

Press and hold Button1.
Momentarily press Button2.
Release Button1.
Report the results.

Is there any difference between Adafruit ESP32 Huzzah and ESP32S? I would be glad to see the picture of your ESP32 Model.

https://learn.adafruit.com/adafruit-huzzah32-esp32-feather?view=all

They are the same modules -- ESP-WROOM-32 but the signal signatures are not alike. Mine one is:


Figure-1:

Pin mapping among LX86 Processor, RF Shielded ESP-WROOM-32, and ESP32S Dev Kit is in Fig-2:


Figure-2:

Figure-3:

In the following ESP32S Interrupt Experiment, the MCU does not respond to external interrupt when the sketch contains an infinite local loop in the loop() function. What could be the reason? There are issues with WDT which may appear in later posts.

//#include "soc/rtc_wdt.h"

#define IRQ18 18
volatile bool flag = false;

void IRAM_ATTR ISR18()
{
  flag = true;
}

void setup()
{
  Serial.begin(115200);
  //rtc_wdt_protect_off();
 // rtc_wdt_disable();
  pinMode(IRQ18, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(IRQ18), ISR18, FALLING);
}

void loop()
{
  if (flag == true)
  {
    Serial.println("Interrupt has occured.");
    flag = false;
    noInterrupts(); //to prevent recurrent interrupt
  }

  if (digitalRead(4) == LOW)
  {
    Serial.println("Closed key detected.");
    while (true) //local infinite loop
    {
      ;//delay(1);//yield();
    }
  }
}