Hieromon / AutoConnect

An Arduino library for ESP8266/ESP32 WLAN configuration at runtime with the Web interface
https://hieromon.github.io/AutoConnect/
MIT License
900 stars 188 forks source link

abort() on ESP32CAM when trying to OTA update feature of AutoConnect. #233

Closed v-c closed 4 years ago

v-c commented 4 years ago

OTA updates from a web browser fails when using the AutoConnect library on a ESP32CAM board. The only diagnostic available is this printed in the serial monitor:

abort() was called at PC 0x4013fb01 on core 1

I believe this is the same as reported here:

https://github.com/espressif/arduino-esp32/issues/3937

Is there a way to specify which core of the ESP32 to run the part of the code that does the OTA Update?

Tost69 commented 4 years ago

Hello v-c,

ESP32 v1 is a dual-core processor. There are functions that can only be executed on one of the cores (if I remember well, e.g. deepsleep / wakeup must use core 1 and not core 0). You cannot control this with SETUP() and LOOP(), because then always core 1 will be used.

You can check the core within LOOP() with:

Serial.print("Setup: Executing on core ");
Serial.println(xPortGetCoreID());

To use core 0 explicitly, you have to use xTaskCreatePinnedToCore in SETUP():

  1. define a global task handle:

    TaskHandle_t handleAutoConnect;
  2. write your code which have to be pinned to a core (same as your coding in LOOP)

    void taskAutoConnect(void *optionalArgs)
    {
    for (;;)
    {
    // some code, e.g. AutoConnect::begin
    delay(1000);
    }
    }
  3. start the task within SETUP():

    // create task TaskAC: function = taskAutoConnect, handle = handleAutoConnect, core = 0, priority = 1, stack = 10000, parameters = NULL
    xTaskCreatePinnedToCore(taskAutoConnect, "TaskAutoConnect", 10000, NULL, 1, &handleAutoConnect, 0);

The function taskAutoConnect is bound to core = 0 and all subroutines called and all objects generated by this function now also are bound to this core. That means that you cannot have the AutoConnect portal on core 0 and a part of it (OTA update) running on core 1 (and I don't think it would be a good idea to implement task handling into this library).

(If you need the power of an ESP32 but don't need the two cores, the new ESP32 v2 may be more attractive to you :-))

Kind regards, Tom

v-c commented 4 years ago

Thanks for the detailed response, Tom. Like you say, it may not be desirable to have the OTA update to run on core 0.

That said, I'm surprised that this situation happens on the ESP32CAM but OTA Update with the AutoConnect library works on other ESP32s (v1).

I'll do some more investigation as to the cause of the problem on this specific board.

v-c commented 4 years ago

After more digging it appears that perhaps it has to do with the partition sizes and the size of the sketch that is causing a kernel panic on the ESP32CAM. Here's the debug log:

abort() was called at PC 0x4014d965 on core 1

Backtrace: 0x400913ec:0x3ffb17b0 0x4009161d:0x3ffb17d0 0x4014d965:0x3ffb17f0 0x4008a463:0x3ffb1810 0x400eb589:0x3ffb1830 0x4015b596:0x3ffb1850 0x4015b7b9:0x3ffb1870 0x400e4319:0x3ffb1890 0x400dc855:0x3ffb18b0 0x400e4cb2:0x3ffb18f0 0x400de7a5:0x3ffb1920 0x400dfb0d:0x3ffb1940 0x400d8c35:0x3ffb1a00 0x400d9da9:0x3ffb1a20 0x400de7a5:0x3ffb1a50 0x401594ad:0x3ffb1a70 0x400d5d55:0x3ffb1aa0 0x400d7011:0x3ffb1ae0 0x400d847e:0x3ffb1cf0 0x400d53ba:0x3ffb1f20 0x400db2cd:0x3ffb1f70 0x400d1f9e:0x3ffb1f90 0x400edf4d:0x3ffb1fb0 0x4008db35:0x3ffb1fd0 **#0 0x400913ec:0x3ffb17b0 in invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:707

1 0x4009161d:0x3ffb17d0 in abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:707

2 0x4014d965:0x3ffb17f0 in is_safe_write_address at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/flash_ops.c:126**

3 0x4008a463:0x3ffb1810 in spi_flash_erase_sector at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/flash_ops.c:204 (discriminator 2)

4 0x400eb589:0x3ffb1830 in EspClass::flashEraseSector(unsigned int) at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\cores\esp32/Esp.cpp:203

5 0x4015b596:0x3ffb1850 in UpdateClass::_writeBuffer() at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\libraries\Update\src/Updater.cpp:81

6 0x4015b7b9:0x3ffb1870 in UpdateClass::write(unsigned char*, unsigned int) at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\libraries\Update\src/Updater.cpp:81

7 0x400e4319:0x3ffb1890 in AutoConnectOTA::_write(unsigned char const*, unsigned int) at .pio\libdeps\esp32cam\AutoConnect_ID2678\src/AutoConnectOTA.cpp:148

8 0x400dc855:0x3ffb18b0 in AutoConnectUploadHandler::upload(String const&, HTTPUpload const&) at .pio/libdeps/esp32cam/ArduinoJson_ID64/src/ArduinoJson/Json/JsonDeserializer.hpp:282

9 0x400e4cb2:0x3ffb18f0 in void std::_Mem_fn_base<void (AutoConnectUploadHandler::)(String const&, HTTPUpload const&), true>::_M_call<AutoConnectOTA&, String const&, HTTPUpload const&>(AutoConnectOTA&, void const volatile, String const&, HTTPUpload const&) const at c:\users\v-c-dev.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:634

  (inlined by) void std::_Mem_fn_base<void (AutoConnectUploadHandler::*)(String const&, HTTPUpload const&), true>::operator()<AutoConnectOTA*&, String const&, HTTPUpload const&, void>(AutoConnectOTA*&, String const&, HTTPUpload const&) const at c:\users\v-c-dev\.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:610
  (inlined by) void std::_Bind<std::_Mem_fn<void (AutoConnectUploadHandler::*)(String const&, HTTPUpload const&)> (AutoConnectOTA*, std::_Placeholder<1>, std::_Placeholder<2>)>::__call<void, String const&, HTTPUpload const&, 0u, 1u, 2u>(std::tuple<String const&, HTTPUpload const&>&&, std::_Index_tuple<0u, 1u, 2u>) at c:\users\v-c-dev\.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1074
  (inlined by) void std::_Bind<std::_Mem_fn<void (AutoConnectUploadHandler::*)(String const&, HTTPUpload const&)> (AutoConnectOTA*, std::_Placeholder<1>, std::_Placeholder<2>)>::operator()<String const&, HTTPUpload 

const&, void>(String const&, HTTPUpload const&) at c:\users\v-c-dev.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1133 (inlined by) std::_Function_handler<void (String const&, HTTPUpload const&), std::_Bind<std::_Mem_fn<void (AutoConnectUploadHandler::)(String const&, HTTPUpload const&)> (AutoConnectOTA, std::_Placeholder<1>, std::_Placeholder<2>)> >::_M_invoke(std::_Any_data const&, String const&, HTTPUpload const&) at c:\users\v-c-dev.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1871

10 0x400de7a5:0x3ffb1920 in std::function<void (String const&, HTTPUpload const&)>::operator()(String const&, HTTPUpload const&) const at .pio/libdeps/esp32cam/ArduinoJson_ID64/src/ArduinoJson/Json/JsonDeserializer.hpp:282

11 0x400dfb0d:0x3ffb1940 in AutoConnectAux::upload(String const&, HTTPUpload const&) at .pio/libdeps/esp32cam/ArduinoJson_ID64/src/ArduinoJson/Json/JsonDeserializer.hpp:282

12 0x400d8c35:0x3ffb1a00 in AutoConnect::_handleUpload(String const&, HTTPUpload const&) at c:\users\v-c-dev.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1754

13 0x400d9da9:0x3ffb1a20 in void std::_Mem_fn_base<void (AutoConnect::)(String const&, HTTPUpload const&), true>::operator()<String const&, HTTPUpload const&, void>(AutoConnect, String const&, HTTPUpload const&) const at c:\users\v-c-dev.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1754

  (inlined by) void std::_Bind<std::_Mem_fn<void (AutoConnect::*)(String const&, HTTPUpload const&)> (AutoConnect*, std::_Placeholder<1>, std::_Placeholder<2>)>::__call<void, String const&, HTTPUpload const&, 0u, 1u, 2u>(std::tuple<String const&, HTTPUpload const&>&&, std::_Index_tuple<0u, 1u, 2u>) at c:\users\v-c-dev\.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1074
  (inlined by) void std::_Bind<std::_Mem_fn<void (AutoConnect::*)(String const&, HTTPUpload const&)> (AutoConnect*, std::_Placeholder<1>, std::_Placeholder<2>)>::operator()<String const&, HTTPUpload const&, void>(String const&, HTTPUpload const&) at c:\users\v-c-dev\.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1133
  (inlined by) std::_Function_handler<void (String const&, HTTPUpload const&), std::_Bind<std::_Mem_fn<void (AutoConnect::*)(String const&, HTTPUpload const&)> (AutoConnect*, std::_Placeholder<1>, std::_Placeholder<2>)> >::_M_invoke(std::_Any_data const&, String const&, HTTPUpload const&) at c:\users\v-c-dev\.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1871

14 0x400de7a5:0x3ffb1a50 in std::function<void (String const&, HTTPUpload const&)>::operator()(String const&, HTTPUpload const&) const at .pio/libdeps/esp32cam/ArduinoJson_ID64/src/ArduinoJson/Json/JsonDeserializer.hpp:282

15 0x401594ad:0x3ffb1a70 in PageBuilder::upload(WebServer&, String, HTTPUpload&) at .pio\libdeps\esp32cam\PageBuilder_ID2010\src/PageBuilder.cpp:289

16 0x400d5d55:0x3ffb1aa0 in WebServer::_uploadWriteByte(unsigned char) at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/Parsing.cpp:298

17 0x400d7011:0x3ffb1ae0 in WebServer::_parseForm(WiFiClient&, String, unsigned int) at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/Parsing.cpp:434

18 0x400d847e:0x3ffb1cf0 in WebServer::_parseRequest(WiFiClient&) at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/Parsing.cpp:199 (discriminator 1)

19 0x400d53ba:0x3ffb1f20 in WebServer::handleClient() at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\libraries\WebServer\src/WebServer.cpp:276

20 0x400db2cd:0x3ffb1f70 in AutoConnect::handleClient() at c:\users\v-c-dev.platformio\packages\toolchain-xtensa32\xtensa-esp32-elf\include\c++\5.2.0/functional:1754

21 0x400d1f9e:0x3ffb1f90 in loop() at src/main.cpp:53

22 0x400edf4d:0x3ffb1fb0 in loopTask(void*) at C:\users\v-c-dev.platformio\packages\framework-arduinoespressif32\cores\esp32/main.cpp:19

23 0x4008db35:0x3ffb1fd0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)

Rebooting... ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0018,len:4 load:0x3fff001c,len:1044 load:0x40078000,len:8896 load:0x40080400,len:5828 entry 0x400806ac

Any suggestions, Tom?

v-c commented 4 years ago

It turns out the problem was the memory available to the OTA. I was able to use a different partition map to get past this problem.

;# Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, app0, app, ota_0, 0x10000, 0x1E0000, app1, app, ota_1, 0x1F0000, 0x1E0000, spiffs, data, spiffs, 0x3D0000, 0x30000,

Documenting how I was able to debug this: 1) Set the options below in platformio.ini (Note the debug build, debug level, and the monitor_filter options to use the esp32_exceptions_decoder) 2) I needed to use a newer version of the espressif32 idf than the current stable version to be able to use the esp_exceptions_decoder

[env:esp32cam] platform = https://github.com/platformio/platform-espressif32.git ; espressif32 board = esp32cam board_build.partitions = esp32cam_partitions.csv framework = arduino ;board_build.partitions = customparts.csv upload_port = COM3 monitor_speed = 115200 ; upload_port = 192.168.0.109 monitor_filters = esp32_exception_decoder build_flags = -DCORE_DEBUG_LEVEL=5 -DBOARD_HAS_PSRAM=TRUE -mfix-esp32-psram-cache-issue lib_deps = AutoConnect build_type = debug

Hieromon commented 4 years ago

@v-c Thank you for reporting your valuable investigation results.

The partition definition as your solution increases OTA reserved area than the default. So, I think your diagnosis may identify the phenomenon induced by the mismatch of sketch size and reserved area for OTA.

One of the causes of this problem is that the object size of the AutoConnect library is too large, but the average user may not have many opportunities to care for it. Therefore, if they encounter this phenomenon once, it may be difficult to solve it by self-help. Should I document some guidance based on your results?

[EDIT] I added descriptions for the partition table to the documentation in v1.2.0. But its description lacks association with this phenomenon caused by insufficient OTA space.

v-c commented 4 years ago

@Hieromon -- It doesn't hurt to document this the debugging solution. When I initially ran into the problem, the abort had insufficient information for me to consider changing the partition size.