WLED icon indicating copy to clipboard operation
WLED copied to clipboard

ESP-IDF V5

Open netmindz opened this issue 5 months ago • 24 comments

Update the code to handle at least being able to compile against V5


Edit (softhack007): espressif has "silently" changed a lot of APIs, and - in many cases - replacements are not behaving the same way as before. We are lucky that a few "legacy APIs" are still available, like the "V4" I2S driver. So even when "it compiles", there may be a lot more adaptations needed before "it really works".


Helpful information and migration guidance

  • https://docs.espressif.com/projects/esp-idf/en/stable/esp32/migration-guides/release-5.x/5.0/peripherals.html
  • https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference
  • https://docs.espressif.com/projects/arduino-esp32/en/latest/migration_guides/2.x_to_3.0.html
  • https://randomnerdtutorials.com/esp32-migrating-version-2-to-3-arduino/#adc-removed-apis

coding guides

We should make sure that the "V5" branch will still compile for "V4" as a backup solution. When adding code that only works in the new framework, it should be conditionally compiled, like in the examples below

  • "V5" code that is not specific to new boards
      #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
      ledcAttach(pwmPin, 25000, 8);  // New API: ledcAttach(pin, freq, resolution)
      #else
      ledcSetup(pwmChannel, 25000, 8);
      // attach the channel to the GPIO to be controlled
      ledcAttachPin(pwmPin, pwmChannel);
      #endif
  • "V5" code only for esp32-P4 or esp32-C6:
 #if defined(CONFIG_IDF_TARGET_ESP32C6)
    // https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-reference/peripherals/gpio.html
    // strapping pins: 4, 5, 8, 9
    if (gpio > 11 && gpio < 14) return false;     // 12-13 USB-JTAG
    if (gpio > 23 && gpio < 31) return false;     // 24-30 SPI FLASH
#elif defined(CONFIG_IDF_TARGET_ESP32P4)
    // strapping pins: 34,35,36,37,38
    if (             gpio <   2) return false;     // NC
    if (gpio > 13 && gpio <  20) return false;     // ESP-Hosted WiFi pins
    if (gpio > 23 && gpio <  26) return false;     // USB Pins
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
  // .... existing code
#else
  // .... existing code
#endif

related

  • https://github.com/wled/WLED/pull/5048
  • C6 experiments - https://github.com/MoonModules/WLED-MM/pull/138
  • https://github.com/wled/WLED/pull/4626
  • https://github.com/wled/WLED/issues/2871
  • https://github.com/MoonModules/WLED-MM/pull/262
  • P4 support - https://github.com/troyhacks/WLED/tree/P4_experimental

Summary by CodeRabbit

  • New Features

    • Added ESP-IDF v5 support for ESP32 builds with optimized RMT and shared memory handling.
    • Enhanced DMX input with improved RDM personality management and callback handling.
  • Bug Fixes

    • Fixed Ethernet initialization parameter order and static IP address comparison logic.
    • Updated network connectivity checks and IP resolution across modules.
    • Added SHA-1 compatibility shim for ESP-IDF 5.2.0+.
  • Dependencies

    • Updated Python runtime to 3.13.
    • Upgraded platformio, FastLED, NeoPixelBus, and related libraries.

✏️ Tip: You can customize this high-level summary in your review settings.

netmindz avatar Aug 14 '25 17:08 netmindz

[!IMPORTANT]

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR updates WLED to support ESP-IDF v5.x while maintaining v4 compatibility. Key changes include disabling NeoEsp32RmtHI driver compilation, renaming the Network API to WLEDNetwork throughout the codebase, updating LEDC/PWM and Ethernet initialization APIs, implementing DMX RDM personality support, and adding SHA-1 compatibility shims for ESP32 builds.

Changes

Cohort / File(s) Summary
NeoEsp32RmtHI driver disabling
lib/NeoESP32RmtHI/include/NeoEsp32RmtHIMethod.h, lib/NeoESP32RmtHI/src/NeoEsp32RmtHIMethod.cpp
Both files wrapped with #if false ... #endif`` preprocessor blocks, effectively excluding compilation of the RMT driver without removing source code.
Network API refactoring (core)
wled00/src/dependencies/network/Network.h, wled00/src/dependencies/network/Network.cpp
Class renamed from NetworkClass to WLEDNetworkClass; global instance renamed from Network to WLEDNetwork. Adjusted MAC address parsing for ESP32 Ethernet via ETH.macAddress().
Network API refactoring (integration)
wled00/bus_manager.cpp, wled00/e131.cpp, wled00/improv.cpp, wled00/json.cpp, wled00/udp.cpp, wled00/wled.cpp, wled00/wled.h, wled00/wled_server.cpp, wled00/xml.cpp, wled00/src/dependencies/e131/ESPAsyncE131.cpp, wled00/src/dependencies/espalexa/Espalexa.h
Systematic replacement of Network.* method calls with WLEDNetwork.* across connectivity checks, IP retrieval, and subnet calculations. Updated WLED_CONNECTED macro definition.
LEDC/PWM API modernization
wled00/bus_manager.cpp, usermods/PWM_fan/PWM_fan.cpp
Replaced ledcSetup() + ledcAttachPin() with single ledcAttach() call for ESP-IDF v5.x. Replaced ledcDetachPin() with ledcDetach(). Updated xSemaphoreHandle type to SemaphoreHandle_t. Added conditional compilation for API versions.
Ethernet initialization update
wled00/network.cpp
Changed ETH.begin() parameter order and types; now passes PHY type first, followed by address (as int32_t), then MCU pins, power, and clock mode. Updated static IP comparisons to use IPAddress(0,0,0,0) instead of integer constants.
DMX subsystem refactoring
wled00/dmx_input.h, wled00/dmx_input.cpp
Updated RDM callback signatures to include separate request and response headers; introduced personalities array and createPersonalities() helper; changed DMX driver installation to use personality array with count. Added compile-time message, null-check safeguards, and DMX_CONFIG_DEFAULT.
Usermod network updates
usermods/ST7789_display/ST7789_display.cpp, usermods/quinled-an-penta/quinled-an-penta.cpp, usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.cpp
Replaced Network.* references with WLEDNetwork.* for connectivity and IP address retrieval in display update and network state tracking logic.
New compatibility shim
wled00/mbedtls_sha1_shim.cpp
Added ESP32-specific SHA-1 compatibility shim mapping mbedtls SHA-1 API to Arduino SHA1Builder for ESP-IDF v5.2.0+. Provides C-callable wrappers for init, starts, update, finish, and free operations.
NeoPixelBus macro aliasing
wled00/bus_wrapper.h
Inserted conditional macro shim remapping NeoEsp32RmtN...Method macros to NeoEsp32RmtX...Method equivalents when NeoPixelBus.h is available.
Build configuration restructuring
platformio.ini
Comprehensive refactoring: added [esp32_idf_V5] manifest block with V5-specific platform, packages, and flags; updated multiple [esp32*] environments to reference V5 paths; introduced -D WLED_USE_SHARED_RMT and -D WLED_DISABLE_MQTT/-D WLED_DISABLE_INFRARED flags; updated library versions (FastLED, NeoPixelBus, AsyncTCP); reorganized default_envs and environment classifications for V5 compatibility.
Dependency updates
requirements.txt
Updated Python from 3.11 to 3.13; bumped platformio (6.1.17 → 6.1.18), starlette, uvicorn, certifi, packaging, and other transitive dependencies; removed typing-extensions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Areas requiring extra attention:

  • Network API rename propagation: Verify all Network.* references across the codebase have been updated to WLEDNetwork.*. The integration is widespread and any missed reference could cause compilation or runtime failures.
  • platformio.ini configuration matrix: Review the new ESP-IDF v5 environment definitions, flag assignments, and library dependency versions to ensure correct platform targeting and compatibility across ESP32 variants (S2, S3, C3, WROVER).
  • DMX RDM callback signature changes: Validate that the new personality-based driver installation and RDM callback mechanism properly integrates with the DMX hardware driver and that callback wiring passes request/response headers correctly.
  • Ethernet parameter reordering: Confirm the new ETH.begin() call parameter sequence matches the updated Ethernet library API and that static IP comparison logic using IPAddress(0,0,0,0) behaves correctly.
  • LEDC API conditionals: Verify that the conditional compilation branches for ESP-IDF v5.x LEDC methods are correctly guarded and that the legacy paths remain functional for older versions.
  • SHA-1 shim implementation: Review the mbedtls wrapper implementation for correct memory management (allocation/deallocation in init/free) and proper digest calculation flow through SHA1Builder.

Possibly related PRs

  • wled/WLED#4890: Directly addresses NeoEsp32RmtHI driver disabling and conflicts with earlier RMT driver integration efforts.
  • wled/WLED#4748: Modifies network connectivity API structure including WLED_CONNECTED macro and isConnected() checks, closely related to Network → WLEDNetwork refactoring in this PR.

Suggested reviewers

  • willmmiles
  • DedeHai

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.23% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'ESP-IDF V5' is vague and does not clearly convey the scope or specific changes involved in this substantial PR. Consider using a more descriptive title that highlights the main changes, such as 'Update ESP32 code for ESP-IDF V5 compatibility with conditional compilation' or 'Migrate to ESP-IDF V5 with V4 fallback support'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Aug 14 '25 17:08 coderabbitai[bot]

I'm not sure if renaming Network is the right approach to fix the conflict @willmmiles

netmindz avatar Aug 16 '25 11:08 netmindz

I am also unsure why we are seeing linker errors for things like mbedtls_sha1_starts

netmindz avatar Aug 16 '25 11:08 netmindz

I'm not sure if renaming Network is the right approach to fix the conflict @willmmiles

Hm, it looks like it's just a bag of stateless utility functions. Probably it should be a namespace instead of a class. I don't think there's a practical solution to avoid the collision other than renaming, unless the newer core offers these utilities itself. (In fact I'd also suggest pulling them in to wled00/network.cpp , given the use of WLED-specific #defines.)

(Best pratice would've been that the upstream libraries put everything they do in a namespace, eg. Arduino::Network or somesuch, but here we are.)

I am also unsure why we are seeing linker errors for things like mbedtls_sha1_starts

I believe that the Tasmota platform omits mbedtls to save flash space, as they've gone over to BearSSL. Looks like they're still exposing the headers though - I don't know if that's an IDF bug or something wrong with their build process.

AsyncWebServer needs an SHA1 implementation as it is required for WebSockets. It looks like the upstream AWS folks have switched over to IDFv5 functions and vendored in Espressif's implementation when building on IDFv4. I'll see if I can pull those patches.

willmmiles avatar Aug 22 '25 12:08 willmmiles

With few fixes it builds. image

MQTT With the change below I was able to build it (I don’t have a way to test runtime behavior): In AsyncMqttClient.hpp line 41, change: #if ESP32 to #ifdef ESP32

mbedTLS Upstream ESPAsyncWebServer made the change here: 57244d47444a3281ba30f4c9da60fb23d05eb495 Applying similar changes to Aircoookie/ESPAsyncWebServer.git#v2.4.2 made it buildable.

WiFi I had crash related to memcpy and MAC adress was shown as 000000000000. Quick fixes are below.

wled.cpp

Compare IPAddress to a value, not to 0 (prevents pointer overload → memcmp on nullptr) and clamp index (prevents out-of-range access cascading into bad compares).

@@ void WLED::initConnection()
-  if (multiWiFi[selectedWiFi].staticIP != 0U && multiWiFi[selectedWiFi].staticGW != 0U) {
-    WiFi.config(multiWiFi[selectedWiFi].staticIP, multiWiFi[selectedWiFi].staticGW, multiWiFi[selectedWiFi].staticSN, dnsAddress);
-  } else {
-    WiFi.config(IPAddress((uint32_t)0), IPAddress((uint32_t)0), IPAddress((uint32_t)0));
-  }
+ if (multiWiFi.empty()) {                       // guard: handle empty WiFi list safely
+  WiFi.config(IPAddress((uint32_t)0), IPAddress((uint32_t)0), IPAddress((uint32_t)0));
+ } else {
+  if (selectedWiFi >= multiWiFi.size()) selectedWiFi = 0; // guard: ensure valid index
+  if (multiWiFi[selectedWiFi].staticIP != IPAddress((uint32_t)0) &&
+    multiWiFi[selectedWiFi].staticGW != IPAddress((uint32_t)0)) { // guard: compare as IPAddress to avoid pointer overload
+    WiFi.config(multiWiFi[selectedWiFi].staticIP, multiWiFi[selectedWiFi].staticGW, multiWiFi[selectedWiFi].staticSN, dnsAddress);
+  } else {
+    WiFi.config(IPAddress((uint32_t)0), IPAddress((uint32_t)0), IPAddress((uint32_t)0));
+  }
+ }

ESP32 MAC fallback (fix Info tab showing 000000000000)

@@ (top of file)
+#ifdef ARDUINO_ARCH_ESP32
+#include <esp_mac.h>  // fallback MAC read from efuse
+#endif
@@ // generate module IDs must be done before AP setup
-escapedMac = WiFi.macAddress();
+escapedMac = WiFi.macAddress();
+#ifdef ARDUINO_ARCH_ESP32
+if (escapedMac == "00:00:00:00:00:00") { // fix: fallback to efuse MAC if WiFi not started
+  uint8_t m[6] = {0};
+  if (esp_read_mac(m, ESP_MAC_WIFI_STA) == ESP_OK) {
+    char buf[18];
+    sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", m[0], m[1], m[2], m[3], m[4], m[5]);
+    escapedMac = buf;
+  }
+}
+#endif
 escapedMac.replace(":", "");
 escapedMac.toLowerCase();

network.cpp

  1. Guard empty Wi-Fi list before accessing multiWiFi[0]
@@ int findWiFi(...)
-  if (multiWiFi.size() <= 1) {
-    DEBUG_PRINTF_P(PSTR("WiFi: Defaulf SSID (%s) used.\n"), multiWiFi[0].clientSSID);
-    return 0;
-  }
+  if (multiWiFi.size() <= 1) {
+    if (multiWiFi.empty()) return 0; // guard: handle empty list safely
+    DEBUG_PRINTF_P(PSTR("WiFi: Defaulf SSID (%s) used.\n"), multiWiFi[0].clientSSID);
+    return 0;
+  }
  1. Safe BSSID compare (both sides must exist & configured BSSID non-zero)
@@ for (size_t n = 0; n < multiWiFi.size(); n++)
-    bool foundBSSID = memcmp(multiWiFi[n].bssid, WiFi.BSSID(o), 6) == 0;
+    const uint8_t* _scanBSSID = WiFi.BSSID(o);
+    bool _cfgHasBSSID = false; for (int _i = 0; _i < 6; _i++) _cfgHasBSSID |= multiWiFi[n].bssid[_i];
+    bool foundBSSID = (_scanBSSID && _cfgHasBSSID) && memcmp(multiWiFi[n].bssid, _scanBSSID, 6) == 0; // guard: safe memcmp against nullptr/empty BSSID

Usermods I had more issues with usermods—the new toolchain’s linker was GC’ing/orphaning the old section-based registration. I switched registration to a ctor-based dynamic hook (no new sections) and kept legacy dtors for backward compatibility. I used the RF433 usermod as the example.

Modified um_manager.cpp:

#include "wled.h"
#include <assert.h>

/*
 * Registration and management utility for v2 usermods
 *
 * Discovery paths, in this order:
 *  1) Legacy dtors window: .dtors.tbl.usermods.0 ... .99 (older toolchains)
 *  2) Dynamic fallback: usermods call registerUsermod(Usermod*) from a ctor
 */

// -------- Legacy dtors window (keep for backward compatibility) --------
static Usermod * const _usermod_table_begin[0]
  __attribute__((section(".dtors.tbl.usermods.0"), unused)) = {};
static Usermod * const _usermod_table_end[0]
  __attribute__((section(".dtors.tbl.usermods.99"), unused)) = {};

struct UMSpan {
  Usermod* const* begin;
  Usermod* const* end;
};

static inline UMSpan reg_dtors_span() {
  UMSpan s{_usermod_table_begin, _usermod_table_end};
  return s;
}

// ----- Dynamic fallback: usermods can push themselves here at boot -----
static Usermod* g_dynMods[16];
static size_t   g_dynCnt = 0;

// Weak, so a stronger definition elsewhere (if any) wins.
// Usermods may call this from a constructor to guarantee registration.
extern "C" void registerUsermod(Usermod* m) __attribute__((weak));
extern "C" void registerUsermod(Usermod* m) {
  if (m && g_dynCnt < (sizeof(g_dynMods)/sizeof(g_dynMods[0]))) {
    g_dynMods[g_dynCnt++] = m;
  }
}

// ----- Common iteration helpers -----

// Accept any callable (incl. capturing lambdas/functors)
template<typename Fn>
static inline void forEachMod(Fn&& fn) {
  // 1) legacy dtors table
  {
    UMSpan s = reg_dtors_span();
    for (auto p = s.begin; p < s.end; ++p) {
      Usermod* m = *p;
      if (m) fn(m);
    }
  }
  // 2) dynamic list
  for (size_t i = 0; i < g_dynCnt; ++i) {
    if (g_dynMods[i]) fn(g_dynMods[i]);
  }
}

static inline size_t countMods() {
  size_t count = 0;
  // dtors window
  {
    UMSpan s = reg_dtors_span();
    count += (size_t)(s.end - s.begin);
  }
  // dynamic
  count += g_dynCnt;
  return count;
}

// --------- Usermod Manager methods (iterate via forEachMod) ---------

void UsermodManager::setup()             { forEachMod([](Usermod* m){ m->setup(); }); }
void UsermodManager::connected()         { forEachMod([](Usermod* m){ m->connected(); }); }
void UsermodManager::loop()              { forEachMod([](Usermod* m){ m->loop(); }); }
void UsermodManager::handleOverlayDraw() { forEachMod([](Usermod* m){ m->handleOverlayDraw(); }); }

void UsermodManager::appendConfigData(Print& dest) {
  forEachMod([&](Usermod* m){ m->appendConfigData(dest); });
}

bool UsermodManager::handleButton(uint8_t b) {
  bool overrideIO = false;
  forEachMod([&](Usermod* m){
    if (m->handleButton(b)) overrideIO = true;
  });
  return overrideIO;
}

bool UsermodManager::getUMData(um_data_t **data, uint8_t mod_id) {
  bool got = false;
  forEachMod([&](Usermod* m){
    if (got) return;
    if (mod_id > 0 && m->getId() != mod_id) return;
    if (m->getUMData(data)) got = true;
  });
  return got;
}

void UsermodManager::addToJsonState(JsonObject& obj) {
  forEachMod([&](Usermod* m){ m->addToJsonState(obj); });
}

void UsermodManager::addToJsonInfo(JsonObject& obj) {
  auto um_id_list = obj.createNestedArray("um");
  forEachMod([&](Usermod* m){
    um_id_list.add(m->getId());
    m->addToJsonInfo(obj);
  });
}

void UsermodManager::readFromJsonState(JsonObject& obj) {
  forEachMod([&](Usermod* m){ m->readFromJsonState(obj); });
}

void UsermodManager::addToConfig(JsonObject& obj) {
  forEachMod([&](Usermod* m){ m->addToConfig(obj); });
}

bool UsermodManager::readFromConfig(JsonObject& obj) {
  bool allComplete = true;
  forEachMod([&](Usermod* m){
    if (!m->readFromConfig(obj)) allComplete = false;
  });
  return allComplete;
}

#ifndef WLED_DISABLE_MQTT
void UsermodManager::onMqttConnect(bool sessionPresent) {
  forEachMod([&](Usermod* m){ m->onMqttConnect(sessionPresent); });
}

bool UsermodManager::onMqttMessage(char* topic, char* payload) {
  bool handled = false;
  forEachMod([&](Usermod* m){
    if (!handled && m->onMqttMessage(topic, payload)) handled = true;
  });
  return handled;
}
#endif // WLED_DISABLE_MQTT

#ifndef WLED_DISABLE_ESPNOW
bool UsermodManager::onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len) {
  bool handled = false;
  forEachMod([&](Usermod* m){
    if (!handled && m->onEspNowMessage(sender, payload, len)) handled = true;
  });
  return handled;
}
#endif // WLED_DISABLE_ESPNOW

void UsermodManager::onUpdateBegin(bool init) {
  forEachMod([&](Usermod* m){ m->onUpdateBegin(init); });
}

void UsermodManager::onStateChange(uint8_t mode) {
  forEachMod([&](Usermod* m){ m->onStateChange(mode); });
}

Usermod* UsermodManager::lookup(uint16_t mod_id) {
  Usermod* found = nullptr;
  forEachMod([&](Usermod* m){
    if (!found && m->getId() == mod_id) found = m;
  });
  return found;
}

size_t UsermodManager::getModCount() {
  return countMods();
}

/* Usermod v2 interface shim for oappend */
Print* Usermod::oappend_shim = nullptr;
void Usermod::appendConfigData(Print& settingsScript) {
  assert(!oappend_shim);
  oappend_shim = &settingsScript;
  this->appendConfigData();
  oappend_shim = nullptr;
}

At the end of usermod_v2_RF433.cpp I added:

// --- Registration via dynamic fallback (no custom sections) ---
static RF433Usermod usermod_v2_RF433;
REGISTER_USERMOD(usermod_v2_RF433);   // OK to keep for legacy dtors builds

extern "C" void registerUsermod(Usermod*) __attribute__((weak));

__attribute__((constructor, used))
static void __rf433_ctor_register(void) {
  if (registerUsermod) registerUsermod(&usermod_v2_RF433);
}

NeoPixelBus I also had issues with NeoPixelBus. At boot, IDF runs check_rmt_legacy_driver_conflict() and aborts if both the old (legacy) RMT driver and the new (“driver_ng” / v2) RMT driver are linked into firmware. I switched to Makuna/NeoPixelBus.git#CORE3 and made a small change:

--- a/src/internal/methods/ESP/ESP32/NeoEsp32RmtXMethod.h
+++ b/src/internal/methods/ESP/ESP32/NeoEsp32RmtXMethod.h
@@ -1,5 +1,7 @@
 #pragma once
+// Needed for ESP_* macros that take a log_tag
+#include "esp_log.h"
+static const char* TAG = "NeoEsp32RmtX";

And I added a temporary shim in wled00/bus_wrapper.h. Since ESP-IDF 5 switched to the new RMT “driver_v2,” Makuna renamed all of the “N” (legacy/driver_v1) variants to “X” (v2) under internal/methods/ESP/ESP32/*

// --- temporary shim for NeoPixelBus CORE3 / RMT driver_v2 ------------------
#if __has_include(<NeoPixelBus.h>)
  #define NeoEsp32RmtNWs2812xMethod  NeoEsp32RmtXWs2812xMethod
  #define NeoEsp32RmtNSk6812Method   NeoEsp32RmtXSk6812Method
  #define NeoEsp32RmtN400KbpsMethod  NeoEsp32RmtX400KbpsMethod
  #define NeoEsp32RmtNTm1814Method   NeoEsp32RmtXTm1814Method
  #define NeoEsp32RmtNTm1829Method   NeoEsp32RmtXTm1829Method
  #define NeoEsp32RmtNTm1914Method   NeoEsp32RmtXTm1914Method
  #define NeoEsp32RmtNApa106Method   NeoEsp32RmtXApa106Method
  #define NeoEsp32RmtNWs2805Method   NeoEsp32RmtXWs2805Method
#endif
// ---------------------------------------------------------------------------

sombree avatar Aug 25 '25 09:08 sombree

Thanks for helping with this @sombree

Could you please open a PR against the V5 branch and we can then pull in your fixes that way, maintaining attribution for your work

netmindz avatar Aug 28 '25 05:08 netmindz

@sombree - can you have a look at the commits I have made on this PR vs your changes please?

netmindz avatar Nov 08 '25 15:11 netmindz

It would be good to apply your V5 experience here @troyhacks

netmindz avatar Nov 08 '25 16:11 netmindz

NeoPixelBus I also had issues with NeoPixelBus. At boot, IDF runs check_rmt_legacy_driver_conflict() and aborts if both the old (legacy) RMT driver and the new (“driver_ng” / v2) RMT driver are linked into firmware.

This is a known incompatibility. Root Case: a new "ws2812 leds" driver in arduino-esp32, which pulls in the new RMT code that conflicts with any "legacy RMT" code. The solution is to disable the arduino driver (we don't need it) with the following build_flags, to prevent crashes at boot:

  -DESP32_ARDUINO_NO_RGB_BUILTIN ;; avoids RMT driver abort on startup "E (98) rmt(legacy): CONFLICT! driver_ng is not allowed to be used with the legacy driver"

Edit: done

softhack007 avatar Nov 18 '25 11:11 softhack007

// -------- Legacy dtors window (keep for backward compatibility) --------
static Usermod * const _usermod_table_begin[0]
  __attribute__((section(".dtors.tbl.usermods.0"), unused)) = {};

ouch 🤌 this looks ugly and fragile ... we should not mingle with linker sections, unless there is no other way.

@sombree @willmmiles did you check the gcc documentation for other solutions, like __attribute__((used)) ??

softhack007 avatar Nov 18 '25 12:11 softhack007

// -------- Legacy dtors window (keep for backward compatibility) --------
static Usermod * const _usermod_table_begin[0]
  __attribute__((section(".dtors.tbl.usermods.0"), unused)) = {};

ouch 🤌 this looks ugly and fragile ... we should not mingle with linker sections, unless there is no other way.

@sombree @willmmiles did you check the gcc documentation for other solutions, like __attribute__((used)) ??

As far as I'm aware, there isn't any other approach for constructing a static list across translation units at build time. This technique was called "Distributed Arrays" when formal language support was proposed. It's used in many places; an example in ESP-IDF is ESP_SYSTEM_INIT_FN. The key advantage is that it requires no RAM; the list exists entirely in code memory. It is my hope to leverage this technique for other static lists in the future, such as effects and bus drivers.

What's changed is that someone at Espressif realized that the ".dtors" section will typically never be called upon in an embedded system, and removed it from the linker map to save some space. I'd packed the table in the ".dtors" section for that reason, and also because it's sorted by the linker script, so an order could be enforced. Now that it's been removed, however, all that data is discarded.

For IDF >=v5.3, we'll need to add a linker fragment to embed the dynamic sections. We can keep the ".dtor.lst" name for compatibility with older systems.

willmmiles avatar Nov 19 '25 00:11 willmmiles

@coderabbitai review additionally, please update your previous review comments to match the latest source code.

softhack007 avatar Dec 01 '25 00:12 softhack007

@softhack007: I'll review the current state of the PR and update my previous review comments to reflect the latest changes in the codebase. This will include examining the ESP-IDF V5 compatibility updates, the fixes that have been applied, and ensuring my feedback is current and relevant.


🧠 Learnings used
Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with appropriate defined constants when those constants are meaningful in the context of the PR. For example, the hardcoded value 32 should be replaced with WLED_MAX_SEGNAME_LEN when it represents a segment name length limit. This improves code maintainability and reduces the risk of inconsistencies.

Learnt from: willmmiles
Repo: wled/WLED PR: 4890
File: lib/NeoESP32RmtHI/include/NeoEsp32RmtHIMethod.h:31-36
Timestamp: 2025-09-02T01:45:58.047Z
Learning: For the NeoEsp32RmtHI driver, RISC-V ESP32-C3 support is currently disabled via bus_wrapper.h rather than compile-time guards, as the maintainer willmmiles is working on resolving underlying nested interrupt issues and prefers to centralize the workaround in one location.

Learnt from: DedeHai
Repo: wled/WLED PR: 4798
File: wled00/FX.cpp:7531-7533
Timestamp: 2025-08-26T11:51:21.817Z
Learning: In WLED PR #4798, DedeHai confirmed that certain gamma-related calls in FX.cpp/FX_fcn.cpp/particle systems are intentional for effect-level shaping (e.g., brightness curves, TV sim, Pride 2015 pre-mix), distinct from final output gamma. Do not flag or remove these in future reviews; add comments when feasible to clarify intent.

Learnt from: DedeHai
Repo: wled/WLED PR: 4939
File: wled00/FX_fcn.cpp:1176-1187
Timestamp: 2025-09-16T18:08:42.848Z
Learning: In WLED finalizeInit() bus creation (wled00/FX_fcn.cpp), intentionally allowing memory overruns when bus configurations exceed MAX_LED_MEMORY is a deliberate design choice. The trade-off prioritizes creating buses with reduced LED counts over completely failing to create buses, which would cause no LED output and UI failures. This approach forces users to update configurations after migrating to version 0.16 while maintaining basic functionality.

Learnt from: willmmiles
Repo: wled/WLED PR: 4890
File: lib/NeoESP32RmtHI/include/NeoEsp32RmtHIMethod.h:173-180
Timestamp: 2025-09-02T01:56:43.841Z
Learning: willmmiles prefers to maintain consistency with upstream NeoPixelBus patterns (like unchecked malloc in construct() methods) rather than diverging until improvements are made upstream first, to minimize maintenance burden and keep the codebase aligned.

Learnt from: mval-sg
Repo: wled/WLED PR: 4876
File: wled00/xml.cpp:0-0
Timestamp: 2025-08-28T08:09:20.630Z
Learning: The WLED codebase has opportunities for refactoring hardcoded array bounds (like the "15" used for DMX channels) to use sizeof(array)/sizeof(array[0]) for more maintainable code, but such changes should be done consistently across the entire codebase in a dedicated refactoring effort.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with defined constants when meaningful constants exist in the codebase. For example, suggest replacing hardcoded "32" with WLED_MAX_SEGNAME_LEN if the context relates to segment name length limits.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, verify that file operations (especially file.open()) respect LittleFS filename limitations. Assume default WLED configuration with LittleFS default filename limit of 255 bytes. Do not assume extreme configuration values like WLED_MAX_SEGNAME_LEN = 512 which would not be standard configurations.

Learnt from: willmmiles
Repo: wled/WLED PR: 4939
File: wled00/FX_fcn.cpp:1183-1194
Timestamp: 2025-09-18T03:17:30.107Z
Learning: In WLED bus management code, dead code branches in error handling (like unreachable else breaks) are intentionally preserved to accommodate potential future API changes, even when currently unreachable.

Learnt from: willmmiles
Repo: wled/WLED PR: 4853
File: wled00/util.cpp:779-781
Timestamp: 2025-08-29T01:34:34.358Z
Learning: On ESP8266 systems, avoid adding no-op stub functions across translation units due to limited code memory constraints, as the compiler cannot inline away the function calls, resulting in wasteful memory usage.

Learnt from: willmmiles
Repo: wled/WLED PR: 4890
File: lib/NeoESP32RmtHI/src/NeoEsp32RmtHI.S:8-16
Timestamp: 2025-09-02T02:27:39.220Z
Learning: The ESP32 macro is defined when compiling code on all ESP32 variants (ESP32, ESP32-S2, ESP32-S3, ESP32-C3, etc.) in the Arduino framework, providing consistent library compatibility across the entire ESP32 family. For target-specific detection, CONFIG_IDF_TARGET_* macros should be used instead.

Learnt from: blazoncek
Repo: wled/WLED PR: 4482
File: wled00/udp.cpp:147-149
Timestamp: 2025-02-19T12:43:34.199Z
Learning: ESP8266 and ESP32 platforms have different maximum segment name lengths in WLED, which can cause truncation when syncing segment names between devices. This platform difference affects the user experience when using the segment name sync feature.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot] avatar Dec 01 '25 00:12 coderabbitai[bot]

@coderabbitai what changes would be needed when we want to switch from platformio to pioarduino as the main build engine of the V5 branch?

softhack007 avatar Dec 01 '25 00:12 softhack007

[!TIP] For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🌐 Web query:

pioarduino platform-espressif32 platformio ESP-IDF 5

💡 Result:

Short answer: Yes — PlatformIO's espressif32 platform supports ESP‑IDF v5.x (added across the 6.x platform releases), but the bundled Arduino core in PlatformIO often lags (Arduino-ESP32 builds included are based on older IDF versions). If you need Arduino on top of ESP‑IDF 5, use pioarduino / rebuild arduino-esp32 with the esp32-arduino-lib-builder (or pick a platform-espressif32 release that advertises the IDF v5.x you need).

Key points and practical steps

  • platform-espressif32 releases (6.4.0 → 6.10.0 etc.) add ESP‑IDF v5.x support (examples: v5.1.1 in 6.4.0, up to v5.4.0 in 6.10.0). Set the platform version in platformio.ini to the desired tag. [1]
  • The “Arduino” framework packaged by PlatformIO in those releases may be an older Arduino-ESP32 core (Arduino v2.x built on IDF v4.x). For pure ESP‑IDF projects use the platform directly; for Arduino-on-IDF‑5 you must either use pioarduino or rebuild Arduino static libraries with esp32-arduino-lib-builder targeting IDF‑5. [1][3][4]
  • Example platformio.ini to pick platform-espressif32 6.10.0 (ESP‑IDF v5.4):
    [env:esp32]
    platform = espressif32 @ 6.10.0
    board = esp32dev
    framework = espidf — or use framework = arduino if the bundled Arduino core meets your needs. [1]

Useful links

  • platform-espressif32 releases (shows IDF/Arduino versions per release). [1]
  • GitHub issue discussing Arduino‑ESP32 v3.0 / IDF‑5 support and pioarduino suggestion. [3]
  • PlatformIO community discussion about pioarduino / rebuilding Arduino libs. [4]

References [1] platformio/platform-espressif32 — Releases (GitHub).
[2] (PlatformIO / Espressif historical docs for PlatformIO + ESP‑IDF support).
[3] Issue: “Support Arduino ESP32 v3.0 based on ESP‑IDF v5.1” — platformio/platform-espressif32 (GitHub).
[4] PlatformIO Community thread: “Use of arduino-esp32 in platformio”.


🏁 Script executed:

#!/bin/bash
# Fetch information about the pioarduino platform repository
curl -s https://api.github.com/repos/pioarduino/platform-espressif32 | jq -r '.description, .homepage'

# Get the README to understand usage
curl -s https://raw.githubusercontent.com/pioarduino/platform-espressif32/main/README.md | head -100

Length of output: 3348


@softhack007: Based on my research, here are the key changes needed to switch from standard PlatformIO to pioarduino for the V5 branch:

Main Changes Required

1. Platform Declaration

Replace your current [esp32_idf_V5] platform configuration with pioarduino:

[esp32_idf_V5]
# Replace this:
# platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip

# With pioarduino stable (currently Arduino 3.3.4 + IDF 5.5.1):
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip

# OR for development/bleeding edge:
# platform = https://github.com/pioarduino/platform-espressif32.git#develop

2. Simplify platform_packages

Pioarduino provides pre-built Arduino libraries against ESP-IDF 5.x, so you can likely remove or simplify the custom platform_packages entries:

# You may be able to remove these since pioarduino includes them:
# platform_packages = 
#     platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.1.0
#     platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1

3. Keep Most Build Flags

Your existing build flags should remain compatible:

  • -DESP32_ARDUINO_NO_RGB_BUILTIN (still needed to avoid RMT conflicts)
  • -DWLED_USE_SHARED_RMT
  • Other WLED-specific flags

4. Library Dependencies

Review and potentially update library versions since pioarduino may have better compatibility:

  • AsyncWebServer/AsyncTCP: Check if pioarduino's included versions work, or keep your forks
  • NeoPixelBus: Your CORE3 branch should still work
  • FastLED: May need version verification

5. Potential Simplifications

With pioarduino, you might be able to remove:

  • The mbedtls_sha1_shim.cpp workaround (if pioarduino's AsyncWebServer already handles this)
  • Some conditional ESP-IDF version checks (if targeting only 5.x)

Benefits of Switching

  1. Pre-built Arduino libs: Properly compiled Arduino-ESP32 against ESP-IDF 5.x without manual building
  2. Community support: Active maintenance focused on IDF 5.x compatibility
  3. Simpler configuration: Less manual platform package management
  4. Up-to-date: Regular releases tracking ESP-IDF updates

Testing Strategy

  1. Start with a single environment (e.g., esp32dev)
  2. Verify compilation works
  3. Test runtime on hardware (WiFi, LED drivers, RMT, etc.)
  4. Gradually migrate other board variants
  5. Compare binary sizes and performance

Would you like me to examine specific sections of your current platformio.ini and propose concrete before/after configurations for the migration?


🧠 Learnings used
Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with appropriate defined constants when those constants are meaningful in the context of the PR. For example, the hardcoded value 32 should be replaced with WLED_MAX_SEGNAME_LEN when it represents a segment name length limit. This improves code maintainability and reduces the risk of inconsistencies.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with defined constants when meaningful constants exist in the codebase. For example, suggest replacing hardcoded "32" with WLED_MAX_SEGNAME_LEN if the context relates to segment name length limits.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, verify that file operations (especially file.open()) respect LittleFS filename limitations. Assume default WLED configuration with LittleFS default filename limit of 255 bytes. Do not assume extreme configuration values like WLED_MAX_SEGNAME_LEN = 512 which would not be standard configurations.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, file operations (especially file.open()) should be checked to ensure they respect LittleFS filename limitations. The default LittleFS filename limit is 255 bytes (LFS_NAME_MAX). Reviews should assume default WLED configuration defines and not extreme edge-case values (e.g., WLED_MAX_SEGNAME_LEN = 512 would not be standard). File paths should be validated to stay within the 255-byte limit.

Learnt from: mval-sg
Repo: wled/WLED PR: 4876
File: wled00/xml.cpp:0-0
Timestamp: 2025-08-28T08:09:20.630Z
Learning: The WLED codebase has opportunities for refactoring hardcoded array bounds (like the "15" used for DMX channels) to use sizeof(array)/sizeof(array[0]) for more maintainable code, but such changes should be done consistently across the entire codebase in a dedicated refactoring effort.

Learnt from: softhack007
Repo: wled/WLED PR: 5107
File: boards/adafruit_matrixportal_esp32s3.json:1-66
Timestamp: 2025-11-22T20:33:14.840Z
Learning: In WLED, board JSON files in the boards/ directory may reference partition files that don't exist or have slightly different names than actual files in tools/. This is intentional because platformio.ini or platformio_override.sample.ini explicitly override the partition file using the board_build.partitions setting, which takes precedence over the board JSON partition reference. This pattern exists in multiple local board definitions and should not be flagged as an issue.

Learnt from: DedeHai
Repo: wled/WLED PR: 4798
File: wled00/FX.cpp:7531-7533
Timestamp: 2025-08-26T11:51:21.817Z
Learning: In WLED PR #4798, DedeHai confirmed that certain gamma-related calls in FX.cpp/FX_fcn.cpp/particle systems are intentional for effect-level shaping (e.g., brightness curves, TV sim, Pride 2015 pre-mix), distinct from final output gamma. Do not flag or remove these in future reviews; add comments when feasible to clarify intent.

Learnt from: blazoncek
Repo: wled/WLED PR: 4482
File: wled00/udp.cpp:147-149
Timestamp: 2025-02-19T12:43:34.199Z
Learning: ESP8266 and ESP32 platforms have different maximum segment name lengths in WLED, which can cause truncation when syncing segment names between devices. This platform difference affects the user experience when using the segment name sync feature.

Learnt from: DedeHai
Repo: wled/WLED PR: 4939
File: wled00/FX_fcn.cpp:1176-1187
Timestamp: 2025-09-16T18:08:42.848Z
Learning: In WLED finalizeInit() bus creation (wled00/FX_fcn.cpp), intentionally allowing memory overruns when bus configurations exceed MAX_LED_MEMORY is a deliberate design choice. The trade-off prioritizes creating buses with reduced LED counts over completely failing to create buses, which would cause no LED output and UI failures. This approach forces users to update configurations after migrating to version 0.16 while maintaining basic functionality.

Learnt from: willmmiles
Repo: wled/WLED PR: 4890
File: lib/NeoESP32RmtHI/include/NeoEsp32RmtHIMethod.h:31-36
Timestamp: 2025-09-02T01:45:58.047Z
Learning: For the NeoEsp32RmtHI driver, RISC-V ESP32-C3 support is currently disabled via bus_wrapper.h rather than compile-time guards, as the maintainer willmmiles is working on resolving underlying nested interrupt issues and prefers to centralize the workaround in one location.

Learnt from: CR
Repo: wled/WLED PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-05T15:24:05.545Z
Learning: Applies to platformio.ini : Use platformio.ini as the single source of truth for hardware build targets and settings

coderabbitai[bot] avatar Dec 01 '25 00:12 coderabbitai[bot]

Something crazy is going on with platformio - since yesterday I get regular build errors on the V5 branch, that look like the one below. It seems that some "pioarduino" package sneaks into the platformio extension in VSCode, and confuses everything.

Additionally, short library hashes like https://github.com/Aircoookie/GifDecoder#bc3af18 randomly stop working, and the only solution seems to be to remove /Users/<me>/.platformio completely, then restart VSCode and let platformio install its files again. After a few restarts, library references are again fetched properly.

very strange .... @Jason2866 any ideas?


Processing esp32dev (board: esp32dev; platform: https://github.com/tasmota/platform-espressif32/releases/download/2025.08.30/platform-espressif32-2025.08.30.zip; framework: arduino)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Tool Manager: Installing https://github.com/pioarduino/scons/releases/download/4.8.1/scons-local-4.8.1.tar.gz
Downloading  [####################################]  100%
Unpacking  [####################################]  100%
Tool Manager: [email protected] has been installed!

[....]

CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (2025.8.30) > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - contrib-piohome @ 3.4.4 
 - framework-arduinoespressif32 @ 3.3.0+sha.9c2d265c 
 - tool-esptoolpy @ 5.0.2 
 - tool-mklittlefs @ 3.2.0 
 - toolchain-xtensa-esp-elf @ 13.2.0+20250707
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ strict
Found 38 compatible libraries
Scanning dependencies...
Dependency Graph
|-- AsyncTCP @ 3.4.6
|-- AnimatedGIF @ 1.4.7
|-- GifDecoder @ 1.1.0+sha.bc3af18
|-- esp_dmx @ 4.1.0+sha.ed12a29
|-- FastLED_no_fastled @ 3.7.1+sha.9ff26b9
|-- NeoPixelBus @ 2.9.0+sha.2f05279
|-- ESPAsyncWebServerWLED @ 2.4.2+sha.39b830c
|-- AsyncMqttClient @ 0.9.0
|-- QuickEspNow @ 0.8.1+sha.193e991
|-- ESPmDNS @ 3.3.0
|-- Wire @ 3.3.0
|-- Update @ 3.3.0
|-- ArduinoOTA @ 3.3.0
|-- EEPROM @ 3.3.0
|-- DNSServer @ 3.3.0
|-- Ethernet @ 3.3.0
|-- LittleFS @ 3.3.0
|-- SPI @ 3.3.0
|-- WiFi @ 3.3.0
|-- NeoESP32RmtHI
|-- ESP32 Async UDP @ 3.3.0
|-- WebServer @ 3.3.0
*** Applied include path shortening for 229 framework paths ***
*** Path length reduced from 32765 to ~11121 characters ***
*** Estimated savings: 21297 characters ***

*** While building `['C:\\ARDUINO_Work\\WLED_upstream_new_0.16\\.pio\\build\\esp32dev\\src\\wled_metadata.cpp.o']' from `['C:\\ARDUINO_Work\\WLED_upstream_new_0.16\\.pio\\build\\esp32dev\\src\\wled_metadata.cpp.o']': Don't know how to build from a source file with suffix `.o'.  Expected a suffix in this list: ['.c', '.m', '.C', '.cpp', '.cc', '.cxx', '.c++', '.C++', '.mm', '.s', '.asm', '.ASM', '.spp', '.SPP', '.sx', '.S'].
File "C:\Users\frank\.platformio\platforms\espressif32\builder\frameworks\arduino.py", line 774, in apply_include_shortening
================================================================================== [FAILED] Took 7.05 seconds ==================================================================================

The other thing that looks like a "pioarduino" inteference is this diff that re-appears regularly

image

The "short hash problem" (mentioned above) looks like this

Resolving esp32dev dependencies...
Library Manager: Installing esp32async/AsyncTCP @ 3.4.6
Unpacking 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
Library Manager: [email protected] has been installed!
Library Manager: Installing bitbank2/AnimatedGIF @ ^1.4.7
Unpacking 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
Library Manager: [email protected] has been installed!
Library Manager: Installing git+https://github.com/Aircoookie/GifDecoder#bc3af18
git version 2.52.0.windows.1
Initialized empty Git repository in C:/Users/frank/.platformio/.cache/tmp/pkg-installing-wepq3hlq/.git/
fatal: couldn't find remote ref bc3af18

VCSBaseException: VCS: Could not process command ['git', 'fetch', '--depth=1', 'origin', 'bc3af18']

deleting the complete .platformio home folder plus deleting .pio folder in the workspace, then restarting VSCode solves this problem, but its still mysterious what goes on.

softhack007 avatar Dec 01 '25 12:12 softhack007

@dedehai next build error is more or less the complete GetChipID functionality. I'll temporarily disable it until we find a solution.

you will most likely run into problem when building V5 on your own PC - see https://github.com/wled/WLED/pull/4838#issuecomment-3596337978 FYI ;-)

wled00/util.cpp: In function 'String computeSHA1(const String&)':
wled00/util.cpp:1145:5: error: 'mbedtls_sha1_starts_ret' was not declared in this scope; did you mean 'mbedtls_sha1_starts'?
 1145 |     mbedtls_sha1_starts_ret(&ctx);
      |     ^~~~~~~~~~~~~~~~~~~~~~~
      |     mbedtls_sha1_starts
Compiling .pio/build/esp32dev/src/wled_eeprom.cpp.o
wled00/util.cpp:1146:5: error: 'mbedtls_sha1_update_ret' was not declared in this scope; did you mean 'mbedtls_sha1_update'?
 1146 |     mbedtls_sha1_update_ret(&ctx, (const unsigned char*)input.c_str(), input.length());
      |     ^~~~~~~~~~~~~~~~~~~~~~~
      |     mbedtls_sha1_update
Compiling .pio/build/esp32dev/src/wled_main.cpp.o
wled00/util.cpp:1147:5: error: 'mbedtls_sha1_finish_ret' was not declared in this scope; did you mean 'mbedtls_sha1_finish'?
 1147 |     mbedtls_sha1_finish_ret(&ctx, shaResult);
      |     ^~~~~~~~~~~~~~~~~~~~~~~
      |     mbedtls_sha1_finish
wled00/util.cpp: In function 'String generateDeviceFingerprint()':
wled00/util.cpp:1165:3: error: 'esp_chip_info_t' was not declared in this scope
 1165 |   esp_chip_info_t chip_info;
      |   ^~~~~~~~~~~~~~~
wled00/util.cpp:1166:18: error: 'chip_info' was not declared in this scope
 1166 |   esp_chip_info(&chip_info);
      |                  ^~~~~~~~~
wled00/util.cpp:1166:3: error: 'esp_chip_info' was not declared in this scope
 1166 |   esp_chip_info(&chip_info);
      |   ^~~~~~~~~~~~~
Compiling .pio/build/esp32dev/src/wled_math.cpp.o
wled00/util.cpp:1167:3: error: 'esp_efuse_mac_get_default' was not declared in this scope
 1167 |   esp_efuse_mac_get_default((uint8_t*)fp);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~
wled00/util.cpp:1177:40: warning: 'ADC_ATTEN_DB_11' is deprecated [-Wdeprecated-declarations]
 1177 |   esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, BIT_WIDTH, 1100, &ch);
      |                                        ^~~~~~~~~~~~~~~
In file included from /home/runner/.platformio/packages/framework-arduinoespressif32/tools/esp32-arduino-libs/esp32/include/esp_adc/deprecated/include/esp_adc_cal.h:12:
/home/runner/.platformio/packages/framework-arduinoespressif32/tools/esp32-arduino-libs/esp32/include/hal/include/hal/adc_types.h:51:5: note: declared here
   51 |     ADC_ATTEN_DB_11 __attribute__((deprecated)) = ADC_ATTEN_DB_12,  ///<This is deprecated, it behaves the same as `ADC_ATTEN_DB_12`
      |     ^~~~~~~~~~~~~~~
*** [.pio/build/esp32dev/src/util.cpp.o] Error 1

softhack007 avatar Dec 01 '25 14:12 softhack007

@willmmiles I'm struggling to disable all "Usermod CI" builds - no matter what I do, the "gather environments" task will add ~100 extra builds for usermods. Do you have an idea how to end that "noise" and stop wasting build time?

softhack007 avatar Dec 01 '25 15:12 softhack007

@softhack007 V5 will potentially run into quite a lot of issues regarding IDF core functions, a lot of stuff got overhauled, mostly for the better but still code will need to be re-written and tested. For example the whole x_malloc() functions. I see many potential pitfalls but once its all done it should hopefully run a lot more stable.

DedeHai avatar Dec 01 '25 15:12 DedeHai

Something crazy is going on with platformio - since yesterday I get regular build errors on the V5 branch, that look like the one below. It seems that some "pioarduino" package sneaks into the platformio extension in VSCode, and confuses everything.

Additionally, short library hashes like https://github.com/Aircoookie/GifDecoder#bc3af18 randomly stop working, and the only solution seems to be to remove /Users/<me>/.platformio completely, then restart VSCode and let platformio install its files again. After a few restarts, library references are again fetched properly.

very strange .... @Jason2866 any ideas?

Processing esp32dev (board: esp32dev; platform: https://github.com/tasmota/platform-espressif32/releases/download/2025.08.30/platform-espressif32-2025.08.30.zip; framework: arduino)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Tool Manager: Installing https://github.com/pioarduino/scons/releases/download/4.8.1/scons-local-4.8.1.tar.gz
Downloading  [####################################]  100%
Unpacking  [####################################]  100%
Tool Manager: [email protected] has been installed!

[....]

CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (2025.8.30) > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - contrib-piohome @ 3.4.4 
 - framework-arduinoespressif32 @ 3.3.0+sha.9c2d265c 
 - tool-esptoolpy @ 5.0.2 
 - tool-mklittlefs @ 3.2.0 
 - toolchain-xtensa-esp-elf @ 13.2.0+20250707
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ strict
Found 38 compatible libraries
Scanning dependencies...
Dependency Graph
|-- AsyncTCP @ 3.4.6
|-- AnimatedGIF @ 1.4.7
|-- GifDecoder @ 1.1.0+sha.bc3af18
|-- esp_dmx @ 4.1.0+sha.ed12a29
|-- FastLED_no_fastled @ 3.7.1+sha.9ff26b9
|-- NeoPixelBus @ 2.9.0+sha.2f05279
|-- ESPAsyncWebServerWLED @ 2.4.2+sha.39b830c
|-- AsyncMqttClient @ 0.9.0
|-- QuickEspNow @ 0.8.1+sha.193e991
|-- ESPmDNS @ 3.3.0
|-- Wire @ 3.3.0
|-- Update @ 3.3.0
|-- ArduinoOTA @ 3.3.0
|-- EEPROM @ 3.3.0
|-- DNSServer @ 3.3.0
|-- Ethernet @ 3.3.0
|-- LittleFS @ 3.3.0
|-- SPI @ 3.3.0
|-- WiFi @ 3.3.0
|-- NeoESP32RmtHI
|-- ESP32 Async UDP @ 3.3.0
|-- WebServer @ 3.3.0
*** Applied include path shortening for 229 framework paths ***
*** Path length reduced from 32765 to ~11121 characters ***
*** Estimated savings: 21297 characters ***

*** While building `['C:\\ARDUINO_Work\\WLED_upstream_new_0.16\\.pio\\build\\esp32dev\\src\\wled_metadata.cpp.o']' from `['C:\\ARDUINO_Work\\WLED_upstream_new_0.16\\.pio\\build\\esp32dev\\src\\wled_metadata.cpp.o']': Don't know how to build from a source file with suffix `.o'.  Expected a suffix in this list: ['.c', '.m', '.C', '.cpp', '.cc', '.cxx', '.c++', '.C++', '.mm', '.s', '.asm', '.ASM', '.spp', '.SPP', '.sx', '.S'].
File "C:\Users\frank\.platformio\platforms\espressif32\builder\frameworks\arduino.py", line 774, in apply_include_shortening
================================================================================== [FAILED] Took 7.05 seconds ==================================================================================

The other thing that looks like a "pioarduino" inteference is this diff that re-appears regularly

image The "short hash problem" (mentioned above) looks like this
Resolving esp32dev dependencies...
Library Manager: Installing esp32async/AsyncTCP @ 3.4.6
Unpacking 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
Library Manager: [email protected] has been installed!
Library Manager: Installing bitbank2/AnimatedGIF @ ^1.4.7
Unpacking 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
Library Manager: [email protected] has been installed!
Library Manager: Installing git+https://github.com/Aircoookie/GifDecoder#bc3af18
git version 2.52.0.windows.1
Initialized empty Git repository in C:/Users/frank/.platformio/.cache/tmp/pkg-installing-wepq3hlq/.git/
fatal: couldn't find remote ref bc3af18

VCSBaseException: VCS: Could not process command ['git', 'fetch', '--depth=1', 'origin', 'bc3af18']

deleting the complete .platformio home folder plus deleting .pio folder in the workspace, then restarting VSCode solves this problem, but its still mysterious what goes on.

Short SHA are not supported anymore. Generated weird issues sometimes. Anyways faster is to provide a github zip reference. For example OMG is doing this way https://github.com/1technophile/OpenMQTTGateway/blob/development/platformio.ini

Jason2866 avatar Dec 01 '25 15:12 Jason2866

@softhack007 V5 will potentially run into quite a lot of issues regarding IDF core functions, a lot of stuff got overhauled, mostly for the better but still code will need to be re-written and tested. For example the whole x_malloc() functions. I see many potential pitfalls but once its all done it should hopefully run a lot more stable.

It exists as we want anyone submitting a PR that relates to a usermod to actually check their usermod builds for all chip types and doesn't have any undocumented nasty interdependencies, so it's not ok to just have a * build for all usermods for esp32 only.

It's triggering because of the change I made for the name clash of network, but to be honest it would be better if there was a better way to handle that than my rather ugly sledgehammer approach to rename which both affects the core of WLED and breaking change in many usermods.

We can keep disable it for this branch. It should only really be advice now for pulls from other repos not out own branch building

netmindz avatar Dec 01 '25 16:12 netmindz

@coderabbitai, please review this PR, and also update any previous review comments to reflect the latest source code.

Additionally, i would like you to create two summary lists:

  • analyse the build logs of esp32dev and esp32c3dev for compilation warnings, and summarize how and where we can improve/modernize the code

  • scan over the "usermod CI" build logs, and try to find generic patterns that lead to compilation errors. Summarize the most frequent errors and provide suggestions for makeing usermods compatible with the V5 esp-idf and v3 arduino-esp32 framework.

softhack007 avatar Dec 01 '25 17:12 softhack007

[!TIP] For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch the latest workflow runs for PR #4838
gh pr view 4838 --repo wled/WLED --json number,headRefName,headRepository

# Get recent workflow runs for this PR branch
gh run list --repo wled/WLED --branch V5 --limit 5 --json databaseId,name,conclusion,createdAt,status

# Get the most recent completed run
LATEST_RUN=$(gh run list --repo wled/WLED --branch V5 --limit 1 --json databaseId --jq '.[0].databaseId')
echo "Latest run ID: $LATEST_RUN"

# List jobs in the latest run
gh run view $LATEST_RUN --repo wled/WLED --json jobs --jq '.jobs[] | {id: .databaseId, name: .name, conclusion: .conclusion}'

Length of output: 1521


🏁 Script executed:

#!/bin/bash
# Get the latest workflow run ID for the V5 branch
LATEST_RUN=$(gh run list --repo wled/WLED --branch V5 --limit 1 --json databaseId --jq '.[0].databaseId')

if [ -z "$LATEST_RUN" ] || [ "$LATEST_RUN" = "null" ]; then
  echo "No workflow runs found for V5 branch"
  exit 1
fi

echo "Fetching logs for run ID: $LATEST_RUN"

# Download logs for esp32dev and esp32c3dev builds
gh run view $LATEST_RUN --repo wled/WLED --log 2>&1 | head -5000 > /tmp/workflow_logs.txt

# Try to extract esp32dev specific logs
echo "=== Searching for esp32dev warnings ==="
grep -i "esp32dev" /tmp/workflow_logs.txt | head -50

echo ""
echo "=== Searching for compilation warnings ==="
grep -E "(warning:|deprecated)" /tmp/workflow_logs.txt | head -100

Length of output: 30750


🏁 Script executed:

#!/bin/bash
# Get more detailed information about workflow jobs
LATEST_RUN=$(gh run list --repo wled/WLED --branch V5 --limit 1 --json databaseId --jq '.[0].databaseId')

if [ -z "$LATEST_RUN" ] || [ "$LATEST_RUN" = "null" ]; then
  echo "No workflow runs found"
  exit 1
fi

# Get job details
echo "=== Job Details for Run $LATEST_RUN ==="
gh run view $LATEST_RUN --repo wled/WLED --json jobs --jq '.jobs[] | select(.name | contains("esp32dev") or contains("esp32c3dev") or contains("usermod")) | {name: .name, conclusion: .conclusion, id: .databaseId}' | head -50

# Try to get logs for specific jobs
echo ""
echo "=== Attempting to fetch build logs ==="
gh run view $LATEST_RUN --repo wled/WLED --log-failed 2>&1 | grep -A 5 -B 5 -E "(warning|error|deprecated|ADC_ATTEN|mbedtls)" | head -200

Length of output: 469


🏁 Script executed:

#!/bin/bash
# Search for common warning patterns in the codebase that would appear in builds
echo "=== Searching codebase for deprecated API usage ==="

# Check for deprecated ADC_ATTEN_DB_11 usage
echo "1. ADC_ATTEN_DB_11 (deprecated in ESP-IDF 5):"
rg "ADC_ATTEN_DB_11" --type cpp -n -C 1

echo ""
echo "2. mbedtls deprecated functions:"
rg "mbedtls_sha1_(starts|update|finish)_ret" --type cpp -n -C 1

echo ""
echo "3. esp_chip_info usage:"
rg "esp_chip_info" --type cpp -n -C 1

echo ""
echo "4. Legacy malloc functions:"
rg "heap_caps_malloc" --type cpp -n -C 1 | head -30

Length of output: 4161


🏁 Script executed:

#!/bin/bash
# Analyze usermod files for common V5 incompatibility patterns
echo "=== Analyzing usermods for V5 compatibility issues ==="

# Check for Network class usage (renamed to WLEDNetwork)
echo "1. Old Network class references in usermods:"
rg "Network\.(localIP|isConnected|subnetMask)" usermods/ --type cpp -n | head -30

echo ""
echo "2. Legacy LEDC API usage in usermods:"
rg "ledcSetup|ledcAttachPin|ledcDetachPin" usermods/ --type cpp -n | head -30

echo ""
echo "3. ESP-IDF version guards in usermods:"
rg "ESP_IDF_VERSION|ESP_IDF_VERSION_MAJOR" usermods/ --type cpp -n -C 1 | head -40

echo ""
echo "4. Usermod registration patterns:"
rg "REGISTER_USERMOD|__attribute__.*section.*usermod" usermods/ --type cpp -n | head -30

Length of output: 7156


🏁 Script executed:

#!/bin/bash
# Get the failed Usermod CI run
USERMOD_RUN=$(gh run list --repo wled/WLED --branch V5 --workflow="Usermod CI" --limit 1 --json databaseId --jq '.[0].databaseId')

if [ -z "$USERMOD_RUN" ] || [ "$USERMOD_RUN" = "null" ]; then
  echo "No usermod CI runs found"
  exit 1
fi

echo "=== Usermod CI Run ID: $USERMOD_RUN ==="

# Get job details from the usermod CI
gh run view $USERMOD_RUN --repo wled/WLED --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusion}' | head -100

Length of output: 8592


🏁 Script executed:

#!/bin/bash
# Fetch failed usermod CI logs
USERMOD_RUN=$(gh run list --repo wled/WLED --branch V5 --workflow="Usermod CI" --limit 1 --json databaseId --jq '.[0].databaseId')

if [ -z "$USERMOD_RUN" ] || [ "$USERMOD_RUN" = "null" ]; then
  echo "No usermod CI runs found"
  exit 1
fi

# Get logs and search for common error patterns
echo "=== Fetching Usermod CI logs for error patterns ==="
gh run view $USERMOD_RUN --repo wled/WLED --log-failed 2>&1 | grep -E "(error:|Network\.|ledcSetup|ledcAttachPin|undefined reference|cannot find)" | head -150

Length of output: 31388


🏁 Script executed:

#!/bin/bash
# Analyze usermod CI logs more comprehensively
USERMOD_RUN=$(gh run list --repo wled/WLED --branch V5 --workflow="Usermod CI" --limit 1 --json databaseId --jq '.[0].databaseId')

if [ -z "$USERMOD_RUN" ] || [ "$USERMOD_RUN" = "null" ]; then
  echo "No usermod CI runs found"
  exit 1
fi

echo "=== Analyzing common usermod build failures ==="
# Extract full log and analyze
gh run view $USERMOD_RUN --repo wled/WLED --log 2>&1 > /tmp/usermod_logs.txt

# Count and categorize errors
echo ""
echo "Error Pattern: Old Network class usage"
grep -c "Network\." /tmp/usermod_logs.txt || echo "0"

echo ""
echo "Error Pattern: LEDC API issues"
grep -c "ledcSetup\|ledcAttachPin\|ledcDetach" /tmp/usermod_logs.txt || echo "0"

echo ""
echo "Error Pattern: mbedtls SHA1 issues"
grep -c "mbedtls_sha1.*undefined\|mbedtls_sha1.*error" /tmp/usermod_logs.txt || echo "0"

echo ""
echo "=== Sample of actual errors from usermod builds ==="
grep -B 2 "error:" /tmp/usermod_logs.txt | head -100

Length of output: 14151


🏁 Script executed:

#!/bin/bash
# Search for specific usermod compilation errors in the repo
echo "=== Checking specific usermods for known V5 issues ==="

# Check audio reactive usermod (known to have issues)
echo "1. Audio Reactive usermod I2S compatibility:"
rg "i2s_driver_install|i2s_set_pin|I2S_MODE" usermods/audioreactive/ --type cpp -n -C 2 | head -40

echo ""
echo "2. PWM usermods LEDC compatibility:"
rg "ledcSetup|ledcWrite|ledcAttachPin" usermods/pwm_outputs/ usermods/PWM_fan/ --type cpp -n -C 2

echo ""
echo "3. Network references in usermods:"
rg "\\bNetwork\\." usermods/ --type cpp -n | grep -v "WLEDNetwork" | head -20

Length of output: 5393


@softhack007: I've completed the analysis of the build logs. Here are the two requested summary lists:

📊 Summary 1: Main Build Warnings Analysis (esp32dev/esp32c3dev)

Compilation Warnings Found & Modernization Recommendations:

1. C++20 Lambda Capture Deprecation ⚠️ (Most frequent)

  • Location: wled00/src/dependencies/espalexa/Espalexa.h lines 254, 257, 268
  • Issue: Implicit capture of this via [=] is deprecated in C++20
  • Fix: Replace [=] with [this] or [=, this] explicitly
// Change from:
server->on(..., [=](AsyncWebServerRequest *request) { ... });
// To:
server->on(..., [this](AsyncWebServerRequest *request) { ... });

2. Deprecated Enum Arithmetic ⚠️

  • Location: wled00/const.h:64
  • Issue: Arithmetic between ledc_channel_t and ledc_mode_t enums
  • Fix: Cast to int before arithmetic operations:
// Instead of mixing enum types:
#define WLED_PWM_CHANNEL (LEDC_CHANNEL_0 + LEDC_LOW_SPEED_MODE)
// Use explicit casting:
#define WLED_PWM_CHANNEL ((int)LEDC_CHANNEL_0 + (int)LEDC_LOW_SPEED_MODE)

3. Legacy ADC Driver Deprecation ⚠️

  • Location: wled00/util.cpp:1179
  • Issue: ADC_ATTEN_DB_11 is deprecated (also in audioreactive usermod)
  • Fix: Replace with ADC_ATTEN_DB_12:
// Change:
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, BIT_WIDTH, 1100, &ch);
// To:
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, BIT_WIDTH, 1100, &ch);

4. Deprecated mbedtls SHA1 Functions ⚠️

  • Location: wled00/util.cpp:1147-1149
  • Issue: mbedtls_sha1_*_ret functions removed in ESP-IDF 5.2+
  • Fix: Already addressed with mbedtls_sha1_shim.cpp wrapper ✅

5. NetworkUDP::flush() Deprecation ⚠️

  • Location: wled00/src/dependencies/espalexa/Espalexa.h:382
  • Issue: flush() deprecated, should use clear()
  • Fix:
// Change:
udp.flush();
// To:
udp.clear();

6. Deprecated Header Paths ⚠️

  • Issue: #include <freertos/xtensa_context.h> moved
  • Fix: Use #include <xtensa_context.h> directly

7. Legacy I2S/DAC Driver Warnings

  • Location: Various (included via dependencies)
  • Issue: Legacy driver deprecation warnings for ADC/DAC/I2S
  • Recommendation: Not urgent for core WLED, but audioreactive usermod will need migration to new drivers

📋 Summary 2: Usermod CI Build Errors - Common Patterns & Fixes

Error Pattern 1: MQTT Disabled (30+ usermod failures)

  • Example Usermods: Si7021_MQTT_HA, sensors_to_mqtt
  • Root Cause: platformio.ini disables MQTT with -D WLED_DISABLE_MQTT for V5 builds
  • Error Messages:
    error: #error "This user mod requires MQTT to be enabled."
    error: 'mqtt' was not declared in this scope
    error: 'mqttDeviceTopic' was not declared in this scope
    
  • Fix for Usermod Authors:
    #ifndef WLED_DISABLE_MQTT
      // MQTT-dependent code here
    #else
      #warning "This usermod requires MQTT support - skipping compilation"
    #endif
    

Error Pattern 2: Legacy LEDC API (40+ failures)

  • Example Usermods: pwm_outputs, PWM_fan (partially fixed)
  • Root Cause: ledcSetup() and ledcAttachPin() APIs changed/removed in Arduino-ESP32 v3
  • Error Messages:
    error: 'ledcSetup' was not declared in this scope; did you mean 'ledc_stop'?
    error: 'ledcAttachPin' was not declared in this scope; did you mean 'ledcAttach'?
    
  • Fix for Usermod Authors (see PWM_fan.cpp for working example):
    #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
      // New API: single call, returns success
      ledcAttach(pin, freq, resolution);
    #else
      // Legacy API: two separate calls
      ledcSetup(channel, freq, resolution);
      ledcAttachPin(pin, channel);
    #endif
    

Error Pattern 3: Arduino Network Class Collision (5000+ occurrences)

  • Root Cause: Arduino-ESP32 v3 introduced Network.h library that conflicts with WLED's custom WLEDNetwork class
  • Error Pattern: Compiler pulls in wrong Network.h header
  • Fix for Usermod Authors:
    // Change all references from:
    Network.localIP()
    Network.isConnected()
    Network.subnetMask()
    
    // To:
    WLEDNetwork.localIP()
    WLEDNetwork.isConnected()
    WLEDNetwork.subnetMask()
    
  • Still Broken: udp_name_sync usermod needs updating

Error Pattern 4: NeoESP32RmtHI Linker Errors (ESP32-S2)

  • Root Cause: NeoESP32RmtHI library disabled for V5 (RMT driver conflicts)
  • Error: undefined reference to 'NeoEsp32RmtMethodIsr'
  • Status: Library intentionally disabled in platformio.ini via lib_ignore
  • Recommendation: Use standard NeoPixelBus RMT methods (NeoEsp32RmtX* instead)

Error Pattern 5: esp_idf_size Tool Arguments

  • Error: esp_idf_size: error: unrecognized arguments: --ng
  • Root Cause: PlatformIO/IDF tooling version mismatch
  • Impact: Doesn't prevent builds, just fails size reporting
  • Status: Known issue with Tasmota platform package

Error Pattern 6: I2S Driver API Changes (audioreactive usermod)

  • Root Cause: I2S driver completely reworked in ESP-IDF 5
  • Functions Changed:
    • i2s_driver_install() → new i2s_new_channel() API
    • i2s_set_pin() → integrated into channel config
    • I2S_MODE_* flags changed
  • Status: Audioreactive usermod disabled for V5 until migration complete
  • Reference: ESP-IDF migration guide needed

🔧 General Recommendations for Usermod V5 Compatibility:

  1. Add ESP-IDF version guards for all hardware APIs:

    #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
      // V5-specific code
    #else
      // V4 legacy code
    #endif
    
  2. Use new Arduino-ESP32 v3 APIs:

    • LEDC: ledcAttach() instead of ledcSetup() + ledcAttachPin()
    • LEDC: ledcDetach() instead of ledcDetachPin()
  3. Update Network class references to WLEDNetwork

  4. Handle MQTT being optional with #ifndef WLED_DISABLE_MQTT guards

  5. Test on all chip variants (ESP32, S2, S3, C3) as APIs differ

  6. Avoid deprecated constants:

    • ADC_ATTEN_DB_11ADC_ATTEN_DB_12
    • Consider I2S legacy driver warnings

Would you like me to create a detailed migration guide document or open tracking issues for the most critical usermod updates?


🧠 Learnings used
Learnt from: Jason2866
Repo: wled/WLED PR: 4838
File: requirements.txt:2-2
Timestamp: 2025-12-01T16:13:06.566Z
Learning: Python 3.13 is supported by ESP-IDF 5.x and PlatformIO (any version including 6.1.18+), contrary to some incomplete documentation. This was confirmed by project maintainer Jason2866 in the WLED repository.

Learnt from: softhack007
Repo: wled/WLED PR: 5107
File: boards/adafruit_matrixportal_esp32s3.json:1-66
Timestamp: 2025-11-22T20:33:14.840Z
Learning: In WLED, board JSON files in the boards/ directory may reference partition files that don't exist or have slightly different names than actual files in tools/. This is intentional because platformio.ini or platformio_override.sample.ini explicitly override the partition file using the board_build.partitions setting, which takes precedence over the board JSON partition reference. This pattern exists in multiple local board definitions and should not be flagged as an issue.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with appropriate defined constants when those constants are meaningful in the context of the PR. For example, the hardcoded value 32 should be replaced with WLED_MAX_SEGNAME_LEN when it represents a segment name length limit. This improves code maintainability and reduces the risk of inconsistencies.

Learnt from: DedeHai
Repo: wled/WLED PR: 4939
File: wled00/FX_fcn.cpp:1176-1187
Timestamp: 2025-09-16T18:08:42.848Z
Learning: In WLED finalizeInit() bus creation (wled00/FX_fcn.cpp), intentionally allowing memory overruns when bus configurations exceed MAX_LED_MEMORY is a deliberate design choice. The trade-off prioritizes creating buses with reduced LED counts over completely failing to create buses, which would cause no LED output and UI failures. This approach forces users to update configurations after migrating to version 0.16 while maintaining basic functionality.

Learnt from: DedeHai
Repo: wled/WLED PR: 4798
File: wled00/FX.cpp:7531-7533
Timestamp: 2025-08-26T11:51:21.817Z
Learning: In WLED PR #4798, DedeHai confirmed that certain gamma-related calls in FX.cpp/FX_fcn.cpp/particle systems are intentional for effect-level shaping (e.g., brightness curves, TV sim, Pride 2015 pre-mix), distinct from final output gamma. Do not flag or remove these in future reviews; add comments when feasible to clarify intent.

Learnt from: mval-sg
Repo: wled/WLED PR: 4876
File: wled00/xml.cpp:0-0
Timestamp: 2025-08-28T08:09:20.630Z
Learning: The WLED codebase has opportunities for refactoring hardcoded array bounds (like the "15" used for DMX channels) to use sizeof(array)/sizeof(array[0]) for more maintainable code, but such changes should be done consistently across the entire codebase in a dedicated refactoring effort.

Learnt from: blazoncek
Repo: wled/WLED PR: 5140
File: wled00/data/settings_time.htm:66-76
Timestamp: 2025-12-01T07:01:16.913Z
Learning: In WLED PR #5134, the fix for macros being initialized with the enable bit set only handles new configurations, not existing ones. If there is a bug in timer/macro handling code (e.g., in settings_time.htm), it must be fixed to work correctly for existing configurations as well.

coderabbitai[bot] avatar Dec 01 '25 17:12 coderabbitai[bot]

ok guys, that's it for today from my side 😅

  • C6 branch and V5 are based on the latest main
  • C6 compiles, but not tested
  • unfortunately, PR #5114 might not be 100% compatible anymore, because @karan-vk has tried to use the I2S NPB driver as a cover/cloak for the bitbang driver, while i've tried to make C3 and C6 use the same RMT drivers, and I2S code disabled. The problem is, my changes are purely "it compiles", so possibly we should keep the door open on C6 to use the bitbang driver in case RMT has problems on the board.
  • I've added the recommended build flag to switch off the arduino ws2812 driver, so hopefully no bootloop crashes due to RMT conflicts anymore. This also implies that we are not forced any more to use neither a totally different version of FastLED, nor my old fastled_no_fastled fork. In fact, the minimum would be fastled 3.7.1, because older versions don't compile with gcc8 and above.
  • FastLED: as we don't need the fastled led output driver, we might be able to go back to an older release, to stay closer to the fastled behaviour in main

I think we should follow the recommendation from json8266:

  • use the newest platform
  • also check this
  • replace short repo hashes with long hashes, and maybe use ".zip" references for dependencies

Edit: don't forget to look through the list created by our rabbit. AI's are still "Often-Wrong" but some recommendation look good to me.

softhack007 avatar Dec 01 '25 17:12 softhack007