From 67030b41f1ae5afccf9246421ea044f921ff68d9 Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 23 Dec 2025 21:14:21 +0100 Subject: [PATCH 01/13] Add serial command to enter flash mode --- src/serial/serialcommands.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/serial/serialcommands.cpp b/src/serial/serialcommands.cpp index 08f9f7f62..cc7a92276 100644 --- a/src/serial/serialcommands.cpp +++ b/src/serial/serialcommands.cpp @@ -158,6 +158,14 @@ void cmdSet(CmdParser* parser) { wifiNetwork.setWiFiCredentials(ssid, ppass); logger.info("CMD SET BWIFI OK: New wifi credentials set, reconnecting"); } + } else if (parser->equalCmdParam(1, "FLASHMODE")) { +#if defined(ESP8266) + logger.info("Entering flash mode..."); + delay(1000); + ESP.rebootIntoUartDownloadMode(); +#else + logger.info("Flash mode not supported on this platform!"); +#endif } else { logger.error("CMD SET ERROR: Unrecognized variable to set"); } From bd87ff8bdb6e3d46401a03d6ade7f4fb58c343d3 Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Sun, 11 Jan 2026 15:42:30 +0100 Subject: [PATCH 02/13] reboot counter for esp8266 failback to flashmode --- src/init.h | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 12 +++++++- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 src/init.h diff --git a/src/init.h b/src/init.h new file mode 100644 index 000000000..7b7c86290 --- /dev/null +++ b/src/init.h @@ -0,0 +1,82 @@ +/* + SlimeVR Code is placed under the MIT license + Copyright (c) 2021 Eiren Rain & SlimeVR contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include +#ifdef ESP8266 +#include // Include this to define rst_info + + +typedef struct rtc_mem { + uint32_t version; // RTC memory version + uint32_t rebootCount; // Number of reboots +} rtc_mem_t; + +// Constructor function that runs during static initialization (before setup) +__attribute__((constructor)) +void checkrebootcount(){ + Serial.begin(115200); + struct rst_info *resetreason; + rtc_mem_t rtcMem; + resetreason = ESP.getResetInfoPtr(); + Serial.println("Reset reason code: " + String(resetreason->reason)); + // Offset 33 to avoid eboot command area + ESP.rtcUserMemoryRead(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); + Serial.println("RTC Memory Version: " + String(rtcMem.version)); + Serial.println("RTC Memory Reboot Count: " + String(rtcMem.rebootCount)); + if (rtcMem.version != 0x01) { + // First boot, initialize RTC memory + rtcMem.version = 0x01; + rtcMem.rebootCount = 0; + } + if (resetreason->reason != REASON_SOFT_WDT_RST && + resetreason->reason != REASON_EXCEPTION_RST && + resetreason->reason != REASON_WDT_RST) { + // Not a crash, reset reboot counter + rtcMem.rebootCount = 0; + } else { + // Crash detected, increment reboot counter + rtcMem.rebootCount++; + + // If more than 3 consecutive crashes, enter safe mode + if (rtcMem.rebootCount >= 3) { + // Implement safe mode actions here + // For example, disable certain features or notify the user + Serial.begin(115200); + Serial.println("Entering safe mode due to repeated crashes."); + // Additional safe mode logic can be added here +#if defined(ESP8266) + Serial.println("Entering flash mode..."); + delay(1000); + ESP.rebootIntoUartDownloadMode(); +#else + Serial.println("Flash mode not supported on this platform!"); +#endif + } + } + Serial.println("Reboot Count: " + String(rtcMem.rebootCount)); + ESP.rtcUserMemoryWrite(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); + + +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index d8589cdf6..93466ec86 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,8 +21,11 @@ THE SOFTWARE. */ -#include +#ifdef esp8266 +#include "init.h" +#endif +#include #include "GlobalVars.h" #include "Wire.h" #include "batterymonitor.h" @@ -59,6 +62,10 @@ BatteryMonitor battery; TPSCounter tpsCounter; void setup() { + while (true) { + + + } Serial.begin(serialBaudRate); globalTimer = timer_create_default(); @@ -159,6 +166,9 @@ void loop() { OTA::otaUpdate(); networkManager.update(); + // Process buffered logs + SlimeVR::Logging::LogBuffer::getInstance().processCycle(); + #if DEBUG_MEASURE_SENSOR_TIME_TAKEN sensorMeasurer.before(); #endif From d279b975439fefb61ca09b05f6f58606b082b5a9 Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Sun, 11 Jan 2026 15:54:45 +0100 Subject: [PATCH 03/13] Removing While Loop and int fixes --- src/init.h | 18 +++++++----------- src/main.cpp | 8 +------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/init.h b/src/init.h index 7b7c86290..433ed7e62 100644 --- a/src/init.h +++ b/src/init.h @@ -23,19 +23,17 @@ #include #ifdef ESP8266 -#include // Include this to define rst_info - +#include // Include this to define rst_info typedef struct rtc_mem { - uint32_t version; // RTC memory version + uint32_t version; // RTC memory version uint32_t rebootCount; // Number of reboots } rtc_mem_t; // Constructor function that runs during static initialization (before setup) -__attribute__((constructor)) -void checkrebootcount(){ +__attribute__((constructor)) void checkrebootcount() { Serial.begin(115200); - struct rst_info *resetreason; + struct rst_info* resetreason; rtc_mem_t rtcMem; resetreason = ESP.getResetInfoPtr(); Serial.println("Reset reason code: " + String(resetreason->reason)); @@ -48,9 +46,9 @@ void checkrebootcount(){ rtcMem.version = 0x01; rtcMem.rebootCount = 0; } - if (resetreason->reason != REASON_SOFT_WDT_RST && - resetreason->reason != REASON_EXCEPTION_RST && - resetreason->reason != REASON_WDT_RST) { + if (resetreason->reason != REASON_SOFT_WDT_RST + && resetreason->reason != REASON_EXCEPTION_RST + && resetreason->reason != REASON_WDT_RST) { // Not a crash, reset reboot counter rtcMem.rebootCount = 0; } else { @@ -75,8 +73,6 @@ void checkrebootcount(){ } Serial.println("Reboot Count: " + String(rtcMem.rebootCount)); ESP.rtcUserMemoryWrite(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); - - } #endif diff --git a/src/main.cpp b/src/main.cpp index 93466ec86..4c0d0e028 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,7 @@ #endif #include + #include "GlobalVars.h" #include "Wire.h" #include "batterymonitor.h" @@ -62,10 +63,6 @@ BatteryMonitor battery; TPSCounter tpsCounter; void setup() { - while (true) { - - - } Serial.begin(serialBaudRate); globalTimer = timer_create_default(); @@ -166,9 +163,6 @@ void loop() { OTA::otaUpdate(); networkManager.update(); - // Process buffered logs - SlimeVR::Logging::LogBuffer::getInstance().processCycle(); - #if DEBUG_MEASURE_SENSOR_TIME_TAKEN sensorMeasurer.before(); #endif From f56efb0d820dc5cef49ab897ddde9fda3579b12f Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 13 Jan 2026 03:47:31 +0100 Subject: [PATCH 04/13] using preinit --- src/init.h | 40 +++++++++++++++++++++++----------------- src/main.cpp | 5 +---- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/init.h b/src/init.h index 433ed7e62..ce5d1332e 100644 --- a/src/init.h +++ b/src/init.h @@ -23,24 +23,31 @@ #include #ifdef ESP8266 -#include // Include this to define rst_info +#include typedef struct rtc_mem { uint32_t version; // RTC memory version uint32_t rebootCount; // Number of reboots } rtc_mem_t; -// Constructor function that runs during static initialization (before setup) -__attribute__((constructor)) void checkrebootcount() { - Serial.begin(115200); +extern "C" void preinit(void) { + HardwareSerial Serialtemp(0); struct rst_info* resetreason; rtc_mem_t rtcMem; resetreason = ESP.getResetInfoPtr(); - Serial.println("Reset reason code: " + String(resetreason->reason)); + Serialtemp.begin(115200); + + Serialtemp.println("\r\n==== SLVR Boot ===="); + Serialtemp.println("Reboot reason code: " + String(ESP.getResetInfoPtr()->reason)); + Serialtemp.println("Core Version: " + ESP.getCoreVersion()); + Serialtemp.println("SDK version: " + String(ESP.getSdkVersion())); + Serialtemp.println("Sketch MD5: " + String(ESP.getSketchMD5())); + Serialtemp.println("Reset reason code: " + String(resetreason->reason)); + // Offset 33 to avoid eboot command area ESP.rtcUserMemoryRead(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); - Serial.println("RTC Memory Version: " + String(rtcMem.version)); - Serial.println("RTC Memory Reboot Count: " + String(rtcMem.rebootCount)); + Serialtemp.println("RTC Memory Version: " + String(rtcMem.version)); + Serialtemp.println("RTC Memory Reboot Count: " + String(rtcMem.rebootCount)); if (rtcMem.version != 0x01) { // First boot, initialize RTC memory rtcMem.version = 0x01; @@ -59,20 +66,19 @@ __attribute__((constructor)) void checkrebootcount() { if (rtcMem.rebootCount >= 3) { // Implement safe mode actions here // For example, disable certain features or notify the user - Serial.begin(115200); - Serial.println("Entering safe mode due to repeated crashes."); - // Additional safe mode logic can be added here -#if defined(ESP8266) - Serial.println("Entering flash mode..."); + Serialtemp.println("\r\n\r\nEntering safe mode due to repeated crashes."); + Serialtemp.println("Entering flash mode..."); + Serialtemp.flush(); + Serialtemp.end(); delay(1000); ESP.rebootIntoUartDownloadMode(); -#else - Serial.println("Flash mode not supported on this platform!"); -#endif } } - Serial.println("Reboot Count: " + String(rtcMem.rebootCount)); ESP.rtcUserMemoryWrite(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); -} + Serialtemp.println("=== SLVR Boot end ==="); + Serialtemp.flush(); + // Deinit UART for main code to reinitialize + Serialtemp.end(); +} #endif diff --git a/src/main.cpp b/src/main.cpp index 4c0d0e028..c32e901a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,10 +21,6 @@ THE SOFTWARE. */ -#ifdef esp8266 -#include "init.h" -#endif - #include #include "GlobalVars.h" @@ -33,6 +29,7 @@ #include "credentials.h" #include "debugging/TimeTaken.h" #include "globals.h" +#include "init.h" #include "logging/Logger.h" #include "ota.h" #include "serial/serialcommands.h" From 4136e6ce9d8428d2b56490582e3711cf4e89f03d Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 13 Jan 2026 03:51:43 +0100 Subject: [PATCH 05/13] Edit Comment --- src/init.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/init.h b/src/init.h index ce5d1332e..167777414 100644 --- a/src/init.h +++ b/src/init.h @@ -64,8 +64,7 @@ extern "C" void preinit(void) { // If more than 3 consecutive crashes, enter safe mode if (rtcMem.rebootCount >= 3) { - // Implement safe mode actions here - // For example, disable certain features or notify the user + // Boot into UART download mode Serialtemp.println("\r\n\r\nEntering safe mode due to repeated crashes."); Serialtemp.println("Entering flash mode..."); Serialtemp.flush(); From 27a4736abbe96d100fd214c6900058824e58040f Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:31:23 +0100 Subject: [PATCH 06/13] Make flashmode work in preinit() --- src/init.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/init.h b/src/init.h index 167777414..18bf2418f 100644 --- a/src/init.h +++ b/src/init.h @@ -67,8 +67,9 @@ extern "C" void preinit(void) { // Boot into UART download mode Serialtemp.println("\r\n\r\nEntering safe mode due to repeated crashes."); Serialtemp.println("Entering flash mode..."); - Serialtemp.flush(); - Serialtemp.end(); + // Serial needs to be stay active for + // rebootIntoUartDownloadMode to work. + // Found out over testing. delay(1000); ESP.rebootIntoUartDownloadMode(); } From bfeeae5dd4485cdca4a44020887d4926fcb18677 Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:34:03 +0100 Subject: [PATCH 07/13] Add more Infos and use only flash for text --- src/init.h | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/init.h b/src/init.h index 18bf2418f..ede96296d 100644 --- a/src/init.h +++ b/src/init.h @@ -25,6 +25,9 @@ #ifdef ESP8266 #include +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + typedef struct rtc_mem { uint32_t version; // RTC memory version uint32_t rebootCount; // Number of reboots @@ -35,19 +38,29 @@ extern "C" void preinit(void) { struct rst_info* resetreason; rtc_mem_t rtcMem; resetreason = ESP.getResetInfoPtr(); - Serialtemp.begin(115200); - - Serialtemp.println("\r\n==== SLVR Boot ===="); - Serialtemp.println("Reboot reason code: " + String(ESP.getResetInfoPtr()->reason)); - Serialtemp.println("Core Version: " + ESP.getCoreVersion()); - Serialtemp.println("SDK version: " + String(ESP.getSdkVersion())); - Serialtemp.println("Sketch MD5: " + String(ESP.getSketchMD5())); - Serialtemp.println("Reset reason code: " + String(resetreason->reason)); - // Offset 33 to avoid eboot command area ESP.rtcUserMemoryRead(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); - Serialtemp.println("RTC Memory Version: " + String(rtcMem.version)); - Serialtemp.println("RTC Memory Reboot Count: " + String(rtcMem.rebootCount)); + Serialtemp.begin(115200); + Serialtemp.println(F("\r\n==== SLVR Boot ====")); + Serialtemp.println(F("Reboot reason code: ") + String(ESP.getResetInfoPtr()->reason)); + Serialtemp.println(F("Core Version: ") + ESP.getCoreVersion()); + Serialtemp.println(F("SDK version: ") + String(ESP.getSdkVersion())); + Serialtemp.println(F("Sketch MD5: ") + String(ESP.getSketchMD5())); + Serialtemp.println(F("Reset reason code: ") + String(resetreason->reason)); + Serialtemp.println(F("RTC Memory Version: ") + String(rtcMem.version)); + Serialtemp.println(F("RTC Memory Reboot Count: ") + String(rtcMem.rebootCount)); + Serialtemp.println(""); + Serialtemp.println(F("PRODUCT_NAME: ") + String(PRODUCT_NAME)); + Serialtemp.println(F("VENDOR_NAME: ") + String(VENDOR_NAME)); + Serialtemp.println(F("VENDOR_URL: ") + String(VENDOR_URL)); + Serialtemp.println(F("Firmware update URL: ") + String(UPDATE_ADDRESS)); + Serialtemp.println(F("BOARD: ") + String(BOARD)); + Serialtemp.println(F("HARDWARE_MCU: ") + String(HARDWARE_MCU)); + Serialtemp.println(F("PROTOCOL_VERSION: ") + String(PROTOCOL_VERSION)); + Serialtemp.println(F("FIRMWARE_VERSION: ") + String(FIRMWARE_VERSION)); + Serialtemp.println(F("SENSOR_DESC_LIST: ")); + Serialtemp.println(String(TOSTRING(SENSOR_DESC_LIST))); + if (rtcMem.version != 0x01) { // First boot, initialize RTC memory rtcMem.version = 0x01; @@ -65,8 +78,8 @@ extern "C" void preinit(void) { // If more than 3 consecutive crashes, enter safe mode if (rtcMem.rebootCount >= 3) { // Boot into UART download mode - Serialtemp.println("\r\n\r\nEntering safe mode due to repeated crashes."); - Serialtemp.println("Entering flash mode..."); + Serialtemp.println(F("\r\n\r\nEntering safe mode due to repeated crashes.")); + Serialtemp.println(F("Entering flash mode...")); // Serial needs to be stay active for // rebootIntoUartDownloadMode to work. // Found out over testing. @@ -76,7 +89,7 @@ extern "C" void preinit(void) { } ESP.rtcUserMemoryWrite(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); - Serialtemp.println("=== SLVR Boot end ==="); + Serialtemp.println(F("=== SLVR Boot end ===")); Serialtemp.flush(); // Deinit UART for main code to reinitialize Serialtemp.end(); From 035ae0e03c9affdae04eb73d6ab5451f1bc51e2b Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:41:26 +0100 Subject: [PATCH 08/13] clang Format --- src/init.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/init.h b/src/init.h index ede96296d..215ac04b4 100644 --- a/src/init.h +++ b/src/init.h @@ -42,7 +42,9 @@ extern "C" void preinit(void) { ESP.rtcUserMemoryRead(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); Serialtemp.begin(115200); Serialtemp.println(F("\r\n==== SLVR Boot ====")); - Serialtemp.println(F("Reboot reason code: ") + String(ESP.getResetInfoPtr()->reason)); + Serialtemp.println( + F("Reboot reason code: ") + String(ESP.getResetInfoPtr()->reason) + ); Serialtemp.println(F("Core Version: ") + ESP.getCoreVersion()); Serialtemp.println(F("SDK version: ") + String(ESP.getSdkVersion())); Serialtemp.println(F("Sketch MD5: ") + String(ESP.getSketchMD5())); From b5bd79199ea1e06c9bee7109f7e078d2ad606d39 Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:43:25 +0100 Subject: [PATCH 09/13] more format --- src/init.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/init.h b/src/init.h index 215ac04b4..223c28981 100644 --- a/src/init.h +++ b/src/init.h @@ -80,7 +80,9 @@ extern "C" void preinit(void) { // If more than 3 consecutive crashes, enter safe mode if (rtcMem.rebootCount >= 3) { // Boot into UART download mode - Serialtemp.println(F("\r\n\r\nEntering safe mode due to repeated crashes.")); + Serialtemp.println( + F("\r\n\r\nEntering safe mode due to repeated crashes.") + ); Serialtemp.println(F("Entering flash mode...")); // Serial needs to be stay active for // rebootIntoUartDownloadMode to work. From 0414e8ffbc65d903b18412834a2b0696b8bb907a Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:59:33 +0100 Subject: [PATCH 10/13] clang format 3th round, fight --- src/init.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/init.h b/src/init.h index 223c28981..34507822c 100644 --- a/src/init.h +++ b/src/init.h @@ -51,7 +51,7 @@ extern "C" void preinit(void) { Serialtemp.println(F("Reset reason code: ") + String(resetreason->reason)); Serialtemp.println(F("RTC Memory Version: ") + String(rtcMem.version)); Serialtemp.println(F("RTC Memory Reboot Count: ") + String(rtcMem.rebootCount)); - Serialtemp.println(""); + Serialtemp.println(); Serialtemp.println(F("PRODUCT_NAME: ") + String(PRODUCT_NAME)); Serialtemp.println(F("VENDOR_NAME: ") + String(VENDOR_NAME)); Serialtemp.println(F("VENDOR_URL: ") + String(VENDOR_URL)); @@ -80,9 +80,9 @@ extern "C" void preinit(void) { // If more than 3 consecutive crashes, enter safe mode if (rtcMem.rebootCount >= 3) { // Boot into UART download mode - Serialtemp.println( - F("\r\n\r\nEntering safe mode due to repeated crashes.") - ); + Serialtemp.println(); + Serialtemp.println(); + Serialtemp.println(F("Entering safe mode due to repeated crashes.")); Serialtemp.println(F("Entering flash mode...")); // Serial needs to be stay active for // rebootIntoUartDownloadMode to work. From eee31d79b3212822a5d401b5401d010505a10376 Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Tue, 27 Jan 2026 01:14:56 +0100 Subject: [PATCH 11/13] Add support for ESP-IDF --- src/init.h | 103 ++++++++++++++++++++++++++++++++-- src/serial/serialcommands.cpp | 9 +++ 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/src/init.h b/src/init.h index 34507822c..faa4888e9 100644 --- a/src/init.h +++ b/src/init.h @@ -42,13 +42,10 @@ extern "C" void preinit(void) { ESP.rtcUserMemoryRead(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); Serialtemp.begin(115200); Serialtemp.println(F("\r\n==== SLVR Boot ====")); - Serialtemp.println( - F("Reboot reason code: ") + String(ESP.getResetInfoPtr()->reason) - ); + Serialtemp.println(F("Reboot reason code: ") + String(resetreason->reason)); Serialtemp.println(F("Core Version: ") + ESP.getCoreVersion()); Serialtemp.println(F("SDK version: ") + String(ESP.getSdkVersion())); Serialtemp.println(F("Sketch MD5: ") + String(ESP.getSketchMD5())); - Serialtemp.println(F("Reset reason code: ") + String(resetreason->reason)); Serialtemp.println(F("RTC Memory Version: ") + String(rtcMem.version)); Serialtemp.println(F("RTC Memory Reboot Count: ") + String(rtcMem.rebootCount)); Serialtemp.println(); @@ -99,3 +96,101 @@ extern "C" void preinit(void) { Serialtemp.end(); } #endif + +#ifdef ESP32 +#include "esp_system.h" +#if defined(CONFIG_IDF_TARGET_ESP32C3) +#include "soc/rtc_cntl_reg.h" +#endif +//#include "driver/rtc_io.h" +#include "esp_chip_info.h" +#include "esp_intr_alloc.h" + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +typedef struct rtc_mem { + uint32_t version; // RTC memory version + uint32_t rebootCount; // Number of reboots +} rtc_mem_t; + +// infos from https://circuitlabs.net/rtc-memory-usage-in-esp-idf/ +RTC_DATA_ATTR rtc_mem_t rtcMem; + +extern "C" void initVariant(void) { + esp_reset_reason_t resetreason; + + resetreason = esp_reset_reason(); + + // don't need to read RTC memory as it is cleard on a WDT reset on ESP32 + + Serial.begin(115200); + Serial.println(F("\r\n==== SLVR Boot ====")); + Serial.println(String(F("Reboot reason code: ")) + String(resetreason)); + Serial.println(String(F("Core Version: ")) + String(ESP.getCoreVersion())); + Serial.println(String(F("SDK version: ")) + String(ESP.getSdkVersion())); + Serial.println(String(F("Sketch MD5: ")) + String(ESP.getSketchMD5())); + Serial.println(String(F("RTC Memory Version: ")) + String(rtcMem.version)); + Serial.println(String(F("RTC Memory Reboot Count: ")) + String(rtcMem.rebootCount)); + Serial.println(); + Serial.println(String(F("PRODUCT_NAME: ")) + String(PRODUCT_NAME)); + Serial.println(String(F("VENDOR_NAME: ")) + String(VENDOR_NAME)); + Serial.println(String(F("VENDOR_URL: ")) + String(VENDOR_URL)); + Serial.println(String(F("Firmware update URL: ")) + String(UPDATE_ADDRESS)); + Serial.println(String(F("BOARD: ")) + String(BOARD)); + Serial.println(String(F("HARDWARE_MCU: ")) + String(HARDWARE_MCU)); + Serial.println(String(F("PROTOCOL_VERSION: ")) + String(PROTOCOL_VERSION)); + Serial.println(String(F("FIRMWARE_VERSION: ")) + String(FIRMWARE_VERSION)); + Serial.println(F("SENSOR_DESC_LIST: ")); + Serial.println(String(TOSTRING(SENSOR_DESC_LIST))); + + if (rtcMem.version != 0x01) { + // First boot, initialize RTC memory + rtcMem.version = 0x01; + rtcMem.rebootCount = 0; + } + if (resetreason != ESP_RST_PANIC && resetreason != ESP_RST_INT_WDT + && resetreason != ESP_RST_TASK_WDT && resetreason != ESP_RST_WDT + && resetreason != ESP_RST_CPU_LOCKUP) { + // Not a crash, reset reboot counter + rtcMem.rebootCount = 0; + } else { + // Crash detected + // ESP32 ram gets cleared on WDT reset, force safe mode + rtcMem.rebootCount = 4; + + // If more than 3 consecutive crashes, enter safe mode + if (rtcMem.rebootCount >= 3) { + // Boot into UART download mode + Serial.println(); + Serial.println(); + +#if defined(CONFIG_IDF_TARGET_ESP32C3) + Serial.println(F("Entering safe mode due to repeated crashes.")); + Serial.println(F("Entering flash mode...")); + // from https://esp32.com/viewtopic.php?t=33180 + delay(1000); + REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); + esp_restart(); +#else + Serial.println( + F("The Firmware does not support reboot into UART download mode for " + "this board.") + ); + Serial.println( + F("You need to manually enter flash mode by holding BOOT button while " + "resetting.") + ); + while (true) { + delay(100); // Halt + } +#endif + } + } + // no need to write, rtcMem is in RTC memory it does it automatically + // ESP.rtcUserMemoryWrite(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); + + Serial.println(F("=== SLVR Boot end ===")); + Serial.flush(); +} +#endif diff --git a/src/serial/serialcommands.cpp b/src/serial/serialcommands.cpp index cc7a92276..dea14f339 100644 --- a/src/serial/serialcommands.cpp +++ b/src/serial/serialcommands.cpp @@ -33,6 +33,9 @@ #ifdef ESP32 #include "nvs_flash.h" +#if defined(CONFIG_IDF_TARGET_ESP32C3) +#include "soc/rtc_cntl_reg.h" +#endif #endif #ifdef EXT_SERIAL_COMMANDS @@ -163,6 +166,12 @@ void cmdSet(CmdParser* parser) { logger.info("Entering flash mode..."); delay(1000); ESP.rebootIntoUartDownloadMode(); +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + logger.info("Entering flash mode..."); + delay(1000); + // from https://esp32.com/viewtopic.php?t=33180 + REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); + esp_restart(); #else logger.info("Flash mode not supported on this platform!"); #endif From 20750f3a21171e424966dd518f4e99a9ff07c9d9 Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Mon, 2 Feb 2026 19:54:28 +0100 Subject: [PATCH 12/13] format --- src/init.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/init.h b/src/init.h index faa4888e9..dd44230ea 100644 --- a/src/init.h +++ b/src/init.h @@ -102,7 +102,6 @@ extern "C" void preinit(void) { #if defined(CONFIG_IDF_TARGET_ESP32C3) #include "soc/rtc_cntl_reg.h" #endif -//#include "driver/rtc_io.h" #include "esp_chip_info.h" #include "esp_intr_alloc.h" From 7e4a9ed237d1f095e333e08c27d7cfd738561f2e Mon Sep 17 00:00:00 2001 From: unlogisch04 <98281608+unlogisch04@users.noreply.github.com> Date: Fri, 20 Mar 2026 00:25:19 +0100 Subject: [PATCH 13/13] Add emergency shell, frst, reboot function --- src/configuration/Configuration.cpp | 20 ++ src/consts.h | 57 ++++++ src/init.h | 305 +++++++++++++++++++--------- 3 files changed, 284 insertions(+), 98 deletions(-) diff --git a/src/configuration/Configuration.cpp b/src/configuration/Configuration.cpp index cadca181b..32112d3e7 100644 --- a/src/configuration/Configuration.cpp +++ b/src/configuration/Configuration.cpp @@ -38,12 +38,32 @@ #define DIR_TOGGLES_OLD "/toggles" #define DIR_TOGGLES "/sensortoggles" +// Global variable defined at file scope (not in namespace) so init.h can access it +extern bool g_safeModeDeferredFactoryResetRequested; + namespace SlimeVR::Configuration { void Configuration::setup() { if (m_Loaded) { return; } + // Safe mode defers LittleFS formatting to normal runtime for reliability. + // If requested, perform the filesystem format before config load. + if (g_safeModeDeferredFactoryResetRequested) { + m_Logger.warn("Deferred safe-mode factory reset detected, formatting LittleFS"); + g_safeModeDeferredFactoryResetRequested = false; + + LittleFS.begin(); + if (!LittleFS.format()) { + m_Logger.error("Deferred LittleFS format failed"); + } else { + m_Logger.info("Deferred LittleFS format OK"); + m_Logger.warn("Rebooting after deferred safe-mode factory reset"); + ESP.restart(); + return; + } + } + bool status = LittleFS.begin(); if (!status) { this->m_Logger.warn("Could not mount LittleFS, formatting"); diff --git a/src/consts.h b/src/consts.h index 76119c5ae..82b136c86 100644 --- a/src/consts.h +++ b/src/consts.h @@ -98,6 +98,63 @@ enum class SensorTypeID : uint8_t { #define BOARD_ESP32S3_SUPERMINI 23 #define BOARD_DEV_RESERVED 250 // Reserved, should not be used in any release firmware +// Returns the BOARD define name (e.g. "BOARD_WEMOSD1MINI"). +// Kept Arduino-independent because this header is used outside Arduino units. +inline const char* boardName() { + switch (BOARD) { + case BOARD_SLIMEVR_LEGACY: + return "BOARD_SLIMEVR_LEGACY"; + case BOARD_SLIMEVR_DEV: + return "BOARD_SLIMEVR_DEV"; + case BOARD_NODEMCU: + return "BOARD_NODEMCU"; + case BOARD_CUSTOM: + return "BOARD_CUSTOM"; + case BOARD_WROOM32: + return "BOARD_WROOM32"; + case BOARD_WEMOSD1MINI: + return "BOARD_WEMOSD1MINI"; + case BOARD_TTGO_TBASE: + return "BOARD_TTGO_TBASE"; + case BOARD_ESP01: + return "BOARD_ESP01"; + case BOARD_SLIMEVR: + return "BOARD_SLIMEVR"; + case BOARD_LOLIN_C3_MINI: + return "BOARD_LOLIN_C3_MINI"; + case BOARD_BEETLE32C3: + return "BOARD_BEETLE32C3"; + case BOARD_ESP32C3DEVKITM1: + return "BOARD_ESP32C3DEVKITM1"; + case BOARD_OWOTRACK: + return "BOARD_OWOTRACK"; + case BOARD_WRANGLER: + return "BOARD_WRANGLER"; + case BOARD_MOCOPI: + return "BOARD_MOCOPI"; + case BOARD_WEMOSWROOM02: + return "BOARD_WEMOSWROOM02"; + case BOARD_XIAO_ESP32C3: + return "BOARD_XIAO_ESP32C3"; + case BOARD_HARITORA: + return "BOARD_HARITORA"; + case BOARD_ESP32C6DEVKITC1: + return "BOARD_ESP32C6DEVKITC1"; + case BOARD_GLOVE_IMU_SLIMEVR_DEV: + return "BOARD_GLOVE_IMU_SLIMEVR_DEV"; + case BOARD_GESTURES: + return "BOARD_GESTURES"; + case BOARD_SLIMEVR_V1_2: + return "BOARD_SLIMEVR_V1_2"; + case BOARD_ESP32S3_SUPERMINI: + return "BOARD_ESP32S3_SUPERMINI"; + case BOARD_DEV_RESERVED: + return "BOARD_DEV_RESERVED"; + default: + return "BOARD_UNKNOWN"; + } +} + #define BAT_EXTERNAL 1 #define BAT_INTERNAL 2 #define BAT_MCP3021 3 diff --git a/src/init.h b/src/init.h index dd44230ea..7c5cd737c 100644 --- a/src/init.h +++ b/src/init.h @@ -22,8 +22,16 @@ */ #include -#ifdef ESP8266 -#include + +#ifdef ESP32 +#include "esp_chip_info.h" +#include "esp_intr_alloc.h" +#include "esp_system.h" +#include "nvs_flash.h" +#if defined(CONFIG_IDF_TARGET_ESP32C3) +#include "soc/rtc_cntl_reg.h" +#endif +#endif #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -33,38 +41,195 @@ typedef struct rtc_mem { uint32_t rebootCount; // Number of reboots } rtc_mem_t; +bool g_safeModeDeferredFactoryResetRequested = false; + +void failSafeProductInfo(Stream* Serial) { + Serial->println(F("==== SLVR Product Info ====")); + Serial->println(String(F("PRODUCT_NAME: ")) + String(PRODUCT_NAME)); + Serial->println(String(F("VENDOR_NAME: ")) + String(VENDOR_NAME)); + Serial->println(String(F("VENDOR_URL: ")) + String(VENDOR_URL)); + Serial->println(String(F("Firmware update URL: ")) + String(UPDATE_ADDRESS)); + Serial->println(String(F("BOARD: ")) + String(BOARD)); + Serial->println(String(F("BOARD NAME: ")) + String(boardName())); + Serial->println(String(F("HARDWARE_MCU: ")) + String(HARDWARE_MCU)); + Serial->println(String(F("PROTOCOL_VERSION: ")) + String(PROTOCOL_VERSION)); + Serial->println(String(F("FIRMWARE_VERSION: ")) + String(FIRMWARE_VERSION)); + Serial->println(F("SENSOR_DESC_LIST: ")); + Serial->println(String(TOSTRING(SENSOR_DESC_LIST))); +} + +void failSafeBootInfo(Stream* Serial, uint32_t resetreason, rtc_mem_t* rtcMem) { + Serial->println(F("\r\n==== SLVR Boot ====")); + Serial->println(String(F("Reboot reason code: ")) + String(resetreason)); + Serial->println(String(F("Core Version: ")) + String(ESP.getCoreVersion())); + Serial->println(String(F("SDK version: ")) + String(ESP.getSdkVersion())); + Serial->println(String(F("Sketch MD5: ")) + String(ESP.getSketchMD5())); + Serial->println(String(F("RTC Memory Version: ")) + String(rtcMem->version)); + Serial->println( + String(F("RTC Memory Reboot Count: ")) + String(rtcMem->rebootCount) + ); + Serial->println(); + failSafeProductInfo(Serial); +} + +bool cmdSafeModeFlashMode(Stream* Serial) { +#if defined(ESP8266) + Serial->println(F("Entering flash mode...")); + // Serial needs to be stay active for + // rebootIntoUartDownloadMode to work. + // Found out over testing. + delay(1000); + ESP.rebootIntoUartDownloadMode(); + return true; + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + Serial->println(F("Entering flash mode...")); + // from https://esp32.com/viewtopic.php?t=33180 + delay(1000); + REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); + esp_restart(); + return true; + +#else + Serial->println( + F("The Firmware does not support reboot into UART download mode for " + "this board.") + ); + Serial->println( + F("You need to manually enter flash mode by holding BOOT button while " + "resetting.") + ); +#endif + return false; // Not supported, caller should handle with a message +} + +void cmdSafeModeReboot() { +#if defined(ESP8266) + // During preinit, system_restart() (used by ESP.restart()) is asynchronous — + // it posts to the SDK task queue which hasn't started yet, causing a hang. + // ESP.reset() calls __real_system_restart_local() which is a direct hardware reset. + ESP.reset(); +#else + ESP.restart(); +#endif +} + +bool cmdSafeModeFactoryReset(Stream* Serial) { + // WiFi and LittleFS operations are not reliable during preinit() on either + // platform. Defer filesystem formatting to normal runtime. + g_safeModeDeferredFactoryResetRequested = true; + +#if defined(ESP8266) + ESP.eraseConfig(); // Erase SDK config sectors (WiFi credentials etc.) +#elif defined(ESP32) + nvs_flash_erase(); // Erase NVS (equivalent to ESP8266's config) +#endif + + if (Serial) { + Serial->println(F("LittleFS format deferred to runtime.")); + Serial->println(F("Continuing normal boot for format + final reboot...")); + Serial->flush(); + } + return true; +} + +void cmdSafeModeHelp(Stream* Serial) { + Serial->println(F("Available commands:")); + Serial->println( + F(" FRST - Factory reset (clears WiFi credentials " + "and config, then reboots)") + ); + Serial->println(F(" REBOOT - Restart the device")); + Serial->println(F(" SET FLASHMODE - Enter UART download / flash mode")); + Serial->println(F(" HELP - Show this help message")); +} + +// Maximum input line length — longest valid command is "SET FLASHMODE" (13 chars). +// Anything beyond this is serial noise or garbage; discard to protect the heap. +// This is especially important because mainSave() runs during preinit/initVariant +// before full system initialization. +#define MAINSAVE_CMD_MAXLEN 32 + +// mainSave is for all the Shell needed loop in case of safe mode +bool mainSave(Stream* Serial) { + String inputBuffer = ""; + + Serial->println(); + Serial->println(F("=== SLVR Emergency Shell ===")); + Serial->println(F("Safe mode command prompt. Type 'HELP' for available commands.")); + cmdSafeModeHelp(Serial); + + while (true) { + while (Serial->available()) { + char c = (char)Serial->read(); + if (c == '\r') { + continue; // ignore carriage return + } + if (c == '\n') { + inputBuffer.trim(); + String cmd = inputBuffer; + cmd.toUpperCase(); + inputBuffer = ""; + + if (cmd == "FRST") { + Serial->println(F("Performing factory reset...")); + if (cmdSafeModeFactoryReset(Serial)) { + return true; + } + } else if (cmd == "REBOOT") { + Serial->println(F("Rebooting...")); + cmdSafeModeReboot(); + } else if (cmd == "SET FLASHMODE") { + cmdSafeModeFlashMode(Serial); + } else if (cmd == "HELP") { + cmdSafeModeHelp(Serial); + } else if (cmd.length() > 0) { + Serial->print(F("Unknown command: '")); + Serial->print(cmd); + Serial->println(F("'. Type 'HELP' for available commands.")); + } + } else { + if (inputBuffer.length() >= MAINSAVE_CMD_MAXLEN) { + // Buffer overflow — likely serial noise or garbage data. Discard + // and warn. + Serial->println(F("")); + Serial->println(F("Input too long, discarding line.")); + inputBuffer = ""; + } else { + inputBuffer += c; + } + } + } + +#if defined(ESP8266) + ESP.wdtFeed(); // Feed the watchdog to prevent reset while in this loop +#endif + delay(1); + } +} + +#ifdef ESP8266 +#include + extern "C" void preinit(void) { - HardwareSerial Serialtemp(0); + HardwareSerial Serial(0); struct rst_info* resetreason; rtc_mem_t rtcMem; resetreason = ESP.getResetInfoPtr(); + + Serial.begin(115200); + // Offset 33 to avoid eboot command area - ESP.rtcUserMemoryRead(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); - Serialtemp.begin(115200); - Serialtemp.println(F("\r\n==== SLVR Boot ====")); - Serialtemp.println(F("Reboot reason code: ") + String(resetreason->reason)); - Serialtemp.println(F("Core Version: ") + ESP.getCoreVersion()); - Serialtemp.println(F("SDK version: ") + String(ESP.getSdkVersion())); - Serialtemp.println(F("Sketch MD5: ") + String(ESP.getSketchMD5())); - Serialtemp.println(F("RTC Memory Version: ") + String(rtcMem.version)); - Serialtemp.println(F("RTC Memory Reboot Count: ") + String(rtcMem.rebootCount)); - Serialtemp.println(); - Serialtemp.println(F("PRODUCT_NAME: ") + String(PRODUCT_NAME)); - Serialtemp.println(F("VENDOR_NAME: ") + String(VENDOR_NAME)); - Serialtemp.println(F("VENDOR_URL: ") + String(VENDOR_URL)); - Serialtemp.println(F("Firmware update URL: ") + String(UPDATE_ADDRESS)); - Serialtemp.println(F("BOARD: ") + String(BOARD)); - Serialtemp.println(F("HARDWARE_MCU: ") + String(HARDWARE_MCU)); - Serialtemp.println(F("PROTOCOL_VERSION: ") + String(PROTOCOL_VERSION)); - Serialtemp.println(F("FIRMWARE_VERSION: ") + String(FIRMWARE_VERSION)); - Serialtemp.println(F("SENSOR_DESC_LIST: ")); - Serialtemp.println(String(TOSTRING(SENSOR_DESC_LIST))); + bool rtcOk = ESP.rtcUserMemoryRead(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); - if (rtcMem.version != 0x01) { + if (!rtcOk || rtcMem.version != 0x01) { // First boot, initialize RTC memory rtcMem.version = 0x01; rtcMem.rebootCount = 0; } + + failSafeBootInfo(&Serial, resetreason->reason, &rtcMem); + if (resetreason->reason != REASON_SOFT_WDT_RST && resetreason->reason != REASON_EXCEPTION_RST && resetreason->reason != REASON_WDT_RST) { @@ -77,42 +242,27 @@ extern "C" void preinit(void) { // If more than 3 consecutive crashes, enter safe mode if (rtcMem.rebootCount >= 3) { // Boot into UART download mode - Serialtemp.println(); - Serialtemp.println(); - Serialtemp.println(F("Entering safe mode due to repeated crashes.")); - Serialtemp.println(F("Entering flash mode...")); - // Serial needs to be stay active for - // rebootIntoUartDownloadMode to work. - // Found out over testing. - delay(1000); - ESP.rebootIntoUartDownloadMode(); + Serial.println(); + Serial.println(); + Serial.println(F("Entering safe mode due to repeated crashes.")); + Serial.println(F("Starting Emergency shell...")); + if (mainSave(&Serial)) { + Serial.println(F("Leaving emergency shell and continuing boot...")); + } else { + return; + } } } ESP.rtcUserMemoryWrite(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); - Serialtemp.println(F("=== SLVR Boot end ===")); - Serialtemp.flush(); + Serial.println(F("=== SLVR Boot end ===")); + Serial.flush(); // Deinit UART for main code to reinitialize - Serialtemp.end(); + Serial.end(); } #endif #ifdef ESP32 -#include "esp_system.h" -#if defined(CONFIG_IDF_TARGET_ESP32C3) -#include "soc/rtc_cntl_reg.h" -#endif -#include "esp_chip_info.h" -#include "esp_intr_alloc.h" - -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) - -typedef struct rtc_mem { - uint32_t version; // RTC memory version - uint32_t rebootCount; // Number of reboots -} rtc_mem_t; - // infos from https://circuitlabs.net/rtc-memory-usage-in-esp-idf/ RTC_DATA_ATTR rtc_mem_t rtcMem; @@ -121,33 +271,16 @@ extern "C" void initVariant(void) { resetreason = esp_reset_reason(); - // don't need to read RTC memory as it is cleard on a WDT reset on ESP32 - - Serial.begin(115200); - Serial.println(F("\r\n==== SLVR Boot ====")); - Serial.println(String(F("Reboot reason code: ")) + String(resetreason)); - Serial.println(String(F("Core Version: ")) + String(ESP.getCoreVersion())); - Serial.println(String(F("SDK version: ")) + String(ESP.getSdkVersion())); - Serial.println(String(F("Sketch MD5: ")) + String(ESP.getSketchMD5())); - Serial.println(String(F("RTC Memory Version: ")) + String(rtcMem.version)); - Serial.println(String(F("RTC Memory Reboot Count: ")) + String(rtcMem.rebootCount)); - Serial.println(); - Serial.println(String(F("PRODUCT_NAME: ")) + String(PRODUCT_NAME)); - Serial.println(String(F("VENDOR_NAME: ")) + String(VENDOR_NAME)); - Serial.println(String(F("VENDOR_URL: ")) + String(VENDOR_URL)); - Serial.println(String(F("Firmware update URL: ")) + String(UPDATE_ADDRESS)); - Serial.println(String(F("BOARD: ")) + String(BOARD)); - Serial.println(String(F("HARDWARE_MCU: ")) + String(HARDWARE_MCU)); - Serial.println(String(F("PROTOCOL_VERSION: ")) + String(PROTOCOL_VERSION)); - Serial.println(String(F("FIRMWARE_VERSION: ")) + String(FIRMWARE_VERSION)); - Serial.println(F("SENSOR_DESC_LIST: ")); - Serial.println(String(TOSTRING(SENSOR_DESC_LIST))); - if (rtcMem.version != 0x01) { // First boot, initialize RTC memory rtcMem.version = 0x01; rtcMem.rebootCount = 0; } + + // don't need to read RTC memory as it is cleard on a WDT reset on ESP32 + Serial.begin(115200); + failSafeBootInfo(&Serial, resetreason, &rtcMem); + if (resetreason != ESP_RST_PANIC && resetreason != ESP_RST_INT_WDT && resetreason != ESP_RST_TASK_WDT && resetreason != ESP_RST_WDT && resetreason != ESP_RST_CPU_LOCKUP) { @@ -161,33 +294,9 @@ extern "C" void initVariant(void) { // If more than 3 consecutive crashes, enter safe mode if (rtcMem.rebootCount >= 3) { // Boot into UART download mode - Serial.println(); - Serial.println(); - -#if defined(CONFIG_IDF_TARGET_ESP32C3) - Serial.println(F("Entering safe mode due to repeated crashes.")); - Serial.println(F("Entering flash mode...")); - // from https://esp32.com/viewtopic.php?t=33180 - delay(1000); - REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); - esp_restart(); -#else - Serial.println( - F("The Firmware does not support reboot into UART download mode for " - "this board.") - ); - Serial.println( - F("You need to manually enter flash mode by holding BOOT button while " - "resetting.") - ); - while (true) { - delay(100); // Halt - } -#endif + mainSave(&Serial); } } - // no need to write, rtcMem is in RTC memory it does it automatically - // ESP.rtcUserMemoryWrite(33, (uint32_t*)&rtcMem, sizeof(struct rtc_mem)); Serial.println(F("=== SLVR Boot end ===")); Serial.flush();