This post will guide you common issues and mistakes that cause Fatal Exception and wdt reset. Fatal exception comes at execution time. program compiles well logically looks correct but at Running suddenly these fatal exceptions come. They are difficult to find out. But I have kept a record of few causes of these fatal exception. That I am sharing here.
First we will simulate these errors with test code and correct it.
Example 1: LED Blink Wdt Reset
LED Blink Program Giving Wdt Reset Cause Error
wdt reset load 0x4010f000, len 1384, room 16 tail 8 chksum 0x2d csum 0x2d v09f0c112 ~ld ⸮
Now we will look into program that caused wdt reset
The program is simple LED Blink but Why this wdt reset error ? can you guess….
This error is caused simply because #define LED 9. This IO 9 of ESP8266 is on bottom side these IOs cannot be used. Its My First Lesson.
Lesson 1: Make sure you are using correct IO numbers.
Example 2: External Interrupt Causing Fatal Exception(9)
The error in serial monitor.
Exception (9): epc1=0x40100f50 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000003 depc=0x00000000 ctx: sys sp: 3ffffc70 end: 3fffffb0 offset: 01a0 >>>stack>>> 3ffffe10: 40103bfc 00000017 3ffe843c 00000001 3ffffe20: 40101180 00d877c3 3ffee2c4 00000000 3ffffe30: 3ffe88f0 3ffee2c4 3ffee378 40201e95 3ffffe40: 00000000 00d3b30f 40201098 000003e8 3ffffe50: 3ffee2c4 80017004 00000001 40201ed4 3ffffe60: 0000007f 00000000 3ffee378 40201c05 3ffffe70: 40106b4c 00080000 00000000 40106b9a
Lets Look at the program that caused fatal exception(9)
Look closely to the Serial monitor You can See “You Pressed Flash Button” message that we are sending from interrupt handler.
Behavior of program:
LED Blinking works perfectly No Wdt Reset or any Fatal Exception until we send external interrupt. Right. Whats the problem then? Interrupt is called we can see message also.
Where is our second message “I am after 1 Sec” Yes you are right some thing after first serial out. i.e. delay(1000); This line causes fatal exception(9). Then Why? Logically every thing is correct then this fatal exception(9) from a delay????
Yes its bug in ESP8266 libraries. that are get used while compilation.
Lesson No. 2: Never Use Delays in External Interrupt Handler
How to Solve this Fatal Exception(9)? I want to use delay in interrupt
To solve this issue I use delayMicroseconds in interrupt handler this will not create any problem.
Modified Program with Same Functionality Without Fatal Exception(9) Error
#define InterruptButton 0 //On board Flash Button as interrupt #define LED 2 //on Board Blue LED void setup() { Serial.begin(115200); pinMode(LED,OUTPUT); pinMode(InterruptButton,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(InterruptButton),myInterruptHandler,CHANGE); } void loop() { // LED Blinking repeatedly: digitalWrite(LED,HIGH); delay(1000); digitalWrite(LED,LOW); delay(1000); } void myInterruptHandler() { Serial.println("You Pressed Flash Button"); delayMicroseconds(1000000); //Simple 1 Sec Delay Serial.println("I am after 1 Sec"); }
Example 3: ESP as Web Server and AP
This program Looks perfect. But causing No errors or Doing nothing.
After Uploading This program.
- We must see HomeServer wifi network.
- But there is no such network created by this code.
Why No WiFi Access point ?
Compilation is ok, No Errors or Exceptions in serial monitor then Why missing HotSpot?
The problem is in Analog = String(analogRead(A0));
void loop() { server.handleClient(); Analog = String(analogRead(A0)); }
By commenting Analog read line and re-uploading the program you will immediately see the HomeServer access point
/* * Copyright (c) 2015, circuits4you.com * All rights reserved. /* Create a WiFi access point and provide a web server on it. */ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> /* Set these to your desired credentials. */ const char *ssid = "HomeServer"; ESP8266WebServer server(80); String Analog; //======================================================================= // handles main page 192.168.4.1 //======================================================================= /* Just a little test message. Go to http://192.168.4.1 in a web browser * connected to this access point to see it. */ void handleRoot() { String s = "hello from esp8266!"; s = s +" ADC:" + Analog; digitalWrite(2, HIGH); server.send(200, "text/plain", s); digitalWrite(2, LOW); } //======================================================================= // Power on setup //======================================================================= void setup() { delay(1000); /* You can remove the password parameter if you want the AP to be open. */ WiFi.softAP(ssid); //AP without password Open Network IPAddress myIP = WiFi.softAPIP(); server.on("/", handleRoot); server.begin(); } //======================================================================= // Main Program Loop //======================================================================= void loop() { server.handleClient(); Analog = String(analogRead(A0)); } //=======================================================================
Lesson No.3: Give Enough Time to server.handleClient();
To solve this problem update loop() with below code
void loop() { server.handleClient(); Analog = String(analogRead(A0)); delay(1000); }
You can use analogRead in hadleRoot() subroutine also.
Example No 4: ESP8266 Trapped in Infinite Loop
This type of error occurs when there is any loop that holding the program. Such as polling of a IO line. Waiting for some event to occur. Such as Wait until Motion Detected. Motion sensor related programs.
Soft WDT reset ctx: cont sp: 3ffefeb0 end: 3fff0090 offset: 01b0 >>>stack>>> 3fff0060: 3fffdad0 00000000 3ffef060 40201ef0 3fff0070: feefeffe feefeffe feefeffe 40205584 3fff0080: feefeffe feefeffe 3ffef070 40100718 <<<stack<<< ets Jan 8 2013,rst cause:2, boot mode:(1,6) ets Jan 8 2013,rst cause:4, boot mode:(1,6)
Lesson 4: Never Use IO polling in program holding state
Secret Function yield() to get rid of many problems
The yield()
function is also implemented inside the ESP8266 libraries:
Yielding
This is one of the most critical differences between the ESP8266 and a more classical Arduino microcontroller. The ESP8266 runs a lot of utility functions in the background – keeping WiFi connected, managing the TCP/IP stack, and performing other duties. Blocking these functions from running can cause the ESP8266 to crash (fatal exceptions) and reset itself. To avoid these mysterious resets, avoid long, blocking loops in your sketch.
The amazing creators of the ESP8266 Arduino libraries also implemented a yield() function, which calls on the background functions to allow them to do their things.
How to use yield() Function?
Example 1: Causing Hang and WDT reset
while(digitalRead(Key)==HIGH); //This will hold the program until button event is occurs
To solve this issue use yield() function in this way
while(digitalRead(Key)==HIGH) { yield(); //This will prevent wdt reset }
Now Let’s See List of Exception Codes of ESP8266
EXC-CAUSE Code | Cause Name | Cause Description | Required Option | EXC-VADDR Loaded |
---|---|---|---|---|
0 | IllegalInstructionCause | Illegal instruction | Exception | No |
1 | SyscallCause | SYSCALL instruction | Exception | No |
2 | InstructionFetchErrorCause | Processor internal physical address or data error during instruction fetch | Exception | Yes |
3 | LoadStoreErrorCause | Processor internal physical address or data error during load or store | Exception | Yes |
4 | Level1InterruptCause | Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register | Interrupt | No |
5 | AllocaCause | MOVSP instruction, if caller�s registers are not in the register file | Windowed Register | No |
6 | IntegerDivideByZeroCause | QUOS, QUOU, REMS, or REMU divisor operand is zero | 32-bit Integer Divide | No |
7 | Reserved for Tensilica | |||
8 | PrivilegedCause | Attempt to execute a privileged operation when CRING ? 0 | MMU | No |
9 | LoadStoreAlignmentCause | Load or store to an unaligned address | Unaligned Exception | Yes |
10..11 | Reserved for Tensilica | |||
12 | InstrPIFDataErrorCause | PIF data error during instruction fetch | Processor Interface | Yes |
13 | LoadStorePIFDataErrorCause | Synchronous PIF data error during LoadStore access | Processor Interface | Yes |
14 | InstrPIFAddrErrorCause | PIF address error during instruction fetch | Processor Interface | Yes |
15 | LoadStorePIFAddrErrorCause | Synchronous PIF address error during LoadStore access | Processor Interface | Yes |
16 | InstTLBMissCause | Error during Instruction TLB refill | MMU | Yes |
17 | InstTLBMultiHitCause | Multiple instruction TLB entries matched | MMU | Yes |
18 | InstFetchPrivilegeCause | An instruction fetch referenced a virtual address at a ring level less than CRING | MMU | Yes |
19 | Reserved for Tensilica | |||
20 | InstFetchProhibitedCause | An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch | Region Protection or MMU | Yes |
21..23 | Reserved for Tensilica | |||
24 | LoadStoreTLBMissCause | Error during TLB refill for a load or store | MMU | Yes |
25 | LoadStoreTLBMultiHitCause | Multiple TLB entries matched for a load or store | MMU | Yes |
26 | LoadStorePrivilegeCause | A load or store referenced a virtual address at a ring level less than CRING | MMU | Yes |
27 | Reserved for Tensilica | |||
28 | LoadProhibitedCause | A load referenced a page mapped with an attribute that does not permit loads | Region Protection or MMU | Yes |
29 | StoreProhibitedCause | A store referenced a page mapped with an attribute that does not permit stores | Region Protection or MMU | Yes |
30..31 | Reserved for Tensilica | |||
32..39 | CoprocessornDisabled | Coprocessor n instruction when cpn disabled. n varies 0..7 as the cause varies 32..39 | Coprocessor | No |
40..63 | Reserved |
Infos from Xtensa Instruction Set Architecture (ISA) Reference Manual