Skip to content

Running out of heap (and thus crashing) during filesystem update will corrupt the filesystem #7950

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
6 tasks done
timkoers opened this issue Mar 29, 2021 · 12 comments
Closed
6 tasks done

Comments

@timkoers
Copy link

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: ESP-12
  • Core Version: 2.6.3
  • Development Env: PlatformIO
  • Operating System: Windows

Settings in IDE

  • Module: nodemcuv2
  • Flash Size: 4MB
  • CPU Frequency: 160MHz
  • Upload Using: Serial
  • Upload Speed: 921600

Problem Description

When the ESP is (almost) out of heap memory, and crashes during an update, the filesystem or files get corrupted, sometimes rendering the internal webserver useless.

How to reproduce

Upload the standard filesystem + sketch via USB.
Open the serial monitor, drag the filesystem image onto the upload button.
Before you click Upload to fs, make sure to visit ESP_IP/fill_memory a couple of times until the free heap memory reaches around 7000 bytes.
Click the upload to fs button, you might want to refresh the ESP_IP/fill_memory page one or two times during the upload, but it should also work without that.

Watch the ESP crash due to the free heap size available and after a reboot, you'll see that the LittleFS is corrupted.

Please note that the filesystem reports that index.html is 3994 bytes both before and after the update, so the filesystems file table is still intact.

Due to the OTA partition of the ESP, I don't think that this will happen during a Flash upgrade, but please feel free to test.

Sketch

#include <Arduino.h>

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

void setup() {

// Connect to wifi
WiFi.begin(SSID, PASS);
server.begin();

    // Route for root / web page
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
      request->send(LittleFS, "/index.html");
    });

    server.on("/fill_memory", HTTP_GET, [](AsyncWebServerRequest *request) {
      // Fill up the memory
      Serial.println("Filling memory");
      fillMemory = true;
      request->send(200, "Ok");
    });

    server.on(
        "/update", HTTP_POST, [](AsyncWebServerRequest *request) { request->send(200, !Update.hasError() ? "OK" : "FAIL"); },
        [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
          // TODO: Add protection agains out of memory crashes. That corrupts the filesystem, or add an emergency mode

          if (!index)
          {
            Update.runAsync(true);

            fsUpdate = request->getParam("SPIFFS") != nullptr;

            Serial.printf(fsUpdate ? "FS Update Start: %s\n" : "Update Start: %s\n", filename.c_str());

            size_t updateSize = fsUpdate ? ((size_t)&_FS_end - (size_t)&_FS_start) : ((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
            fsUpdate = request->getParam("SPIFFS") != nullptr;

            if ((updateStarted = Update.begin(updateSize, fsUpdate ? U_FS : U_FLASH), !updateStarted))
            {
              Update.printError(Serial);
            }
          }
          if (!Update.hasError())
          {
            if (Update.write(data, len) != len)
            {
              Update.printError(Serial);
            }
          }
          if (final)
          {
            if (Update.end(true))
            {
              Serial.printf("Update Success: %uB\n", index + len);
            }
            else
            {
              Update.printError(Serial);
            }
          }
        });
    server.onNotFound([](AsyncWebServerRequest *request) {
      request->send(404, "text/plain", "Not found");
    });
}

long debugMillis = 0;

void *memory;

void loop()
{
  environment.loop();

  if((millis() - debugMillis) > 1000){
    Serial.printf("Free heap: %d\n", ESP.getFreeHeap());
    debugMillis = millis();
  }

  if (fillMemory)
  {
    memory = malloc(5000);

    fillMemory = false;
  }
}

Debug Messages

TRACE HomeEnvironment.cpp:263 [74]: Opening ESP8266 SPIFFS
TRACE HomeEnvironment.cpp:82 Listing directory: /
TRACE HomeEnvironment.cpp:91 FILE: ESP-Power-Test.crt
TRACE HomeEnvironment.cpp:92   SIZE: 4440
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-02 12:04:52       
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-02 12:04:52       
TRACE HomeEnvironment.cpp:91 FILE: ESP-Power-Test.key
TRACE HomeEnvironment.cpp:92   SIZE: 1704
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-02 12:05:10
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-02 12:05:10
TRACE HomeEnvironment.cpp:91 FILE: ca.crt
TRACE HomeEnvironment.cpp:92   SIZE: 1164
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-02 12:05:04
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-02 12:05:04
TRACE HomeEnvironment.cpp:91 FILE: configuration.json
TRACE HomeEnvironment.cpp:92   SIZE: 417
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-29 09:32:41
TRACE HomeEnvironment.cpp:99   LAST WRITE: 1970-01-01 00:00:00
TRACE HomeEnvironment.cpp:91 FILE: index.html
TRACE HomeEnvironment.cpp:92   SIZE: 3994
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-29 12:46:48
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-29 12:46:48

Free heap: 12032
Free heap: 12264
Free heap: 12336
Filling memory
Free heap: 7328
Free heap: 7328
Free heap: 7000
Filling memory
Free heap: 7136
Free heap: 7136
Free heap: 7064
Filling memory
Free heap: 7064
Free heap: 6688
Free heap: 7040
Filling memory
Free heap: 7040
Free heap: 6992
Free heap: 7008
Free heap: 6680
Free heap: 6816
Free heap: 6280
Free heap: 6280
FS Update Start: littlefs.bin
Free heap: 1592
Free heap: 2048
Free heap: 2360
Free heap: 2472
Filling memory

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Exception (28):
epc1=0x4021d1b5 epc2=0x00000000 epc3=0x00000000 excvaddr=0x0000000b depc=0x00000000

LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
  epc1=0x4021d1b5 in String::String(String const&) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:303
     (inlined by) ?? at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.cpp:132
     (inlined by) String::String(String const&) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.cpp:39

>>>stack>>>

ctx: sys
sp: 3fffea10 end: 3fffffb0 offset: 0190
3fffeba0:  3ffe92e8 402100e9 00000018 4021e19c
3fffebb0:  40102a14 3fffbf54 402100d0 402100f0
3fffebc0:  3fffec98 3ffe92f8 3fffebf8 3fffebe0
3fffebd0:  3fffec98 3fffba94 402100d0 40211166  
3fffebe0:  80000000 00000003 00000003 00000059
3fffebf0:  3fffed4c 000012c9 656e6f6e 40100b00
3fffec00:  84ffbf54 3fffbfdc 000d000f 000000c8
3fffec10:  3fffbf54 00000020 3fffb4d4 40100e48
3fffec20:  00000001 3fffbf54 3fffec60 40239411
3fffec30:  00000000 3fffed2c 00000000 3fffba94
3fffec40:  3fffbd93 3fffba94 3fffbf54 4021024d
3fffec50:  3fffeca0 00000020 00000008 40100e83
3fffec60:  3fffb4d4 402100fc 00000008 4021e19c
3fffec70:  00000000 3fffbf54 3fffbfac 402100fc
3fffec80:  3fffbf70 3ffe8e60 3fffbf54 4021cc60
3fffec90:  3fffbf70 402100d0 3fffbf54 40210cbd
3fffeca0:  736f6c00 3fff0065 80000000 6e6e6f00
3fffecb0:  69746365 80006e6f 80000cda 40100b83
3fffecc0:  3fffed20 00000020 00000050 3fffba94
3fffecd0:  3fffbd93 3fffba94 3fffbf54 4020f375
3fffece0:  3fffed20 3fffed2c 3fffbf54 4020ed0a
3fffecf0:  3fffbd93 0000000e 3fffed20 3fffba94
3fffed00:  3fffbd93 00000002 3fffba94 4020f396
3fffed10:  3fffbad8 00000002 3fffba94 40205ea3
3fffed20:  3f006b4f 3ffe8d64 82ffba94 4021cc00
3fffed30:  3fffbaa4 80000002 3fffba94 4020f7d1
3fffed40:  3fffbf00 000c000f 3fffba94 40100205
3fffed50:  3fff42dc 80000000 3fffbe9c 402125b8
3fffed60:  3fff04e4 3fffbe00 000d000f 80006e6f
3fffed70:  00000000 0000005b 3fffbac8 3fffba94  
3fffed80:  3fffbd93 00000002 3fffba94 4020f974
3fffed90:  3fffb3dc 3ffeec58 4020d6ec 4021e132
3fffeda0:  3fffbd93 3fffbac8 3fffbd93 3fffba94
3fffedb0:  3fffbd93 00000002 00000001 4020fa60
3fffedc0:  3fffb3dc 0000060d 0000060d 40100b83
3fffedd0:  00000000 4bc6a7f0 26e978d4 00000000
3fffede0:  00000000 00000000 4bc6a7f0 00000000
3fffedf0:  3fffbac8 3fff4b26 401005c2 0000b826
3fffee00:  00000000 00000030 4020d548 3fffee70
3fffee10:  00000000 3fff8644 3fffbbd4 4020fc8d
3fffee20:  00028002 40212209 3fff4ef4 40100391
3fffee30:  00000000 3fff8644 3fffbbd4 402233e6
3fffee40:  3fff4aac 3fffb3c4 3fff8644 3fff1b00
3fffee50:  00000006 00000001 3fff4cb4 3fff1b00
3fffee60:  3fff4aac 3fff1ae4 3fff1ae5 40223451
3fffee70:  3fff4f0c 3fffb3c4 3fffbbd4 3fff1b00
3fffee80:  3fff4aac 3fff1ae4 3fff1ae5 4024ebb0
3fffee90:  402944ac 00000020 00000010 40100e83
3fffeea0:  3fff1d70 3108a8c0 00000014 40100e83
3fffeeb0:  00000000 00000000 00000000 3fff1e20
3fffeec0:  3fff1d70 3fffbbf2 3fffbbd4 40254892
3fffeed0:  00000014 3fff1d70 000005d3 40100b83
3fffeee0:  00000000 3fff1fc4 3ffee4f8 3fff23e4
3fffeef0:  3fffdc80 00000020 3fff4d24 3fff23e4
3fffef00:  00000008 3fff1d70 3fffbbd4 4024b1c9
3fffef10:  3fffdc80 3fff238c 3fff4d24 4024afe8
3fffef20:  402856ce 3fff238c 3fff4d24 402856df
3fffef30:  3fffbbe4 3fffbbd4 00000000 3fffdcb0
3fffef40:  4027ae07 00000000 3fff4d24 40280ec7
3fffef50:  40000f49 3fffdab0 3fffdab0 40000f49
3fffef60:  40000e19 00000005 000a08a8 00000000
3fffef70:  00000000 aa55aa55 00000053 40104e71
3fffef80:  40104e77 000a08a8 00000000 ffffffff
3fffef90:  4010000d ffffffff ffffffff ffffffff
3fffefa0:  00000000 3fffef3c 00000000 3fffff68
3fffefb0:  3fffffc0 00000000 00000000 feefeffe
3fffefc0:  feefeffe feefeffe feefeffe feefeffe
3fffefd0:  feefeffe feefeffe feefeffe feefeffe
3fffefe0:  feefeffe feefeffe feefeffe feefeffe
3fffeff0:  feefeffe feefeffe feefeffe feefeffe
3ffff000:  feefeffe feefeffe feefeffe feefeffe
3ffff010:  feefeffe feefeffe feefeffe feefeffe
3ffff020:  feefeffe feefeffe feefeffe feefeffe
3ffff030:  feefeffe feefeffe feefeffe feefeffe
3ffff040:  feefeffe feefeffe feefeffe feefeffe
3ffff050:  00000009 00000000 0000000a 00000000
3ffff060:  00000009 00000000 0000000a 00000000
3ffff070:  00000009 00000000 0000000a 00000000
3ffff080:  00000007 00000000 0000000a 00000000
3ffff090:  00000007 00000000 0000000a 00000000
3ffff0a0:  3ffff200 00000000 3ffff200 402355c2
3ffff0b0:  00000000 a0000000 00000000 0000001c
3ffff0c0:  00007000 00000000 00007000 00000000
3ffff0d0:  00000004 00000000 0000000a 00000000
3ffff0e0:  00000004 00000000 0000000a 00000000
3ffff0f0:  00000001 40103f2e 4022e9cd 00000027
3ffff100:  00000000 a0000000 00000000 0000001c
3ffff110:  00004000 3ffff6c8 00004000 00000000
3ffff120:  3ffff280 00000000 3ffff280 402355c2
3ffff130:  0000a000 3ffff223 3ffff190 4022eaf8
3ffff140:  00000027 00080000 4022e9cd 0000001f
3ffff150:  3ffff280 0000001f 3ffff280 402355c2
3ffff160:  3ffff1e0 3ffff718 3ffff190 00000000
3ffff170:  40102a14 3fffc200 00000022 402354f8
3ffff180:  3ffff280 3ffff718 3ffff1e0 4022eaf8
3ffff190:  0000001f 00000027 00000000 00000001
3ffff1a0:  3ffe8344 00000001 3ffff280 402355c2
3ffff1b0:  3ffff223 3ffe9c56 00000000 656d6974
3ffff1c0:  00000006 3ffff324 00000000 3ffe9c59
3ffff1d0:  00000000 3ffe9c58 3ffff280 402359f3
3ffff1e0:  00000000 0000001f 00000000 00000000
3ffff1f0:  0000001f 0000004f 00302073 3ffe8344
3ffff200:  00000027 00000009 00000001 65776f50
3ffff210:  0000001f 3ffff38e 00000000 3fff07d8
3ffff220:  00393634 000012ed 3ffe94ec 4022f428
3ffff230:  3ffff337 00000009 00000000 ffff0208
3ffff240:  3ffff310 3ffff300 00000010 3ffe8344
3ffff250:  0000001f 00000009 00000001 4022f428
3ffff260:  3ffff359 3fff07f8 7fffffb6 3fff0578
3ffff270:  3fff1c64 00000001 3ffe9480 4022f428
3ffff280:  3ffff37f 00000044 7fffffb0 ffff0208
3ffff290:  3ffff330 7fffffff 3ffe9358 4021b7c4
3ffff2a0:  4021b7b8 3fff07f8 3ffe9358 4021be55
3ffff2b0:  35303038 00000031 3fff07f8 4021be74
3ffff2c0:  00000002 00000000 00000002 ffffffff
3ffff2d0:  0000004f 3ffff732 3ffe9499 3fff0578
3ffff2e0:  4021b7b8 3fff07f8 3ffe9358 4021b7c4
3ffff2f0:  4021b7b8 3fff07f8 3ffe9358 4021be55
3ffff300:  3fff1c64 0000004f 3fff07f8 4021be74
3ffff310:  3fff1c64 00000001 3fff07f8 4021bec0
3ffff320:  3fff1c64 00000001 3ffe9480 4021ae79
3ffff330:  34395b1b 4152546d 5b1b4543 1b206d30
3ffff340:  6d30395b 656d6f48 69766e45 6d6e6f72
3ffff350:  2e746e65 3a707063 1b393634 206d305b
3ffff360:  3538345b 203a5d38 65657246 61656820
3ffff370:  656d2070 79726f6d 3531203a 00383030
3ffff380:  65657266 20676e69 66667562 3a737265
3ffff390:  33363120 20003434 69756854 64202c73
3ffff3a0:  62687361 6472616f 3838383a feef0034
3ffff3b0:  feefeffe feefeffe feefeffe feefeffe
3ffff3c0:  feefeffe feefeffe feefeffe feefeffe
3ffff3d0:  feefeffe feefeffe feefeffe feefeffe
3ffff3e0:  feefeffe feefeffe feefeffe feefeffe
3ffff3f0:  feefeffe feefeffe feefeffe feefeffe
3ffff400:  feefeffe feefeffe feefeffe feefeffe
3ffff410:  feefeffe feefeffe feefeffe feefeffe
3ffff420:  feefeffe feefeffe feefeffe feefeffe
3ffff430:  feefeffe feefeffe feefeffe feefeffe
3ffff440:  feefeffe feefeffe feefeffe feefeffe  
3ffff450:  feefeffe feefeffe feefeffe feefeffe
3ffff460:  feefeffe feefeffe feefeffe feefeffe
3ffff470:  feefeffe feefeffe feefeffe feefeffe
3ffff480:  feefeffe feefeffe feefeffe feefeffe
3ffff490:  feefeffe feefeffe feefeffe feefeffe
3ffff4a0:  feefeffe feefeffe feefeffe feefeffe
3ffff4b0:  00000007 00000000 0000000a 00000000
3ffff4c0:  00000007 00000000 0000000a 00000000
3ffff4d0:  feefeffe feefeffe feefeffe feefeffe
3ffff4e0:  00000000 a0000000 00000000 0000001c
3ffff4f0:  00000006 00000000 0000000a 00000000
3ffff500:  00000006 00000000 0000000a 00000000
3ffff510:  0000a000 00000000 3ffee228 000000ff
3ffff520:  0000005c 00000001 40104cb9 3ffeec58
3ffff530:  00000005 00000000 00000020 401004c8
3ffff540:  40101ee5 00000000 00000005 40101ab4
3ffff550:  3ffeaa95 40104d6b 3ffee458 402354f8
3ffff560:  4010264f 3ffee458 3ffeec58 00000039
3ffff570:  00007fff 02a5ddee 3ffeef80 40102830
3ffff580:  3ffeb328 00000000 00000000 00040000
3ffff590:  00007fff 02a5ddee 40102cf2 00000100
3ffff5a0:  3ffeb328 7fffffff 00002200 00000001
3ffff5b0:  00000001 00004288 4000050c 00000001
3ffff5c0:  3ffeb328 00000000 3ffff6a0 02a5ddee
3ffff5d0:  3ffeb34c 2c9f0300 4000050c 3fffc278
3ffff5e0:  40102a14 3fffc200 00000022 3ffe9c59
3ffff5f0:  4021f63c 00000030 00000010 ffffffff
3ffff600:  4021fbe8 0000007f 00000065 00000000
3ffff610:  60000000 0000007e 6000001c 00000000
3ffff620:  000000b0 00000014 3ffff643 64656c69
3ffff630:  0000001a 3ffff79f 00000000 00000030
3ffff640:  00373536 00e8a101 40106188 3fff093c
3ffff650:  00000001 00004e20 00000000 4022f428
3ffff660:  3ffff730 3ffff720 00000010 3ffe8344
3ffff670:  00000039 00000009 00000001 3ffff6e0
3ffff680:  3ffff6fd 00000001 3ffff970 3fff093c
3ffff690:  00000000 3fff0638 3ffe9738 4022f428
3ffff6a0:  3ffff7b9 00000000 7fffff96 ffff0208
3ffff6b0:  3ffff750 7fffffff 3ffe968e 3fff093c
3ffff6c0:  4021b7b8 3fff07f8 3ffe9358 4021b7c4
3ffff6d0:  34343230 3fff0734 3ffe9358 4021be55
3ffff6e0:  00000002 00000000 00000002 ffffffff
3ffff6f0:  00000069 3ffffb39 3ffe973a 3fff093c
3ffff700:  4021b7b8 3fff07f8 3ffe9358 4021b7c4
3ffff710:  4021b7b8 3fff07f8 3ffe9358 4021be55
3ffff720:  00000000 00000069 3fff07f8 4021be74
3ffff730:  00000000 3fff0638 3fff07f8 4021bec0
3ffff740:  00000000 3fff0638 3ffe9738 4021ae79
3ffff750:  31335b1b 5252456d 5b1b524f 1b206d30
3ffff760:  6d30395b 656d6f48 69766e45 6d6e6f72
3ffff770:  2e746e65 3a707063 1b373536 206d305b
3ffff780:  3434345b 3a5d3032 54514d20 6c432054
3ffff790:  746e6569 6f6f6c20 61662070 64656c69
3ffff7a0:  6e69202c 61697469 697a696c 6e20676e
3ffff7b0:  63207765 6e65696c 00000074 40101ab4
3ffff7c0:  3ffeaa92 4027b073 3ffee200 00000020
3ffff7d0:  00000000 4026e5eb 3ffef6b8 3fff1fc4
3ffff7e0:  00000000 00000002 00000001 3ffee200
3ffff7f0:  3fff835a 401053bb 3fff82f0 3fff18b0
3ffff800:  3fff238c 2c9f0300 4000050c 3fffc278
3ffff810:  40102a14 4024aba9 3fff82f0 3fff18b0
3ffff820:  0000000f 00000000 00000010 00000000
3ffff830:  0000000f 00000000 00000010 00000000
3ffff840:  3fff1da8 3fff1d70 3fff8314 4024ae36
3ffff850:  00000000 3fff1d70 3fff8314 4024b254
3ffff860:  3ffff890 00000000 00007800 00000000
3ffff870:  3ffff9d0 00000000 3ffff9d0 3fff8314
3ffff880:  3fff8314 3fff81e0 3fff1d70 40253145
3ffff890:  005e0001 0000fb00 4022e9cd 00000002
3ffff8a0:  3fff8368 3fff81e0 3fff1d70 40254af4
3ffff8b0:  3ffff930 3ffff971 3ffff8e0 00000000
3ffff8c0:  00000018 3ffff934 00000001 00000000
3ffff8d0:  00000002 3fff1c2c 00000004 402555fc
3ffff8e0:  00000002 00000000 3ffffa40 3fff81dc
3ffff8f0:  00000000 3fff8314 3fff8380 40254b3c
3ffff900:  3fff1d70 3ffff930 00000004 3fff81dc
3ffff910:  00000016 3fff8314 3fff8380 4025347e
3ffff920:  3fff1d70 3ffff930 00000004 4024b40d
3ffff930:  00000494 3108a8c0 ffffffff 4024b44c
3ffff940:  3fff81e0 3fff1d70 3f302078 4025354a
3ffff950:  3fff1cf8 00000ad3 00000ad3 40100b83
3ffff960:  3fff1cf8 00000020 0000000c 0000204a
3ffff970:  3fff1cf8 00000020 3fff7524 40100e48
3ffff980:  3fff1cf8 00000001 3ffffa04 40239411
3ffff990:  3ffffa60 00000001 3fff838c 40225be2
3ffff9a0:  00000005 00000000 00000020 401004c8
3ffff9b0:  00000000 00000000 00000005 40101ab4
3ffff9c0:  3ffeaa95 40104d6b 3ffee4a8 000012fa
3ffff9d0:  4010264f 3ffee4a8 40225b90 00000000
3ffff9e0:  00007fff 00a82772 3ffeef80 40102830
3ffff9f0:  3ffeb328 00000000 00000000 4022707c
3ffffa00:  00007fff 00a82772 40102cf2 00000100
3ffffa10:  3ffeb328 7fffffff 00002200 00000001
3ffffa20:  3fff840c 00000020 0000000c 40100e83
3ffffa30:  3ffeb328 40227693 0000000c 4021e19c
3ffffa40:  00000015 00000034 00000000 40227693
3ffffa50:  00000000 3fffc200 00000022 3ffffef0
3ffffa60:  3fff840c 3ffffef0 3ffffa80 40228349
3ffffa70:  3fff840c 00000000 00000000 4022852d
3ffffa80:  72615f08 6e697564 745f046f 6c057063
3ffffa90:  6c61636f 00000000 00000000 00000000
3ffffaa0:  00000000 00000000 00000000 00000000
3ffffab0:  00000000 00000000 00000000 00000000
3ffffac0:  00000005 00000000 00000020 401004c8
3ffffad0:  00000000 00000000 00000005 40101ab4
3ffffae0:  3ffeaa95 40104d6b 3ffee458 00000000
3ffffaf0:  4010264f 3ffee458 3434345b 3a5d3931
3ffffb00:  756f4320 6e20646c 2820746f 292d6572
3ffffb10:  6e6e6f63 20746365 74206f74 4d206568
3ffffb20:  20545451 76726573 40007265 00000100
3ffffb30:  3ffeb340 7fffffff 3434345b 3a5d3032
3ffffb40:  54514d20 6c432054 746e6569 6f6f6c20
3ffffb50:  61662070 64656c69 6e69202c 61697469
3ffffb60:  697a696c 6e20676e 63207765 6e65696c
3ffffb70:  40100074 3fffc200 00000022 00000000
3ffffb80:  4026ec38 00000030 4027bf6f 00000001
3ffffb90:  ffffffff 00000000 3ffeabe1 00000008
3ffffba0:  4027bfbe 3ffee188 3fff1fc4 00000001
3ffffbb0:  00000002 00000000 00000020 401004c8
3ffffbc0:  00000005 00000005 00000002 40101ab4
3ffffbd0:  3ffeaa92 4027b073 3ffee188 00000020
3ffffbe0:  00000000 4026e5eb 3ffef6b8 3fff1fc4
3ffffbf0:  00000000 00000002 00000000 3ffee188
3ffffc00:  3fff859e 401053bb 4027bf6f 00000001
3ffffc10:  ffffffff 00000000 3ffeabe1 00000008
3ffffc20:  4027bfbe 3ffee200 3fff1fc4 00000001
3ffffc30:  00000002 00000000 00000020 401004c8
3ffffc40:  00000005 00000005 00000002 40101ab4
3ffffc50:  3ffeaa92 4027b073 3ffee200 00000020
3ffffc60:  00000000 4026e5eb 3ffef6b8 3fff1fc4
3ffffc70:  00000000 00000002 00000000 3ffee200
3ffffc80:  3fff8592 401053bb 3fff82f0 3fff18b0
3ffffc90:  3fff238c 00000000 3fff1d70 40252ec4
3ffffca0:  00000002 00000000 0000000a 00000000
3ffffcb0:  00000002 00000000 0000000a 00000000
3ffffcc0:  ffffffff 00000000 3ffeabe1 00000008
3ffffcd0:  00000000 a0000000 00000000 0000001c
3ffffce0:  00002000 00000000 00002000 00000000
3ffffcf0:  3ffffe50 00000000 3ffffe50 402355c2
3ffffd00:  0000a000 3ffffdf3 00000020 401004c8
3ffffd10:  00000000 4026e5eb 4022e9cd 00000004
3ffffd20:  3ffffe50 00000004 3ffffe50 402355c2
3ffffd30:  00000005 00000000 00000020 401004c8
3ffffd40:  40103c63 00040000 00000005 40101ab4
3ffffd50:  3ffeaa95 40104d6b 3ffee4d0 4022eaf8
3ffffd60:  4010264f 3ffee4d0 00000020 401004c8
3ffffd70:  00007fff 02ce48b5 3ffeef80 40102830
3ffffd80:  3ffeb334 00000000 00000000 401004c8
3ffffd90:  00007fff 02ce48b5 40102cf2 00000100
3ffffda0:  3ffeb334 7fffffff 00002200 00000001
3ffffdb0:  00000001 00004288 00000000 3ffeec58
3ffffdc0:  3ffeb334 00000000 00000020 02ce48b5
3ffffdd0:  00000005 00000000 00000020 401004c8
3ffffde0:  40102a14 3fffc200 00000005 40101ab4
3ffffdf0:  3ffeaa95 40104d6b 3ffee480 ffffffff
3ffffe00:  4010264f 3ffee480 00000000 00418937
3ffffe10:  00007fff 02cf2abb 3ffeef80 40102830
3ffffe20:  3ffeb334 00000000 00000000 02ce495b
3ffffe30:  00007fff 02cf2abb 40102cf2 00000100
3ffffe40:  3ffeb334 7fffffff 00002200 00000001
3ffffe50:  00000001 00004a88 00000000 02ce2dc1
3ffffe60:  3ffeb334 2c9f0300 4000050c 02cf2abb
3ffffe70:  3ffeb310 2c9f0300 4000050c 3fffc278
3ffffe80:  40102a14 3fffc200 00000022 ffffffff
3ffffe90:  402168b4 00000030 00000010 ffffffff
3ffffea0:  4021689a 00000a97 00000000 00001388
3ffffeb0:  00000000 4bc6a7f0 810624dd 00000000
3ffffec0:  00000000 00000000 4bc6a7f0 00000000
3ffffed0:  3fff0638 3fffdad0 401005c2 0000b81b
3ffffee0:  00000000 00000010 3fffff00 4021b7c4
3ffffef0:  00d4dfcd 3fffc6fc 0000005c 4021bcd4
3fffff00:  65657246 61656820 32203a70 00000001
3fffff10:  00000001 00000000 3fff840c 40224ed8
3fffff20:  00000001 4bc6a7f0 00000000 00000000
3fffff30:  00000000 4bc6a7f0 81cac083 00000000
3fffff40:  00000000 00000000 4bc6a7f0 00000000
3fffff50:  00f42400 c11ed380 40100500 0000b81b
3fffff60:  00f42400 c11ed348 3fff1c00 40223fc6
3fffff70:  00000000 4020a88c 3fff74d4 40222a4a
3fffff80:  00000000 00000000 00000001 401004c8
3fffff90:  3fffdad0 00000000 3ffe8624 401004e9
3fffffa0:  feefeffe feefeffe 3ffe8624 4021e4cc
<<<stack<<<

0x402100e9 in AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:123
0x4021e19c in operator new(unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/abi.cpp:39
0x40102a14 in wDev_ProcessFiq at ??:?
0x402100d0 in AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:122
0x402100f0 in AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/ESPAsyncWebServer.h:105
 (inlined by) AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:123
0x402100d0 in AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:122
0x40211166 in AsyncWebServerResponse::_assembleHead(unsigned char) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:128
0x40100b00 in umm_assimilate_down at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:243
0x40100e48 in free at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:398
0x40239411 in operator delete(void*) at /workdir/repo/gcc/libstdc++-v3/libsupc++/del_op.cc:48
0x4021024d in AsyncBasicResponse::_respond(AsyncWebServerRequest*) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:300
 (inlined by) ?? at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:308
 (inlined by) ?? at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:79
 (inlined by) AsyncBasicResponse::_respond(AsyncWebServerRequest*) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:184
0x40100e83 in malloc at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:552
0x402100fc in AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/StringArray.h:32
 (inlined by) ?? at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/StringArray.h:67
 (inlined by) AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:123
0x4021e19c in operator new(unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/abi.cpp:39
0x402100fc in AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/StringArray.h:32
 (inlined by) ?? at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/StringArray.h:67
 (inlined by) AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:123
0x4021cc60 in String::~String() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.cpp:125
0x402100d0 in AsyncWebServerResponse::addHeader(String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:122
0x40210cbd in AsyncBasicResponse::AsyncBasicResponse(int, String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebResponses.cpp:179
0x40100b83 in umm_free_core at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:351
0x4020f375 in AsyncWebServerRequest::send(AsyncWebServerResponse*) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebRequest.cpp:728
0x4020ed0a in AsyncWebServerRequest::beginResponse(int, String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebRequest.cpp:732
0x4020f396 in AsyncWebServerRequest::send(int, String const&, String const&) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebRequest.cpp:774
0x40205ea3 in operator() at src/ESP-Power-Test.cpp:101
 (inlined by) _M_invoke at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:2071
0x4021cc00 in String::invalidate() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:309
 (inlined by) String::invalidate() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.cpp:138
0x4020f7d1 in AsyncWebServerRequest::_removeNotInterestingHeaders() at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebRequest.cpp:182
0x40100205 in std::function<void (AsyncWebServerRequest*)>::operator()(AsyncWebServerRequest*) const at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:2465
0x402125b8 in AsyncCallbackWebHandler::handleRequest(AsyncWebServerRequest*) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebHandlerImpl.h:118
0x4020f974 in AsyncWebServerRequest::_parseLine() at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebRequest.cpp:582 (discriminator 1)
0x4020d6ec in std::_Function_base::_Base_manager<AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(void*, AsyncClient*)#9}>::_M_manager(std::_Any_data&, std::_Function_base::_Base_manager<AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(void*, AsyncClient*)#9}> const&, std::_Manager_operation) at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:1931
0x4021e132 in String::trim() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:300
 (inlined by) ?? at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:309
 (inlined by) String::trim() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.cpp:828
0x4020fa60 in AsyncWebServerRequest::_onData(void*, unsigned int) at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebRequest.cpp:124
0x40100b83 in umm_free_core at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:351
0x401005c2 in millis at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_wiring.cpp:188 (discriminator 3)
0x4020d548 in std::_Function_base::_Base_manager<AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(AsyncWebParameter*)#2}>::_M_manager(std::_Any_data&, std::_Function_base::_Base_manager<AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(AsyncWebParameter*)#2}> const&, std::_Manager_operation) at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:1931
0x4020fc8d in std::_Function_handler<void (void*, AsyncClient*, void*, unsigned int), AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(void*, AsyncClient*, void*, unsigned int)#8}>::_M_invoke(std::_Any_data const&, void*, AsyncClient*, void*, unsigned int) at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:2073
0x40212209 in operator() at .pio\libdeps\nodemcuv2\ESP Async WebServer\src/WebServer.cpp:45
 (inlined by) _M_invoke at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:2071
0x40100391 in std::function<void (void*, AsyncClient*, void*, unsigned int)>::operator()(void*, AsyncClient*, void*, unsigned int) const at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:2465
0x402233e6 in AsyncClient::_recv(std::shared_ptr<ACErrorTracker>&, tcp_pcb*, pbuf*, long) at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2\bits/shared_ptr_base.h:915
 (inlined by) AsyncClient::_recv(std::shared_ptr<ACErrorTracker>&, tcp_pcb*, pbuf*, long) at .pio\libdeps\nodemcuv2\ESPAsyncTCP\src/ESPAsyncTCP.cpp:649
0x40223451 in AsyncClient::_s_recv(void*, tcp_pcb*, pbuf*, long) at .pio\libdeps\nodemcuv2\ESPAsyncTCP\src/ESPAsyncTCP.cpp:738
0x4024ebb0 in tcp_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/tcp_in.c:501 (discriminator 1)
0x402944ac in node_remove_from_list at ??:?
0x40100e83 in malloc at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:552
0x40100e83 in malloc at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:552
0x40254892 in ip4_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/ip4.c:1467
0x40100b83 in umm_free_core at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:351
0x4024b1c9 in ethernet_input_LWIP2 at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/netif/ethernet.c:188
0x4024afe8 in esp2glue_ethernet_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-lwip/lwip-git.c:469
0x402856ce in ethernet_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-esp/lwip-esp.c:365
0x402856df in ethernet_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-esp/lwip-esp.c:373
0x4027ae07 in ppPeocessRxPktHdr at ??:?
0x40280ec7 in ets_snprintf at ??:?
0x40104e71 in call_user_start_local at ??:?
0x40104e77 in call_user_start_local at ??:?
0x4010000d in call_user_start at ??:?
0x402355c2 in __ssputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:233
0x40103f2e in lmacRecycleMPDU at ??:?
0x4022e9cd in _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c:194 (discriminator 1)
0x402355c2 in __ssputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:233
0x4022eaf8 in _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c:246
0x4022e9cd in _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c:194 (discriminator 1)
0x402355c2 in __ssputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:233
0x40102a14 in wDev_ProcessFiq at ??:?
0x402354f8 in __ssputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:180
0x4022eaf8 in _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c:246
0x402355c2 in __ssputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:233
0x402359f3 in _svfprintf_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:667
0x4022f428 in sprintf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/sprintf.c:646
0x4022f428 in sprintf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/sprintf.c:646
0x4022f428 in sprintf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/sprintf.c:646
0x4021b7c4 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:165
0x4021b7b8 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:162
0x4021be55 in Print::print(char const*) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:130
0x4021be74 in Print::println() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:186
0x4021b7b8 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:162
0x4021b7c4 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:165
0x4021b7b8 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:162
0x4021be55 in Print::print(char const*) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:130
0x4021be74 in Print::println() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:186
0x4021bec0 in Print::println(char const*) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:198
0x4021ae79 in log_log(int, char const*, int, char const*, ...) at .pio\libdeps\nodemcuv2\HomeEnvironment\src/logs.cpp:95
0x40104cb9 in lmacTxFrame at ??:?
0x401004c8 in ets_post at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:177
0x40101ee5 in rcUpdateTxDone at ??:?
0x40101ab4 in pp_post at ??:?
0x40104d6b in lmacRxDone at ??:?
0x402354f8 in __ssputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:180
0x4010264f in rcReachRetryLimit at ??:?
0x40102830 in rcReachRetryLimit at ??:?
0x40102cf2 in wDev_ProcessFiq at ??:?
0x40102a14 in wDev_ProcessFiq at ??:?
0x4021f63c in uart_do_write_char at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/uart.cpp:463 (discriminator 1)
 (inlined by) uart_tx_fifo_full at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/uart.cpp:469 (discriminator 1)
 (inlined by) uart_do_write_char at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/uart.cpp:476 (discriminator 1)
0x4021fbe8 in uart_write at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/uart.cpp:508
0x40106188 in spi_flash_write at ??:?
0x4022f428 in sprintf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/sprintf.c:646
0x4022f428 in sprintf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/sprintf.c:646
0x4021b7b8 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:162
0x4021b7c4 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:165
0x4021be55 in Print::print(char const*) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:130
0x4021b7b8 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:162
0x4021b7c4 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:165
0x4021b7b8 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:162
0x4021be55 in Print::print(char const*) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:130
0x4021be74 in Print::println() at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:186
0x4021bec0 in Print::println(char const*) at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:198
0x4021ae79 in log_log(int, char const*, int, char const*, ...) at .pio\libdeps\nodemcuv2\HomeEnvironment\src/logs.cpp:95
0x40101ab4 in pp_post at ??:?
0x4027b073 in ppTxPkt at ??:?
0x4026e5eb in ieee80211_output_pbuf at ??:?
0x401053bb in wdt_feed at ??:?
0x40102a14 in wDev_ProcessFiq at ??:?
0x4024aba9 in glue2esp_linkoutput at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-esp/lwip-esp.c:301
0x4024ae36 in new_linkoutput at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-lwip/lwip-git.c:260
0x4024b254 in ethernet_output at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/netif/ethernet.c:312
0x40253145 in etharp_output_LWIP2 at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/etharp.c:896
0x4022e9cd in _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c:194 (discriminator 1)
0x40254af4 in ip4_output_if_opt_src at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/ip4.c:1764
0x402555fc in mem_malloc at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/mem.c:210
0x40254b3c in ip4_output_if_opt at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/ip4.c:1577
0x4025347e in igmp_send at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/igmp.c:802
0x4024b40d in do_memp_malloc_pool at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/memp.c:255
0x4024b44c in memp_malloc at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/memp.c:356
0x4025354a in igmp_lookup_group at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/igmp.c:258
0x40100b83 in umm_free_core at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:351
0x40100e48 in free at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:398
0x40239411 in operator delete(void*) at /workdir/repo/gcc/libstdc++-v3/libsupc++/del_op.cc:48
0x40225be2 in std::_Function_base::_Base_manager<std::_Bind<std::_Mem_fn<bool (esp8266::MDNSImplementation::MDNSResponder::*)()> (esp8266::MDNSImplementation::MDNSResponder*)> >::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\tim\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\4.8.2/functional:1954
0x401004c8 in ets_post at C:\Users\Tim\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:177
0x40101ab4 in pp_post at ??:?
0x40104d6b in lmacRxDone at ??:?


last failed alloc call: 402100E9(24)

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

 ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld
TRACE HomeEnvironment.cpp:263 [67]: Opening ESP8266 SPIFFS
TRACE HomeEnvironment.cpp:82 Listing directory: /
TRACE HomeEnvironment.cpp:91 FILE: ESP-Power-Test.crt
TRACE HomeEnvironment.cpp:92   SIZE: 4440
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-02 12:04:52
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-02 12:04:52
TRACE HomeEnvironment.cpp:91 FILE: ESP-Power-Test.key
TRACE HomeEnvironment.cpp:92   SIZE: 1704
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-02 12:05:10
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-02 12:05:10
TRACE HomeEnvironment.cpp:91 FILE: ca.crt
TRACE HomeEnvironment.cpp:92   SIZE: 1164
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-02 12:05:04
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-02 12:05:04
TRACE HomeEnvironment.cpp:91 FILE: configuration.json
TRACE HomeEnvironment.cpp:92   SIZE: 417
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-29 09:32:41
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-29 09:32:41
TRACE HomeEnvironment.cpp:91 FILE: index.html
TRACE HomeEnvironment.cpp:92   SIZE: 3994
TRACE HomeEnvironment.cpp:97     CREATION: 2021-03-29 12:46:48
TRACE HomeEnvironment.cpp:99   LAST WRITE: 2021-03-29 12:46:48

The original index.html file:

<!DOCTYPE HTML>
<html lang="en">
<!-- Rui Santos - Complete project details at https://RandomNerdTutorials.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. -->

<head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1">
    <title>Test</title>
    <style>
        body {
            min-width: 310px;
            max-width: 100%;
            height: 400px;
            margin: 2% 2%;
        }

        h2 {
            font-family: Arial;
            font-size: 2.5rem;
            text-align: center;
            width: max-content;
            margin: 0 33%;
        }

        h3 {
            font-family: Arial;
            font-size: 1.8rem;
            text-align: left;
            width: max-content;
        }

        .button {
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 15px 15px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 16px;
            margin: 4px 2px;
            cursor: pointer;
        }

        #container {
            width: 100%;
        }

        #overlay {
            position: fixed;
            /* Sit on top of the page content */
            display: none;
            /* Hidden by default */
            width: 100%;
            /* Full width (cover the whole page) */
            height: 100%;
            /* Full height (cover the whole page) */
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(0, 0, 0, 0.5);
            /* Black background with opacity */
            z-index: 2;
            /* Specify a stack order in case you're using a different order for other elements */
            cursor: pointer;
            /* Add a pointer on hover */
        }

        #overlay_text {
            position: absolute;
            top: 50%;
            left: 50%;
            font-size: 50px;
            color: white;
            font-family: Arial;
            transform: translate(-50%, -50%);
            -ms-transform: translate(-50%, -50%);
        }
    </style>
</head>

<body>
    <div id="overlay">
        <div id="overlay_text">Updating..</div>
    </div>

    <h3>Firmware update</h3>

    <form id="upload_ota" method="post" enctype="multipart/form-data">
        <input type="file" name="name" id="file">
        <!--<input class="button" type="submit" value="Upload">-->
    </form>
    <br>
    <div style="display:inline-block">
        <button class="button" onclick="upload_ota('')" style="float:left; margin-right:5px;">Upload</button>
        <button class="button" onclick="upload_ota('SPIFFS')" style="float:right; margin-left:5px;">Upload to
            FS</button>
    </div>
</body>
<script>    
    function upload_ota(type) {
        var typeArgument = type != "" ? "?SPIFFS" : "";

        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
            //if (this.readyState == 4 && this.status == 200) {
            //    // TODO: Check how many bytes have been transmitted and calculate the progress based on that
            //    // State object.
            //    var data = JSON.parse(this.responseText);
            //    ota_finished();
            //} else {
            //    document.getElementById("overlay").style.display = "none";
            //}
        };
        xhttp.open("POST", `/update${typeArgument}`, true);
        xhttp.send(new FormData(document.getElementById("upload_ota")));
        document.getElementById("overlay").style.display = "block";
    }
</script>

</html>

This is the resulting html file due to the corruption:

<!-- Rui Santos - Complete project details at https://RandomNerdTutorials.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. --><head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1">
    <title>Test</title>
    <style>
        body {
            min-width: 310px;
            max-width: 100%;
            height: 400px;
            margin: 2% 2%;
        }

        h2 {
            font-family: Arial;
            font-size: 2.5rem;
            text-align: center;
            width: max-content;
            margin: 0 33%;
        }

        h3 {
            font-family: Arial;
            font-size: 1.8rem;
            text-align: left;
            width: max-content;
        }

        .button {
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 15px 15px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 16px;
            margin: 4px 2px;
            cursor: pointer;
        }

        #container {
            width: 100%;
        }

        #overlay {
            position: fixed;
            /* Sit on top of the page content */
            display: none;
            /* Hidden by default */
            width: 100%;
            /* Full width (cover the whole page) */
            height: 100%;
            /* Full height (cover the whole page) */
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(0, 0, 0, 0.5);
            /* Black background with opacity */
            z-index: 2;
            /* Specify a stack order in case you're using a different order for other elements */
            cursor: pointer;
            /* Add a pointer on hover */
        }

        #overlay_text {
            position: absolute;
            top: 50%;
            left: 50%;
            font-size: 50px;
            color: white;
            font-family: Arial;
            transform: translate(-50%, -50%);
            -ms-transform: translate(-50%, -50%);
        }
    </style>
</head>

<body>
    <div id="overlay">
        <div id="overlay_text">Updating..</div>
    </div>

    <h3>Firmware update</h3>

    <form id="upload_ota" method="post" enctype="multipart/form-data">
        <input type="file" name="name" id="file">
        <!--<input class="button" type="submit" value="Upload">-->
    </form>
    <br>
    <div style="display:inline-block">
        <button class="button" onclick="upload_ota('')" style="float:left; margin-right:5px;">Upload</button>
        <button class="button" onclick="upload_ota('SPIFFS')" style="float:right; margin-left:5px;">Upload to
            FS</button>
    </div>

<script>    
    function upload_ota(type) {
        var typeArgument = type != "" ? "?SPIFFS" : "";

        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function () {
            //if (this.readyState == 4 && this.status == 200) {
            //    // TODO: Check how many bytes have been transmitted and calculate the progress based on that
            //    // State object.
            //    var data = JSON.parse(this.responseText);
            //    ota_finished();
            //} else {
            //    document.getElementById("overlay").style.display = "none";
            //}
        };
        xhttp.open("POST", `/update${typeArgument}`, true);
        xhttp.se����������������������������������������������������������������������������������������������������������������������������������������������������������</script></body>
@earlephilhower
Copy link
Collaborator

Closing as this is expected behavior. It overwrites the FS directly since in may cases the FS is way larger than the standard OTA space.

Use the ATOMIC_FS_UPDATE define in the OTA to make it use the OTA space, but then your largest FS will only be the size of the OTA space.

@timkoers
Copy link
Author

@earlephilhower The ESP continues to function with 2000 bytes of free memory, until the update starts and is almost completed. I agree that this is the expected behaviour, but a check if there is enough free heap memory to even process the update is a must in my opinion.

@Pablo2048
Copy link

I don't think so - you can always check the heap space before doing the update in your code, but according to your log it seems like you "eat the memory" when the update was in progress, so it's practically impossible to avoid this crash...

@timkoers
Copy link
Author

@Pablo2048 Nope, the crash also occured on a system where I did not eat memory and the memory is only been eaten once. Running the Updater asynchronously creates the scenario that heap usage could be changed during the update. This is something that the library should account for as it can potentially brick (end user) devices

@Pablo2048
Copy link

Pablo2048 commented Mar 29, 2021

So ok, lets say that we have the following scenario - the update is running, half of the filesystem is already overwritten (on the fly) and now the heap disappeared - we just not have enough memory. What do you think has to be done? The filesystem is already corrupted (half overwriten). The only way I can see is by using @earlephilhower suggestion - ATOMIC_FS_UPDATE - when download can not be finished, filesystem cannot be overwriten. Unfortunately the maximum size of the filesystem is the free OTA area, so if you have 2M/2M you are out of luck.

@Pablo2048
Copy link

Ehm, and the crash you have posted seems to be in the AsyncWebServer - he is unable to allocate some strings when he tries to add some headers...

@earlephilhower
Copy link
Collaborator

It's impossible to guarantee no memory overflow while doing OTA. There's a lot going on in the system with Wifi, external IP connections (as shown in your crash), etc. So that is why if you really care you use the ATOMIC option.

Also, you can use gzip to compress your filesystem w/ATOMIC (not with live update). So the compressed filesystem needs to fit in the OTA area but can decompress to a much larger one (i.e. an empty LittleFS 3MB FS is <100KB compressed IIRC).

@timkoers
Copy link
Author

So ok, lets say that we have the following scenario - the update is running, half of the filesystem is already overwritten (on the fly) and now the heap disappeared - we just not have enough memory. What do you think has to be done? The filesystem is already corrupted (half overwriten). The only way I can see is by using @earlephilhower suggestion - ATOMIC_FS_UPDATE - when download can not be finished, filesystem cannot be overwriten. Unfortunately the maximum size of the filesystem is the free OTA area, so if you have 2M/2M you are out of luck.

Yeah I got you, sorry, misunderstood your last post.

It's impossible to guarantee no memory overflow while doing OTA. There's a lot going on in the system with Wifi, external IP connections (as shown in your crash), etc. So that is why if you really care you use the ATOMIC option.

Also, you can use gzip to compress your filesystem w/ATOMIC (not with live update). So the compressed filesystem needs to fit in the OTA area but can decompress to a much larger one (i.e. an empty LittleFS 3MB FS is <100KB compressed IIRC).

Is the atomic behaviour guaranteed when using decompression, so that nothing will be changed if the ESP crashes when decompressing?

@earlephilhower
Copy link
Collaborator

ATOMIC uses the same stuff as the program OTA and runs right at bootup before any app code is run. So it's guaranteed to be atomic except in the case of power failure. That's one niggle that's left, and it applies to FS and app.

@devyte
Copy link
Collaborator

devyte commented Mar 30, 2021

To clarify:
When the FS is being updated with atomic, the eboot sector isn't touched. If power fails during decompression, I think that on next boot up the decompression should just restart, so for this case you can't end up with a corrupted system.
For app update with atomic, if the eboot sector changed in the firmware (which is super rare) AND you get a power failure before the 4KB eboot sector is finished updating, then you get a bricked device. The chance of that happening is very very low. But yes, it's a niggle that is still pending, i. e. @davisonja's #6538.

@timkoers
Copy link
Author

So ok, lets say that we have the following scenario - the update is running, half of the filesystem is already overwritten (on the fly) and now the heap disappeared - we just not have enough memory. What do you think has to be done? The filesystem is already corrupted (half overwriten). The only way I can see is by using @earlephilhower suggestion - ATOMIC_FS_UPDATE - when download can not be finished, filesystem cannot be overwriten. Unfortunately the maximum size of the filesystem is the free OTA area, so if you have 2M/2M you are out of luck.

Yeah I got you, sorry, misunderstood your last post.

It's impossible to guarantee no memory overflow while doing OTA. There's a lot going on in the system with Wifi, external IP connections (as shown in your crash), etc. So that is why if you really care you use the ATOMIC option.

Also, you can use gzip to compress your filesystem w/ATOMIC (not with live update). So the compressed filesystem needs to fit in the OTA area but can decompress to a much larger one (i.e. an empty LittleFS 3MB FS is <100KB compressed IIRC).

Is the atomic behaviour guaranteed when using decompression, so that nothing will be changed if the ESP crashes when decompressing?

So ok, lets say that we have the following scenario - the update is running, half of the filesystem is already overwritten (on the fly) and now the heap disappeared - we just not have enough memory. What do you think has to be done? The filesystem is already corrupted (half overwriten). The only way I can see is by using @earlephilhower suggestion - ATOMIC_FS_UPDATE - when download can not be finished, filesystem cannot be overwriten. Unfortunately the maximum size of the filesystem is the free OTA area, so if you have 2M/2M you are out of luck.

Would it be an idea to add something to LittleFS/Updater that checks if the update was interrupted due to a crash or something?
Store a flag in the RTC memory for example?

@Pablo2048
Copy link

Pablo2048 commented Mar 30, 2021

Would it be an idea to add something to LittleFS/Updater that checks if the update was interrupted due to a crash or something?
Store a flag in the RTC memory for example?

This can be done in your application code - I'm strongly against using the RTC area internally by some library without some sort of central management. For example I'm using portion of RTC area for counting unexpected crashes and forcing emergency mode when the application crashes too often to avoid bricking the device. So yes - you can use the RTC memory to mark unsuccessful update, but it wont survive power failure (EEPROM would be better?).

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

4 participants