Skip to content

Usage of any type of interrupt leads to an exception #2477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kvv213 opened this issue Sep 3, 2016 · 16 comments
Closed

Usage of any type of interrupt leads to an exception #2477

kvv213 opened this issue Sep 3, 2016 · 16 comments

Comments

@kvv213
Copy link

kvv213 commented Sep 3, 2016

Hello EveryOne!

I spent more than a week in otder to try to eliminate a hang of my WeMos D1 R2 board with ESP8266 onboard.

If the board is connected to PC then it just hang down. When it is standalone I can see something the following:
Reset reason: Hardware Watchdog
Reset info: Fatal exception:4 flag:1 (WDT) epc1:0x40000f68 epc2:0x00000000 epc3:0x40000f68 excvaddr:0x00000000 depc:0x00000000

The 4-th expection means:
Level1InterruptCause
Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register

I use interrupt in order to cacth impulses on a pin when one of the routines is publishing information to a remote server via WiFi. The rest of time I use Bounce2.

This is how I attach interrupt

attachInterrupt(digitalPinToInterrupt(GASMeterPin), inter, FALLING); 
  noInterrupts();

This is the callback function

void ICACHE_RAM_ATTR inter(){
  if (interruptImpulse){
    garageGASMeter += GasImpulseResolution;
    interruptImpulse=false;
  }
}

Loop routine:

void loop() {
  errorLED(); // working with ERROR LED
  getImpulse(); // check and catch for the impulse
  //delay(10);
  blinker(); // call for status LED blink
  server.handleClient(); // Check Web-Server requests
  ArduinoOTA.handle(); // Check for OTA update
  TempAndHumidity(); // update Temperature, Humidity
  publisher(); // Update ThingSpeak
  WiFiLed();
}

And the publisher:

void publisher() { // uploads data to ThingSpeak
  unsigned long CurrentMillis = millis();
  if (CurrentMillis - publishTemp > publishEvery) {
    publishTemp = millis();
    if (publishIsRequired) {
      interruptImpulse=true;
      interrupts();
      LastPublishStatus = ThingSpeak.writeFields(garageChannelNumber, garageWriteAPIKey);
      interruptImpulse=false;
      noInterrupts();
    }
  }
}

It is not easy to catch the exception but it appeares :(

@kvv213
Copy link
Author

kvv213 commented Sep 3, 2016

Some fresh exception:
ets Jan 8 2013,rst cause:4, boot mode:(3,7)

wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v00000000
~ld

@me-no-dev
Copy link
Collaborator

I think you have interrupts() and noInterrupts() backwards

@kvv213
Copy link
Author

kvv213 commented Sep 3, 2016

me-no-dev, could you please explain?

I have both interrupts() and nointerrupts():

if (publishIsRequired) {
      interruptImpulse=true;
      interrupts();
      LastPublishStatus = ThingSpeak.writeFields(garageChannelNumber, garageWriteAPIKey);
      interruptImpulse=false;
      noInterrupts();
    }

I enable interrupts at the beginning of the critical code and after it....

@me-no-dev
Copy link
Collaborator

you need to disable interrupt before going into critical code, then enable them again after you are done
In the code above, all interrupts will trigger in your critical code

@kvv213
Copy link
Author

kvv213 commented Sep 3, 2016

me-no-dev, I can be wrong but the code above exactly you wrote. The critical code is:
LastPublishStatus = ThingSpeak.writeFields(garageChannelNumber, garageWriteAPIKey);
And this string is wrapped by interrupts() and nointerrupts(). The rest of the code works more or less well without any interrupts.

The mentioned string execution can take long time because it connects with an internet server. So I need to catch my impulses during this process.

@kvv213
Copy link
Author

kvv213 commented Sep 4, 2016

I've spet another two days in order to catch this hardware watchdog issue. The only thing I'm sure that the problem is not in my code. The only thing I need to do - enter the following code into my sketch:

attachInterrupt(digitalPinToInterrupt(GASMeterPin), inter, FALLING); 
interrupts();

An I receive a hardware watchdog reset after few minutes and up to 1 hour and 10 minutes. :) I don't know what to do else :)

@kvv213
Copy link
Author

kvv213 commented Sep 4, 2016

It seems that I'm very close to the solution. My opinion that the problem is not in attachInterrupt but in interrupts()/noInterrupts().
Here I've jsut found that there is some mess around prohibitiong interruptions. The thing is noe yet done and it is good not to nest some interrupts/noInterrupts into each one because there can be a problem with some counter (as I guess it should bot enable interrupts if they were disabled more than once). But this thing doesn't work.

So... I had hardware watchdogs resets when I tried to use the pair of interrupts/noInterrupts or just interrupts alone. That cased problems because one of my libs works with interrupts and it doesn't enable interrupts. Also even once usage of interrupts() in setup() leads to random wdt reset.

Now I'm testing my skets with my WeMos board without any interrupts()/noInterrupts() and it works twice more than before: two hours instead of 40 minutes or 1 hour 10 minutes.

Later I'll introduce larger test and push information here.

@kvv213
Copy link
Author

kvv213 commented Sep 5, 2016

Hello EveryOne once more!

I'm still struggle with WDT resets which appear mostly randomly and without clear understanding from my side when and why it happen. I send 2 weeks and two WeMos D1 R2 modules without any result.

Do date I'm pretty sure that the problem is not in the interrupts. There is a slightly chance that the sketch I use is not the best written. So I'll redisign it completely and see will I get rid of the WDT Reset or not.

@kvv213
Copy link
Author

kvv213 commented Sep 6, 2016

Hello EveryOne!

It seems that after two days of refactoring of my Sketch for WeMos D1 R2 it is clear what was the problem of usage of PWM for internal LED (or external).
I used standard cycle from Arduino examples, something like this:

  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }

The frequence of fading is default. The board is also connected to WiFi. I got random Hardware WatchDogs. This could happen just after restart or in time around 40 minutes.
When the module transfers data to Internet then the fade effect at the LED is topped. But it is not the reson for WDT reste. But the most probably moment for WDT is after WiFi communication.

I think this can be connected with this issue #836

@yhua537
Copy link

yhua537 commented Sep 6, 2016

what me-no-dev means
noInterrupts(); // turn off interruptImpulse=true; LastPublishStatus = ThingSpeak.writeFields(garageChannelNumber, garageWriteAPIKey); interruptImpulse=false; interrupts(); // turn back on

@devyte
Copy link
Collaborator

devyte commented Oct 13, 2017

@kvv213 your interrupt() - noInterrupt() calls look reversed. In any case, you most likely shouldn't be messing with that, unless you have time-critical code (e.g.: like the serial communication with a DHT sensor). You certainly shouldn't nest those calls, and also network communications should not be wrapped.
Closing as user error and off-topic, see #3655 .

@devyte devyte closed this as completed Oct 13, 2017
@palsbo
Copy link

palsbo commented Dec 29, 2017

Maybe a litle late! This is what I found.
This was my simple test sketch:

void handleInterrupt() {
}

void setup() {
  Serial.begin(74880);
  delay(100);
  Serial.println("Started");
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
}

void loop() {
 delay(1);
}

It failed with an exception after a few seconds!

After removing the delay(1) in loop, it works.
What is delay doing with the interrupts?
Also using Wamos D1 mini.

@devyte
Copy link
Collaborator

devyte commented Dec 29, 2017

@palsbo two things: your ISR needs the ICACHE_RAM_ATTR keyword, and it should not have an empty body. Declare a global volatile bool, set it in the ISR, check and clear it in the loop.

@kubark42
Copy link

kubark42 commented Mar 28, 2018

@palsbo two things: your ISR needs the ICACHE_RAM_ATTR keyword...

@devyte, is this still true? It seems like a really broad assertion, and the info I found googling around seems stale. However, from what I understand of the root problem, from the explanation at #2680 (comment), ICACHE_RAM_ATTR could always be required on a per-function basis.

@devyte
Copy link
Collaborator

devyte commented Mar 28, 2018

Yes. All ISRs need to be in RAM, and all functions called from the ISR must be in RAM as well.

@sketmrdi
Copy link

Arduino IDE not detecting esp8266 module.showing this error "esptool.py v2.8
Serial port COM1
Connecting.................."
please help me to hardresetting the module
Screenshot (3)
Screenshot (2)
Screenshot (1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants