Skip to content

Add experimental ESP32-C5 support with WiFi 6 dual-band#5354

Draft
jonny190 wants to merge 1 commit intowled:mainfrom
jonny190:ESP32-C5
Draft

Add experimental ESP32-C5 support with WiFi 6 dual-band#5354
jonny190 wants to merge 1 commit intowled:mainfrom
jonny190:ESP32-C5

Conversation

@jonny190
Copy link

@jonny190 jonny190 commented Feb 6, 2026

  • Add CONFIG_IDF_TARGET_ESP32C5 conditionals alongside ESP32-C3
  • Use bit-bang LED output (RMT legacy API conflicts with IDF 5.x)
  • Add IDF 5.x API compatibility (LEDC, mbedtls, ADC)
  • Fix Network namespace collision with Arduino-ESP32 v3.x
  • Prefer 5GHz WiFi connection for hidden SSIDs
  • Add WiFi band indicator to info API and UI
  • Exclude C5 from I2S parallel output, touch sensors, analog mic
  • Add chip ID verification for OTA updates

ESP32-C5 features: WiFi 6 dual-band (2.4GHz + 5GHz), RISC-V single core, 240MHz, 2 RMT channels. Requires pioarduino platform fork.

Summary by CodeRabbit

  • New Features

    • Added support for ESP32-C5 microcontroller variant
    • WiFi band frequency information now displayed in device details panel
  • Improvements

    • Optimized frame timing configurations for ESP32-C5 performance
    • Enhanced WiFi 5GHz connection handling for ESP32-C5
    • Improved device fingerprinting compatibility across firmware versions
  • Known Limitations

    • OTA firmware updates not yet supported for ESP32-C5

- Add CONFIG_IDF_TARGET_ESP32C5 conditionals alongside ESP32-C3
- Use bit-bang LED output (RMT legacy API conflicts with IDF 5.x)
- Add IDF 5.x API compatibility (LEDC, mbedtls, ADC)
- Fix Network namespace collision with Arduino-ESP32 v3.x
- Prefer 5GHz WiFi connection for hidden SSIDs
- Add WiFi band indicator to info API and UI
- Exclude C5 from I2S parallel output, touch sensors, analog mic
- Add chip ID verification for OTA updates

ESP32-C5 features: WiFi 6 dual-band (2.4GHz + 5GHz), RISC-V single core,
240MHz, 2 RMT channels. Requires pioarduino platform fork.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 6, 2026

Walkthrough

This pull request adds comprehensive ESP32-C5 support across the WLED codebase by extending conditional compilation guards to recognize the new target, introducing ESP32-C5 specific hardware drivers and WiFi handling, adding IDF version-aware compatibility logic, and creating a new BitBang RMT wrapper for LED control on ESP32-C5.

Changes

Cohort / File(s) Summary
RMT/LED Hardware Core
lib/NeoESP32RmtHI/include/NeoEsp32RmtHIMethod.h, lib/NeoESP32RmtHI/src/NeoEsp32RmtHIMethod.cpp
Updated preprocessor guards to exclude ESP32C5 alongside ESP32C3; added IDF version guard (< 5) for legacy NeoEsp32RmtHI implementation path.
LED Driver & Bus Management
wled00/bus_wrapper.h, wled00/bus_manager.cpp, wled00/FX_fcn.cpp, wled00/FXparticleSystem.cpp
Introduced NeoEsp32C5BitBang wrapper class for LED control; expanded I2S/RMT guards to exclude ESP32C5; adjusted LEDC initialization and duty cycle writes for IDF 5.x compatibility; updated arithmetic optimizations to include ESP32C5 fast-path variants; extended particle system friction/collision handling for ESP32C5.
Frame Timing & Effects
wled00/FX.h
Adjusted MIN_FRAME_DELAY to differentiate ESP32C5 from base ESP32, assigning it to the slower-target group (value 3) alongside ESP32S2 and ESP32C3.
Platform Configuration
wled00/const.h, wled00/pin_manager.cpp, wled00/button.cpp, wled00/wled.h
Added ESP32C5 to macro conditionals for digital channels, LED limits, memory, pin defaults, UART/RX-TX mapping, LOLIN WiFi fix, and parallel I2S gating; extended strapping-pin checks in PinManager for ESP32C5.
DMX/Serial Support
wled00/dmx_output.cpp, wled00/src/dependencies/dmx/ESPDMX.cpp, wled00/src/dependencies/dmx/SparkFunDMX.cpp
Expanded ESP32 target checks to include ESP32C5 in DMX initialization paths and conditional compilation guards.
WiFi & Network Handling
wled00/wled.cpp, wled00/network.cpp, wled00/json.cpp, wled00/src/dependencies/network/Network.h
Added ESP32C5-specific 5GHz WiFi initialization with hidden SSID support and 20-second timeout fallback; introduced Network → WLEDNetwork macro rename for IDF 5.x conflict avoidance; added WiFi band reporting in JSON and UI info; clarified static IP configuration casting.
Configuration & Device Info
wled00/cfg.cpp, wled00/set.cpp, wled00/improv.cpp, wled00/ota_update.cpp, wled00/udp.cpp, wled00/data/index.js
Excluded ESP32C5 from parallel I2S and useParallelI2S feature gates; added ESP32C5 to Improv WiFi scan targets; introduced chipId check for ESP32C5 in OTA with unsupported-yet blocking; added node type reporting for ESP32C5; added optional WiFi band row to info UI.
Memory & Utilities
usermods/audioreactive/audio_reactive.cpp, wled00/util.cpp
Expanded audio reactive analog mic guards to include ESP32C5; introduced IDF version-aware SHA1/fingerprint computation with mbedtls API selection and conditional header inclusion; enabled RCOTRAM allocation for ESP32C5.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • willmmiles
  • netmindz
  • softhack007
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding ESP32-C5 support with WiFi 6 dual-band capability, which aligns with the primary objectives of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
wled00/data/index.js (1)

1056-1071: ⚠️ Potential issue | 🟡 Minor

Add missing ESP32-C5 case to btype() function.

The firmware reports ESP32-C5 nodes with type ID 41 (NODE_TYPE_ID_ESP32C5), but the btype() function has no case for it. ESP32-C5 nodes will display as "?" in the Nodes list. Add:

case 41: return "ESP32-C5";
wled00/util.cpp (1)

1180-1206: ⚠️ Potential issue | 🟡 Minor

Fingerprint value will change for devices upgrading from IDF 4.x to IDF 5.x builds.

On IDF 5.x, the ADC calibration entropy (lines 1187–1205) is excluded and chip_info.revision is used instead of chip_info.full_revision. This means the fingerprint—and consequently the device ID from getDeviceId()—will differ after an IDF version upgrade on the same hardware.

Given this is used for opt-in usage reporting (per prior learnings), this is likely acceptable, but it means the device will appear as a "new" device in tracking after the firmware upgrade. Worth documenting this expected behavior change.

Also, the preprocessor indentation is inconsistent: lines 1180–1184 indent #if/#else/#endif with 2 spaces (matching the function body), while lines 1185 and 1206 place #if/#endif at column 0. Minor nit, but worth unifying.

wled00/pin_manager.cpp (1)

211-216: ⚠️ Potential issue | 🔴 Critical

Separate pin restriction blocks needed for ESP32-C5 as it has different reserved GPIO ranges than ESP32-C3.

ESP32-C5 has a distinct GPIO layout:

  • SPI flash: GPIO 16–22 (not 11–17 like C3)
  • USB-JTAG: GPIO 13–14 (not 18–19 like C3)
  • Strapping pins: GPIO 2, 7, 27, 28 (not 2, 8, 9 like C3)

The current code applies C3's restrictions to both chips. Split into separate #elif blocks with C5-specific ranges.

wled00/wled.h (1)

144-149: ⚠️ Potential issue | 🔴 Critical

ESPDMX library does not explicitly support ESP32-C5. The library's documentation lists ESP-IDF v4.4.1+ as a requirement but does not explicitly document ESP32-C5 compatibility. While ESPDMX appears in the codebase guards alongside C5 (lines 144–149, 460–464), the library maintainers have not validated or tested C5 support. Consider confirming this works on actual C5 hardware or consulting the library maintainer before merging.

🤖 Fix all issues with AI agents
In `@lib/NeoESP32RmtHI/src/NeoEsp32RmtHIMethod.cpp`:
- Around line 35-41: bus_wrapper.h is including and aliasing the legacy HI RMT
types even when the .cpp is compiled out on IDF 5+, causing unresolved symbols;
wrap the entire HI-specific include/typedef block (the NeoEsp32RmtHIMethod.h
inclusion and the NeoEsp32RmtMethod(x) macro mappings) with an `#if`
ESP_IDF_VERSION_MAJOR < 5 guard (in addition to the existing
CONFIG_IDF_TARGET_ESP32C5 / __riscv checks) so that on IDF 5+ the HI path is
skipped and the code falls through to the standard RmtN methods used at link
time.

In `@wled00/bus_wrapper.h`:
- Around line 248-268: Re-indent the NeoEsp32C5BitBang class and the
NeoEsp32RmtMethod macro to use the file's 2-space header style: move all
class-level keywords, access specifiers (public:, private:) and member
declarations (typedef, constructor, methods, and the _bb field) left so each
line is indented with two spaces relative to the header block, matching other .h
files; ensure the template line and macro definition (NeoEsp32RmtMethod) follow
the same 2-space indentation level and preserve all identifiers and signatures
exactly (NeoEsp32C5BitBang, T_BB, SettingsObject, _bb, NeoEsp32RmtMethod).

In `@wled00/const.h`:
- Around line 524-525: Replace the incorrect preprocessor symbol
ARDUINO_ARCH_ESP32C5 with the project-wide CONFIG_IDF_TARGET_ESP32C5 in the
conditional that sets MAX_LED_MEMORY so the ESP32-C5 path selects 32768 bytes;
update the clause that currently reads 'defined(ARDUINO_ARCH_ESP32C5)' to use
'defined(CONFIG_IDF_TARGET_ESP32C5)' alongside ARDUINO_ARCH_ESP32C3 to ensure
the intended MAX_LED_MEMORY value is applied for ESP32-C5 builds.

In `@wled00/ota_update.cpp`:
- Around line 431-437: Update the documented list of known ESP32 chip IDs to
include the ESP32-C5 entry for consistency with the runtime check: add "0x0017 =
ESP32-C5" to the comment block that enumerates known chip IDs (the same block
that currently lists other IDs like ESP32, ESP32-S2, etc.), ensuring it matches
the validation using CONFIG_IDF_TARGET_ESP32C5 and the chipId value 0x0017; no
code logic changes are needed since BOOTLOADER_OFFSET for ESP32-C5 is already
correct.

In `@wled00/util.cpp`:
- Around line 1145-1153: Fix the indentation in util.cpp for the IDF conditional
block so it uses 2-space indentation (not 4). Locate the block that dispatches
between mbedtls_sha1_starts / mbedtls_sha1_update / mbedtls_sha1_finish and the
_ret variants (mbedtls_sha1_starts_ret, mbedtls_sha1_update_ret,
mbedtls_sha1_finish_ret) and reformat the lines inside the `#if/`#else/#endif to
use 2 spaces per indent level to match the project's .cpp style.
🧹 Nitpick comments (3)
wled00/src/dependencies/network/Network.h (1)

1-9: Include guard does not protect the #include directives (pre-existing).

The #include <WiFi.h> / #include <ETH.h> (lines 1–5) sit outside the #ifndef Network_h guard. This is a pre-existing issue and not introduced by this PR, but worth noting: if this header is included multiple times, those platform headers are re-included each time (though they have their own guards, so it's benign in practice).

wled00/util.cpp (1)

1168-1173: Mid-file #include directives — consider moving to the top of the file.

These #include directives are placed between the #ifdef ESP32 guard and the generateDeviceFingerprint() function definition. While functional, mid-file includes reduce readability and make dependency tracking harder. The existing ESP32 includes (lines 8–15) would be a more natural location, guarded by the same IDF version check.

wled00/wled.cpp (1)

719-780: Remove redundant #include "esp_wifi.h" (already in wled.h for all ESP32 variants).

esp_wifi.h is already included at file scope in wled.h line 100 under the #else // ESP32 block, making the include at wled.cpp:721 redundant. Remove it to avoid duplication and maintain single point of configuration.

Suggested fix
 `#if` defined(CONFIG_IDF_TARGET_ESP32C5)
     // ESP32-C5: Prefer 5GHz WiFi 6 for better performance with hidden SSIDs
-    `#include` "esp_wifi.h"
     DEBUG_PRINTF_P(PSTR("ESP32-C5: Trying 5GHz for hidden SSID: %s\n"), multiWiFi[selectedWiFi].clientSSID);

Comment on lines +35 to +41

// NeoEsp32RmtHI uses the legacy (IDF 4.x) low-level RMT API which is incompatible with IDF 5.x.
// On IDF 5+ builds (pioarduino / Arduino-ESP32 v3.x), WLED selects standard NeoEsp32RmtN methods
// for RISC-V targets anyway (see bus_wrapper.h), so this implementation is not needed.
#if ESP_IDF_VERSION_MAJOR < 5

#include <algorithm>
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

fd -t f "bus_wrapper.h" --exec cat {} \;

Repository: wled/WLED

Length of output: 50366


🏁 Script executed:

rg -n "RmtHI|NeoEsp32RmtHI|ESP_IDF_VERSION" wled00/bus_wrapper.h -A 3 -B 3

Repository: wled/WLED

Length of output: 386


🏁 Script executed:

# Check the header file to see if it has any IDF version guards
fd -t f "NeoEsp32RmtHIMethod.h" --exec cat {} \;

Repository: wled/WLED

Length of output: 35417


🏁 Script executed:

# Check if there are any other references to NeoEsp32RmtHI that might guard instantiation
rg -n "NeoEsp32RmtHI|RmtHI" --type cpp --type h | grep -E "(ifdef|if defined|ESP_IDF)" | head -20

Repository: wled/WLED

Length of output: 35


Add IDF version guard to bus_wrapper.h RMT method selection.

The .cpp implementation correctly gates legacy RMT code behind #if ESP_IDF_VERSION_MAJOR < 5, preventing incompatible code from being compiled on IDF 5.x. However, bus_wrapper.h does not gate the header inclusion by IDF version—it only checks target chip (CONFIG_IDF_TARGET_ESP32C5) and architecture (__riscv).

On classic ESP32 with IDF 5.x (Arduino-ESP32 v3.x), the current logic will:

  1. Include NeoEsp32RmtHIMethod.h (not gated by IDF version)
  2. Expose all HI method typedefs via #define NeoEsp32RmtMethod(x) NeoEsp32RmtHIN...
  3. Attempt to instantiate these types in bus creation
  4. Hit unresolved symbol errors at link time because the driver implementation is compiled out

Add an ESP_IDF_VERSION_MAJOR < 5 check around the HI method path in bus_wrapper.h (near line 269) to fall through to standard RmtN methods on IDF 5.x, matching the intent of the .cpp gate.

🤖 Prompt for AI Agents
In `@lib/NeoESP32RmtHI/src/NeoEsp32RmtHIMethod.cpp` around lines 35 - 41,
bus_wrapper.h is including and aliasing the legacy HI RMT types even when the
.cpp is compiled out on IDF 5+, causing unresolved symbols; wrap the entire
HI-specific include/typedef block (the NeoEsp32RmtHIMethod.h inclusion and the
NeoEsp32RmtMethod(x) macro mappings) with an `#if` ESP_IDF_VERSION_MAJOR < 5 guard
(in addition to the existing CONFIG_IDF_TARGET_ESP32C5 / __riscv checks) so that
on IDF 5+ the HI path is skipped and the code falls through to the standard RmtN
methods used at link time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonny190 the rabbit is right, this is a quite dangerous change. it means that the code will still have the high prio interrupt driver for RMT (NeoEsp32RmtHI.S), but the C++ support code will be missing. Its one of the things that the "V5" branch should handle, hopefully with a better and more generic approach.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines +248 to +268
#if defined(CONFIG_IDF_TARGET_ESP32C5)
// ESP32-C5: NeoPixelBus 2.8.x legacy RMT API conflicts with IDF 5.x driver_ng, use bit-bang instead.
// Bit-bang constructor takes 4 args but NeoPixelBus passes 5 (including channel), so we wrap it.
template<typename T_BB>
class NeoEsp32C5BitBang {
public:
typedef NeoNoSettings SettingsObject;
NeoEsp32C5BitBang(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel = NeoBusChannel_0)
: _bb(pin, pixelCount, elementSize, settingsSize) {}
bool IsReadyToUpdate() const { return _bb.IsReadyToUpdate(); }
void Initialize() { _bb.Initialize(); }
void Update(bool b) { _bb.Update(b); }
bool AlwaysUpdate() { return _bb.AlwaysUpdate(); }
bool SwapBuffers() { return _bb.SwapBuffers(); }
uint8_t* getData() const { return _bb.getData(); }
size_t getDataSize() const { return _bb.getDataSize(); }
void applySettings(const SettingsObject& settings) { _bb.applySettings(settings); }
private:
T_BB _bb;
};
#define NeoEsp32RmtMethod(x) NeoEsp32C5BitBang<NeoEsp32BitBang ## x ## Method>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align NeoEsp32C5BitBang indentation with 2‑space header style.

Access specifiers and members should follow the 2‑space indentation used elsewhere in this header.

🧹 Suggested indentation fix
-class NeoEsp32C5BitBang {
-public:
-    typedef NeoNoSettings SettingsObject;
-    NeoEsp32C5BitBang(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel = NeoBusChannel_0)
-        : _bb(pin, pixelCount, elementSize, settingsSize) {}
-    bool IsReadyToUpdate() const { return _bb.IsReadyToUpdate(); }
-    void Initialize() { _bb.Initialize(); }
-    void Update(bool b) { _bb.Update(b); }
-    bool AlwaysUpdate() { return _bb.AlwaysUpdate(); }
-    bool SwapBuffers() { return _bb.SwapBuffers(); }
-    uint8_t* getData() const { return _bb.getData(); }
-    size_t getDataSize() const { return _bb.getDataSize(); }
-    void applySettings(const SettingsObject& settings) { _bb.applySettings(settings); }
-private:
-    T_BB _bb;
-};
+class NeoEsp32C5BitBang {
+  public:
+    typedef NeoNoSettings SettingsObject;
+    NeoEsp32C5BitBang(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel = NeoBusChannel_0)
+        : _bb(pin, pixelCount, elementSize, settingsSize) {}
+    bool IsReadyToUpdate() const { return _bb.IsReadyToUpdate(); }
+    void Initialize() { _bb.Initialize(); }
+    void Update(bool b) { _bb.Update(b); }
+    bool AlwaysUpdate() { return _bb.AlwaysUpdate(); }
+    bool SwapBuffers() { return _bb.SwapBuffers(); }
+    uint8_t* getData() const { return _bb.getData(); }
+    size_t getDataSize() const { return _bb.getDataSize(); }
+    void applySettings(const SettingsObject& settings) { _bb.applySettings(settings); }
+  private:
+    T_BB _bb;
+};

As per coding guidelines, "wled00/**/!(html_).h: Use 2-space indentation for non-generated C++ header files (.h)".

🤖 Prompt for AI Agents
In `@wled00/bus_wrapper.h` around lines 248 - 268, Re-indent the NeoEsp32C5BitBang
class and the NeoEsp32RmtMethod macro to use the file's 2-space header style:
move all class-level keywords, access specifiers (public:, private:) and member
declarations (typedef, constructor, methods, and the _bb field) left so each
line is indented with two spaces relative to the header block, matching other .h
files; ensure the template line and macro definition (NeoEsp32RmtMethod) follow
the same 2-space indentation level and preserve all identifiers and signatures
exactly (NeoEsp32C5BitBang, T_BB, SettingsObject, _bb, NeoEsp32RmtMethod).

Comment on lines +524 to 525
#elif defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32C5)
#define MAX_LED_MEMORY 32768
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Search for ARDUINO_ARCH_ESP32C5 usage in codebase
rg "ARDUINO_ARCH_ESP32C5" -n

Repository: wled/WLED

Length of output: 144


🏁 Script executed:

# Also check for CONFIG_IDF_TARGET_ESP32C5 as an alternative
rg "CONFIG_IDF_TARGET_ESP32C5" -n

Repository: wled/WLED

Length of output: 11840


🏁 Script executed:

# Check the context around the lines in question in wled00/const.h
head -530 wled00/const.h | tail -15

Repository: wled/WLED

Length of output: 393


🌐 Web query:

pioarduino ESP32-C5 ARDUINO_ARCH_ESP32C5 macro support

💡 Result:

  • Official PlatformIO espressif32 does not support Arduino-ESP32 3.x, so ESP32‑C5 + Arduino framework won’t be properly supported there (PlatformIO still recommends Arduino core 2.x and has an open request/discussion around Arduino 3.x support). [2]
  • ESP32‑C5 support exists in Arduino‑ESP32 (3.x), but to use it in a PlatformIO workflow you generally need the community fork “pioarduino” platform-espressif32, which was created specifically to bring newer SoCs (including ESP32‑C5) to PlatformIO. [1][3]

About ARDUINO_ARCH_ESP32C5

  • In the Arduino-ESP32 ecosystem, you should not rely on a dedicated ARDUINO_ARCH_ESP32C5 macro being provided. Instead, for chip-selection conditionals use ESP-IDF target macros / helpers, e.g. CONFIG_IDF_TARGET_ESP32C5 or SOC_IS(ESP32C5) (from ESP-IDF’s SoC capability system). [4]
  • In PlatformIO configs people typically pass ARDUINO_VARIANT=esp32c5 (and similar flags) rather than an ARDUINO_ARCH_ESP32C5 architecture macro. [5]

If you must key off ARDUINO_ARCH_ESP32C5 for compatibility with an existing library, the practical workaround is to define it yourself in build_flags for your ESP32‑C5 environment (while still using CONFIG_IDF_TARGET_ESP32C5/SOC_IS(ESP32C5) for “real” detection). [4][5]

Sources: [1] [2] [3] [4] [5]


Use CONFIG_IDF_TARGET_ESP32C5 instead of ARDUINO_ARCH_ESP32C5 for consistency and correctness.

ARDUINO_ARCH_ESP32C5 is not provided by Arduino-ESP32 or pioarduino. The codebase consistently uses CONFIG_IDF_TARGET_ESP32C5 elsewhere (60+ occurrences), and line 511 of this same file uses CONFIG_IDF_TARGET_* macros. If ARDUINO_ARCH_ESP32C5 remains undefined, the code silently falls through to MAX_LED_MEMORY 65536 instead of the intended 32768 for ESP32-C5.

🤖 Prompt for AI Agents
In `@wled00/const.h` around lines 524 - 525, Replace the incorrect preprocessor
symbol ARDUINO_ARCH_ESP32C5 with the project-wide CONFIG_IDF_TARGET_ESP32C5 in
the conditional that sets MAX_LED_MEMORY so the ESP32-C5 path selects 32768
bytes; update the clause that currently reads 'defined(ARDUINO_ARCH_ESP32C5)' to
use 'defined(CONFIG_IDF_TARGET_ESP32C5)' alongside ARDUINO_ARCH_ESP32C3 to
ensure the intended MAX_LED_MEMORY value is applied for ESP32-C5 builds.

Comment on lines +431 to +437
#elif defined(CONFIG_IDF_TARGET_ESP32C5)
if (chipId != 0x0017) {
*bootloaderErrorMsg = "Chip ID mismatch - expected ESP32-C5 (0x0017), got 0x" + String(chipId, HEX);
return false;
}
*bootloaderErrorMsg = "ESP32-C5 update not supported yet";
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for ESP32-C5 chip ID references in the codebase
rg "ESP32-C5|0x0017|C5" wled00/ota_update.cpp -A 2 -B 2

Repository: wled/WLED

Length of output: 889


🏁 Script executed:

# Look for bootloader offset definitions and their sources
rg "BOOTLOADER_OFFSET" wled00/ota_update.cpp -B 5 -A 5

Repository: wled/WLED

Length of output: 2263


🏁 Script executed:

# Check if there are any ESP-IDF header files or documentation referenced
rg "esp_chip_id|esp_flash|bootloader" wled00/ -t cpp --max-count 5

Repository: wled/WLED

Length of output: 1356


🏁 Script executed:

# Look for chip ID definitions or mappings in comments
rg "0x0017|chipId" wled00/ota_update.cpp -B 3 -A 3

Repository: wled/WLED

Length of output: 2086


🏁 Script executed:

# Check for any references to chip ID meanings in the file
rg "Chip ID|esp_efuse_mac_get_chip_id|0x000[0-9A-F]" wled00/ota_update.cpp -B 2 -A 2

Repository: wled/WLED

Length of output: 2245


Update the ESP32 chip ID comment list to include ESP32-C5 (0x0017).

The chip ID 0x0017 for ESP32-C5 is used in the validation code (line 434) but is missing from the documented list of known ESP32 chip IDs (lines ~406–412). Add 0x0017 = ESP32-C5 to that list for consistency. The BOOTLOADER_OFFSET = 0x2000 for ESP32-C5 (line 22) is correctly defined.

🤖 Prompt for AI Agents
In `@wled00/ota_update.cpp` around lines 431 - 437, Update the documented list of
known ESP32 chip IDs to include the ESP32-C5 entry for consistency with the
runtime check: add "0x0017 = ESP32-C5" to the comment block that enumerates
known chip IDs (the same block that currently lists other IDs like ESP32,
ESP32-S2, etc.), ensuring it matches the validation using
CONFIG_IDF_TARGET_ESP32C5 and the chipId value 0x0017; no code logic changes are
needed since BOOTLOADER_OFFSET for ESP32-C5 is already correct.

Comment on lines +1145 to +1153
#if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5
mbedtls_sha1_starts(&ctx);
mbedtls_sha1_update(&ctx, (const unsigned char*)input.c_str(), input.length());
mbedtls_sha1_finish(&ctx, shaResult);
#else
mbedtls_sha1_starts_ret(&ctx);
mbedtls_sha1_update_ret(&ctx, (const unsigned char*)input.c_str(), input.length());
mbedtls_sha1_finish_ret(&ctx, shaResult);
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

mbedtls 3.x API changes _ret suffix removed

💡 Result:

In Mbed TLS 3.x, many cryptography functions that previously had a *_ret suffix (introduced in 2.x as “the version that returns an int”) were renamed back to the original name without _ret, and the old non-_ret variants they replaced are gone. So code written for 2.x that calls mbedtls_*_ret() often needs to be updated to call mbedtls_*() (and still check the return value). [1]

Examples of renames (3.x)

  • mbedtls_sha256_starts_retmbedtls_sha256_starts
  • mbedtls_sha256_update_retmbedtls_sha256_update
  • mbedtls_sha256_finish_retmbedtls_sha256_finish
  • mbedtls_sha256_retmbedtls_sha256
    Similarly for MD5, RIPEMD160, SHA1, SHA512, plus:
  • mbedtls_ctr_drbg_update_retmbedtls_ctr_drbg_update
  • mbedtls_hmac_drbg_update_retmbedtls_hmac_drbg_update [1]

Migration options

  1. Rename your calls from *_ret to the non-suffixed names per the list in the 3.0 migration guide. [1]
  2. Keep old names temporarily by including compat_2.x.h, which provides macros mapping the 2.x names to the 3.x names. [1]

Sources:
[1] Mbed TLS 3.0 Migration Guide (section “Rename mbedtls_*_ret() cryptography functions…”) (mcuxpresso.nxp.com)

Citations:


🏁 Script executed:

# Check the actual indentation and content of the file at lines 1145-1153
sed -n '1140,1160p' wled00/util.cpp | cat -A

Repository: wled/WLED

Length of output: 840


IDF 5.x mbedtls API migration is correct, but fix indentation.

The conditional correctly dispatches between mbedtls 3.x (with IDF 5.x, using mbedtls_sha1_starts, _update, _finish without _ret suffix) and mbedtls 2.x (using the _ret variants). However, the code uses 4-space indentation instead of the required 2-space indentation for .cpp files.

🤖 Prompt for AI Agents
In `@wled00/util.cpp` around lines 1145 - 1153, Fix the indentation in util.cpp
for the IDF conditional block so it uses 2-space indentation (not 4). Locate the
block that dispatches between mbedtls_sha1_starts / mbedtls_sha1_update /
mbedtls_sha1_finish and the _ret variants (mbedtls_sha1_starts_ret,
mbedtls_sha1_update_ret, mbedtls_sha1_finish_ret) and reformat the lines inside
the `#if/`#else/#endif to use 2 spaces per indent level to match the project's
.cpp style.

@softhack007
Copy link
Member

@jonny190 thank you for your effort 🥇

we already have an experimental branch for esp-idf V5 and a sub-branch for esp32-c6 based on V5.

In order to keep work focussed and have a common tech baseline, I would like to keep these together, by integrating your work on the C5 there instead of main.

Would you mind to create a new PR for the V5-C6 branch, and integrate your work with the "skeletons" we already have?

@jonny190
Copy link
Author

jonny190 commented Feb 7, 2026

Absolutely, I'll get one in tomorrow, the computer is off for the night now, I'll also look at some of code rabbits comments and see what I can do

@softhack007
Copy link
Member

softhack007 commented Feb 7, 2026

Absolutely, I'll get one in tomorrow, the computer is off for the night now, I'll also look at some of code rabbits comments and see what I can do

Thanks, and no need to hurry 😉
you will see that we found a way to avoid the "RMT vs. RMT_ng" crash at startup. I'm curious if you can get LEDs output to work with RMT instead of bitBang on that basis.

Edit: V5 is slightly behind "main" (maybe 1 or 2 months), but it will catch up with main soon - once I find a bit of time to wade through merge conflicts.

Edit2: i just noticed that you did not create any additions for platformio.ini yet. Once you managed to move everything to our C6-V5 branch, please also add new build environments for -C5, based on the structure you'll find for -C6.

@softhack007 softhack007 marked this pull request as draft February 7, 2026 00:25
@softhack007 softhack007 marked this pull request as draft February 7, 2026 00:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants