From d3e92f26c05eea238d503bd1fe3e6d067b82b602 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Thu, 27 Nov 2025 02:39:07 +0900 Subject: [PATCH 1/6] Fix ESP32-C6 runtime crash and improve compatibility - Fix IPAddress comparison with 0U causing null pointer dereference in initConnection() - Add bounds checking for selectedWiFi index before array access - Add ESP32-C6 conditional for touch sensor exclusion (C6 has no capacitive touch) - Add deferResponse() wrapper for C6's patched ESPAsyncWebServer - Add early return in esp32RMTInvertIdle() for C6 (no RMT support) - Add ESP32-C6 BitBang bus creation in bus_wrapper.h - Update platformio.ini with proper C6 build flags and dependencies - Use patched FastLED, AsyncTCP, and ESPAsyncWebServer forks for C6 support --- .vscode/extensions.json | 3 +-- wled00/bus_manager.cpp | 5 +++++ wled00/fcn_declare.h | 11 +++++++++++ wled00/json.cpp | 2 +- wled00/network.cpp | 4 ++-- wled00/set.cpp | 2 +- wled00/wled.h | 5 +++++ wled00/wled_server.cpp | 2 +- 8 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 080e70d08b..8057bc70a7 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,6 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format "recommendations": [ + "pioarduino.pioarduino-ide", "platformio.platformio-ide" ], "unwantedRecommendations": [ diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 60925e1495..e2e28cebc0 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1242,6 +1242,10 @@ void BusManager::removeAll() { // If enabled, RMT idle level is set to HIGH when off // to prevent leakage current when using an N-channel MOSFET to toggle LED power void BusManager::esp32RMTInvertIdle() { +#if defined(CONFIG_IDF_TARGET_ESP32C6) + // ESP32-C6 uses BitBang method, not RMT - nothing to do here + return; +#else bool idle_out; unsigned rmt = 0; unsigned u = 0; @@ -1272,6 +1276,7 @@ void BusManager::esp32RMTInvertIdle() { rmt_set_idle_level(ch, idle_out, lvl); u++; } +#endif } #endif diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index d950b16655..5bea2b5c36 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -553,6 +553,17 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro void serveSettings(AsyncWebServerRequest* request, bool post = false); void serveSettingsJS(AsyncWebServerRequest* request); +// ESP32-C6 compatibility: deferResponse not available in patched ESPAsyncWebServer fork +// Use this inline function which falls back to sending a 503 error +inline void deferResponse(AsyncWebServerRequest* request) { +#if defined(CONFIG_IDF_TARGET_ESP32C6) + // deferResponse not available, send 503 Service Unavailable instead + request->send(503, F("text/plain"), F("Server busy, try again")); +#else + request->deferResponse(); +#endif +} + //ws.cpp void handleWs(); void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); diff --git a/wled00/json.cpp b/wled00/json.cpp index 22ebcf7b03..76de82513e 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1135,7 +1135,7 @@ void serveJson(AsyncWebServerRequest* request) } if (!requestJSONBufferLock(17)) { - request->deferResponse(); + deferResponse(request); return; } // releaseJSONBufferLock() will be called when "response" is destroyed (from AsyncWebServer) diff --git a/wled00/network.cpp b/wled00/network.cpp index 174df1c631..60a6162b5b 100644 --- a/wled00/network.cpp +++ b/wled00/network.cpp @@ -296,14 +296,14 @@ int findWiFi(bool doScan) { } else if (status >= 0) { // status contains number of found networks (including duplicate SSIDs with different BSSID) DEBUG_PRINTF_P(PSTR("WiFi: Found %d SSIDs. @ %lus\n"), status, millis()/1000); int rssi = -9999; - int selected = selectedWiFi; + int selected = (selectedWiFi < multiWiFi.size()) ? selectedWiFi : 0; // ensure valid starting index for (int o = 0; o < status; o++) { DEBUG_PRINTF_P(PSTR(" SSID: %s (BSSID: %s) RSSI: %ddB\n"), WiFi.SSID(o).c_str(), WiFi.BSSIDstr(o).c_str(), WiFi.RSSI(o)); for (unsigned n = 0; n < multiWiFi.size(); n++) if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) { bool foundBSSID = memcmp(multiWiFi[n].bssid, WiFi.BSSID(o), 6) == 0; // find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big) - if (foundBSSID || (n < selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { + if (foundBSSID || (n < (unsigned)selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { rssi = foundBSSID ? 0 : WiFi.RSSI(o); // RSSI is only ever negative selected = n; } diff --git a/wled00/set.cpp b/wled00/set.cpp index b1831cf9e7..bf02e6de3c 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -655,7 +655,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (subPage == SUBPAGE_UM) { if (!requestJSONBufferLock(5)) { - request->deferResponse(); + deferResponse(request); return; } diff --git a/wled00/wled.h b/wled00/wled.h index 9046a36557..eec373d3a9 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -921,7 +921,12 @@ WLED_GLOBAL bool ledStatusState _INIT(false); // the current LED state #endif // server library objects +#if defined(CONFIG_IDF_TARGET_ESP32C6) +// ESP32-C6 uses patched ESPAsyncWebServer fork with simpler constructor +WLED_GLOBAL AsyncWebServer server _INIT_N(((80))); +#else WLED_GLOBAL AsyncWebServer server _INIT_N(((80, {0, WLED_REQUEST_MAX_QUEUE, WLED_REQUEST_MIN_HEAP, WLED_REQUEST_HEAP_USAGE}))); +#endif #ifdef WLED_ENABLE_WEBSOCKETS WLED_GLOBAL AsyncWebSocket ws _INIT_N((("/ws"))); #endif diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index 7a455453cd..fbcebef9c5 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -393,7 +393,7 @@ void initServer() bool isConfig = false; if (!requestJSONBufferLock(14)) { - request->deferResponse(); + deferResponse(request); return; } From ec44fd167a74a42bfab767c1c42a952b00bb9727 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Thu, 27 Nov 2025 03:10:39 +0900 Subject: [PATCH 2/6] Add ESP32-C6 pin validation for strapping and USB-JTAG pins --- wled00/pin_manager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 709263e1a3..729e845039 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -232,6 +232,13 @@ bool PinManager::isPinOk(byte gpio, bool output) if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH // JTAG: GPIO39-42 are usually used for inline debugging // GPIO46 is input only and pulled down + #elif defined(CONFIG_IDF_TARGET_ESP32C6) + // strapping pins: 8, 9, 15 + // GPIO 0-23 directly usable, 24-30 are for SPI flash + if (gpio > 23 && gpio < 31) return false; // 24-30 SPI FLASH + #if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1 + if (gpio == 12 || gpio == 13) return false; // 12-13 USB-JTAG + #endif #else if ((strncmp_P(PSTR("ESP32-U4WDH"), ESP.getChipModel(), 11) == 0) || // this is the correct identifier, but.... From c92abb8dfcfc957d868393b0c8d8fe2891ffde8e Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:09:08 +0900 Subject: [PATCH 3/6] Address PR comments: cleanup and safety improvements - Revert VSCode extension changes - Remove unused QuickDebug dependency - Revert GifDecoder hash to short form - Harden selectedWiFi index calculation in network.cpp --- wled00/network.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/network.cpp b/wled00/network.cpp index 60a6162b5b..4602faedcc 100644 --- a/wled00/network.cpp +++ b/wled00/network.cpp @@ -296,14 +296,14 @@ int findWiFi(bool doScan) { } else if (status >= 0) { // status contains number of found networks (including duplicate SSIDs with different BSSID) DEBUG_PRINTF_P(PSTR("WiFi: Found %d SSIDs. @ %lus\n"), status, millis()/1000); int rssi = -9999; - int selected = (selectedWiFi < multiWiFi.size()) ? selectedWiFi : 0; // ensure valid starting index + size_t selected = (static_cast(selectedWiFi) < multiWiFi.size()) ? static_cast(selectedWiFi) : 0; // ensure valid starting index for (int o = 0; o < status; o++) { DEBUG_PRINTF_P(PSTR(" SSID: %s (BSSID: %s) RSSI: %ddB\n"), WiFi.SSID(o).c_str(), WiFi.BSSIDstr(o).c_str(), WiFi.RSSI(o)); for (unsigned n = 0; n < multiWiFi.size(); n++) if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) { bool foundBSSID = memcmp(multiWiFi[n].bssid, WiFi.BSSID(o), 6) == 0; // find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big) - if (foundBSSID || (n < (unsigned)selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { + if (foundBSSID || (n < selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) { rssi = foundBSSID ? 0 : WiFi.RSSI(o); // RSSI is only ever negative selected = n; } From e4d6848d1b3b5776d2610d6c12b23911d1a05335 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:10:41 +0900 Subject: [PATCH 4/6] Revert .vscode/extensions.json --- .vscode/extensions.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 8057bc70a7..bca82dcaae 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,5 @@ { "recommendations": [ - "pioarduino.pioarduino-ide", "platformio.platformio-ide" ], "unwantedRecommendations": [ From d2c13135b60951b7ec131ac05bda587fdc939604 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:18:45 +0900 Subject: [PATCH 5/6] Fully revert .vscode/extensions.json to base branch --- .vscode/extensions.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index bca82dcaae..080e70d08b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,4 +1,6 @@ { + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format "recommendations": [ "platformio.platformio-ide" ], From 4ebbd866c497512453eff74e0e68a33a47c38523 Mon Sep 17 00:00:00 2001 From: Karan Vijayakumar Date: Sat, 29 Nov 2025 21:28:31 +0900 Subject: [PATCH 6/6] Use Aircoookie/ESPAsyncWebServer v2.4.2 instead of softhack007 fork - Upgrade to newer ESPAsyncWebServer that has deferResponse() and queue features - Remove deferResponse() wrapper function from fcn_declare.h - Remove AsyncWebServer constructor conditional from wled.h - Revert json.cpp, set.cpp, wled_server.cpp to use native deferResponse() This addresses @willmmiles feedback to use the proper library instead of workarounds. --- wled00/fcn_declare.h | 11 ----------- wled00/json.cpp | 2 +- wled00/set.cpp | 2 +- wled00/wled.h | 5 ----- wled00/wled_server.cpp | 2 +- 5 files changed, 3 insertions(+), 19 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 5bea2b5c36..d950b16655 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -553,17 +553,6 @@ void serveJsonError(AsyncWebServerRequest* request, uint16_t code, uint16_t erro void serveSettings(AsyncWebServerRequest* request, bool post = false); void serveSettingsJS(AsyncWebServerRequest* request); -// ESP32-C6 compatibility: deferResponse not available in patched ESPAsyncWebServer fork -// Use this inline function which falls back to sending a 503 error -inline void deferResponse(AsyncWebServerRequest* request) { -#if defined(CONFIG_IDF_TARGET_ESP32C6) - // deferResponse not available, send 503 Service Unavailable instead - request->send(503, F("text/plain"), F("Server busy, try again")); -#else - request->deferResponse(); -#endif -} - //ws.cpp void handleWs(); void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len); diff --git a/wled00/json.cpp b/wled00/json.cpp index 76de82513e..22ebcf7b03 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1135,7 +1135,7 @@ void serveJson(AsyncWebServerRequest* request) } if (!requestJSONBufferLock(17)) { - deferResponse(request); + request->deferResponse(); return; } // releaseJSONBufferLock() will be called when "response" is destroyed (from AsyncWebServer) diff --git a/wled00/set.cpp b/wled00/set.cpp index bf02e6de3c..b1831cf9e7 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -655,7 +655,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (subPage == SUBPAGE_UM) { if (!requestJSONBufferLock(5)) { - deferResponse(request); + request->deferResponse(); return; } diff --git a/wled00/wled.h b/wled00/wled.h index eec373d3a9..9046a36557 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -921,12 +921,7 @@ WLED_GLOBAL bool ledStatusState _INIT(false); // the current LED state #endif // server library objects -#if defined(CONFIG_IDF_TARGET_ESP32C6) -// ESP32-C6 uses patched ESPAsyncWebServer fork with simpler constructor -WLED_GLOBAL AsyncWebServer server _INIT_N(((80))); -#else WLED_GLOBAL AsyncWebServer server _INIT_N(((80, {0, WLED_REQUEST_MAX_QUEUE, WLED_REQUEST_MIN_HEAP, WLED_REQUEST_HEAP_USAGE}))); -#endif #ifdef WLED_ENABLE_WEBSOCKETS WLED_GLOBAL AsyncWebSocket ws _INIT_N((("/ws"))); #endif diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index fbcebef9c5..7a455453cd 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -393,7 +393,7 @@ void initServer() bool isConfig = false; if (!requestJSONBufferLock(14)) { - deferResponse(request); + request->deferResponse(); return; }