me-no-dev / ESPAsyncWebServer

Async Web Server for ESP8266 and ESP32
3.7k stars 1.21k forks source link

delay() instruction generating Exception (9) error on ESP8266 / nodeMCU with ESPAsyncWebServer library #1187

Open fedekrum opened 2 years ago

fedekrum commented 2 years ago

This code generates an exception 9 error

#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

AsyncWebServer server(80);

const char* ssid = "SSID";
const char* password = "PASS";
int x=0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  Serial.print("\n");
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.printf("\nWiFi Failed!\n");
    return;
  }
  Serial.print("\nHTTP://");
  Serial.println(WiFi.localIP());

  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {

    delay(1);   // --- THIS IS THE CONFLICTING INSTRUCTION

    request->send(200, "text/plain", (String)millis()+" - "+(String)x++);
  });

  server.onNotFound(notFound);
  server.begin();
}

void loop() {
  delay(1000);
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "404 Not found");
}

if I replace delay(1) with

    for(int q=0;q<=1000000;q++){
      digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN));
    }

I get the same exception.

https://stackoverflow.com/questions/73127447/delay-instruction-generating-exception-9-error-on-esp8266-nodemcu-with-esp

Pablo2048 commented 2 years ago

Did You read this: https://github.com/me-no-dev/ESPAsyncWebServer#important-things-to-remember ?

fedekrum commented 2 years ago

That will justify the delay() for sure. Thanks But the problem still exists if you change it for the "for" loop as I suggested. Looks like the callback is time sensitive beyond the yield or the delay commands.

Pablo2048 commented 2 years ago

The problem is that the callback has to be shortest as possible - You can not hang there for too long time.

fedekrum commented 2 years ago

I wonder why? The technical explanation beyond it. May be the author can throw some light on this.

Pablo2048 commented 2 years ago

Well, the ESP8266 Arduino is built on NONOS_SDK so it does not contain any form of RTOS. Despite this there is some form of cooperative multitasking - internal task for handling WiFi and "user" task handling the Arduino code. This webserver is async so it uses AsyncTCP library which runs (read it as "its called from") in this internal task context (so the "problem" is inside AsyncTCP library and not the server). For more explanation you can read here https://github.com/me-no-dev/ESPAsyncTCP/blob/15476867dcbab906c0f1d47a7f63cdde223abeab/src/ESPAsyncTCP.cpp#L61 - I suggest you to give some time studying the AsyncTCP library to get more info.

MacDada commented 2 years ago

For more explanation you can read here https://github.com/me-no-dev/ESPAsyncTCP/blob/15476867dcbab906c0f1d47a7f63cdde223abeab/src/ESPAsyncTCP.cpp#L61

That is strange:

The client sketch must always test if the connection is still up at loop() entry and after the return of any function call, that may have done a delay() or yield()

I've read docs and examples in ESPAsyncWebServer and ESPAsyncTCP -> there is nothing about "connection checking" anywhere in the loop()s.

Pablo2048 commented 2 years ago

Simplest thing first - ask the original author for explanation ;-) ...

MacDada commented 2 years ago

Simplest thing first - ask the original author for explanation ;-) ...

well, both libs are made / maintained (?*) by @me-no-dev, so I guess I am asking in the right place ;-)


*with last update a year ago and 64 pending PRs, I'm starting to think I shouldn't spend too much time trying to understand it all…

stale[bot] commented 1 year ago

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.