From 92be9116bce9130788922625292143b76c16f8cc Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Mon, 20 Jul 2026 09:55:13 +0200 Subject: [PATCH 1/6] Fix bootloop on C3 and S3, remove stray flag --- platformio.ini | 7 +------ wled00/util.cpp | 8 ++------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/platformio.ini b/platformio.ini index 3b00cc1616..b38af57dfd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -366,7 +366,6 @@ build_flags = -g -DARDUINO_ARCH_ESP32S2 -DCONFIG_IDF_TARGET_ESP32S2=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 - -DCO -DARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 ! ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT @@ -386,11 +385,11 @@ build_flags = -g -DARDUINO_ARCH_ESP32 -DARDUINO_ARCH_ESP32C3 -DCONFIG_IDF_TARGET_ESP32C3=1 - -DCO -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT ${esp32_idf_V5.build_flags} + -march=rv32imc ; non-atomic RISC-V architecture (default is rv32imac, C3 does not support the 'a'tomic operations) lib_deps = ${esp32_idf_V5.lib_deps} lib_ignore = ${esp32_idf_V5.lib_ignore} @@ -409,7 +408,6 @@ build_flags = -g -DARDUINO_ARCH_ESP32S3 -DCONFIG_IDF_TARGET_ESP32S3=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_DFU_ON_BOOT=0 - -DCO ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_MODE, ARDUINO_USB_CDC_ON_BOOT ${esp32_idf_V5.build_flags} @@ -433,7 +431,6 @@ build_flags = -g -DARDUINO_ARCH_ESP32C5 -DCONFIG_IDF_TARGET_ESP32C5=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 - -DCO ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_MODE ;; ARDUINO_USB_CDC_ON_BOOT @@ -460,7 +457,6 @@ build_flags = -g -DARDUINO_ARCH_ESP32C6 -DCONFIG_IDF_TARGET_ESP32C6=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 - -DCO -DARDUINO_USB_MODE=1 ;; this flag is - most likely - mandatory for ESP32-C6 ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT @@ -484,7 +480,6 @@ build_flags = -g -DARDUINO_ARCH_ESP32P4 -DCONFIG_IDF_TARGET_ESP32P4=1 -D CONFIG_ASYNC_TCP_USE_WDT=0 - -DCO -DARDUINO_USB_MODE=1 ;; this flag is - most likely - mandatory for ESP32-P4 -D WLED_DISABLE_INFRARED ;; library not compatible with -P4 -D WLED_DISABLE_ESPNOW ;; not yet tested diff --git a/wled00/util.cpp b/wled00/util.cpp index 22ded94917..a09b958a44 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -1321,11 +1321,7 @@ String computeSHA1(const String& input) { } #ifdef ESP32 -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) -#include "esp_adc_cal.h" // ToDO: deprecated API -//#include "esp_adc/adc_cali.h" // new API -//#include "esp_adc/adc_cali_scheme.h" // new API -#else +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) #include "esp_adc_cal.h" #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4,4,7) // backwards compatibility patch #define ADC_ATTEN_DB_12 ADC_ATTEN_DB_11 @@ -1343,7 +1339,7 @@ String generateDeviceFingerprint() { fp[0] ^= chip_info.revision | (chip_info.model << 16); #endif -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) // mix in ADC calibration data - legacy adc calibration API is not supported on new MCUs (-C5, -C6, -C61, -P4) esp_adc_cal_characteristics_t ch; #if (SOC_ADC_MAX_BITWIDTH == 13) || (CONFIG_SOC_ADC_RTC_MAX_BITWIDTH == 13) // S2 has 13 bit ADC From 5a5fd54acfbd49014f1529a22a02561e289b8934 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 21 Jul 2026 09:34:25 +0200 Subject: [PATCH 2/6] remove `-march` --- platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index b38af57dfd..11c02d3aa3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -389,7 +389,6 @@ build_flags = -g ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT ${esp32_idf_V5.build_flags} - -march=rv32imc ; non-atomic RISC-V architecture (default is rv32imac, C3 does not support the 'a'tomic operations) lib_deps = ${esp32_idf_V5.lib_deps} lib_ignore = ${esp32_idf_V5.lib_ignore} From 986f790354493dd1b683fd58ce896e248ca2fdce Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Wed, 22 Jul 2026 02:38:52 +0200 Subject: [PATCH 3/6] fix AR usermod pulling in the legacy ADC driver on ESP32 --- usermods/audioreactive/audio_reactive.cpp | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/usermods/audioreactive/audio_reactive.cpp b/usermods/audioreactive/audio_reactive.cpp index ba175282b3..116333c9cd 100644 --- a/usermods/audioreactive/audio_reactive.cpp +++ b/usermods/audioreactive/audio_reactive.cpp @@ -5,8 +5,48 @@ #include #include +#endif + +// AI: below section was generated by an AI +#if defined(CONFIG_IDF_TARGET_ESP32) && defined(ARDUINO_ARCH_ESP32) && (ESP_IDF_VERSION_MAJOR >= 5) +/* + * Bootloop workaround for classic ESP32 on esp-idf 5.x (WLED V5): + * AR still uses the legacy I2S driver (driver/i2s.h) which pulls in the legacy ADC driver. + * This causes a "abort" on boot as IDF V5 does not allow the legacy ADC driver to be used + * if any other function (i.e. Arduino's analogRead()) pulls in the new driver. + * + * The no-op stubs below satisfy exactly the symbols i2s_legacy.c.obj needs, so the real + * adc_i2s_deprecated.c.obj / adc_legacy.c.obj are never linked. This is safe because on IDF >= 5 + * the analog built-in-ADC mic class (I2SAdcSource) is compiled out anyway (see audio_source.h), + * so these paths are never executed; digital I2S/PDM mics don't use them. + * Delete this block once the usermod is ported to the new I2S driver (driver/i2s_std.h). + */ +#include + +// Stub: would configure the (removed) I2S built-in ADC mode. Never called for digital mics. +extern "C" esp_err_t adc_i2s_mode_init(int adc_unit, int channel) { + (void)adc_unit; (void)channel; + return ESP_ERR_NOT_SUPPORTED; +} +// Stub: would select the ADC data source for I2S DMA. Never called for digital mics. +extern "C" esp_err_t adc_set_i2s_data_source(int adc_unit, int pattern) { + (void)adc_unit; (void)pattern; + return ESP_ERR_NOT_SUPPORTED; +} + +// Stub: would acquire ADC1 for DMA (built-in ADC mode only). Report failure if ever called. +extern "C" esp_err_t adc1_dma_mode_acquire(void) { + return ESP_ERR_NOT_SUPPORTED; +} + +// Stub: would release the legacy ADC1 lock. No lock is ever taken, so nothing to do. +extern "C" esp_err_t adc1_lock_release(int adc_unit) { + (void)adc_unit; + return ESP_OK; +} #endif +// AI: end #if defined(ARDUINO_ARCH_ESP32) && (defined(WLED_DEBUG) || defined(SR_DEBUG)) #include From 5d59d7b018f927c7489f39a77c72b1a030a87bdc Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 23 Jul 2026 05:33:18 +0200 Subject: [PATCH 4/6] fix ID generation for all targets, add efuse entropy for new chips --- usermods/audioreactive/audio_reactive.cpp | 13 +- wled00/util.cpp | 168 ++++++++++++++++++++-- 2 files changed, 164 insertions(+), 17 deletions(-) diff --git a/usermods/audioreactive/audio_reactive.cpp b/usermods/audioreactive/audio_reactive.cpp index 116333c9cd..c257b4e59c 100644 --- a/usermods/audioreactive/audio_reactive.cpp +++ b/usermods/audioreactive/audio_reactive.cpp @@ -8,7 +8,7 @@ #endif // AI: below section was generated by an AI -#if defined(CONFIG_IDF_TARGET_ESP32) && defined(ARDUINO_ARCH_ESP32) && (ESP_IDF_VERSION_MAJOR >= 5) +#if defined(CONFIG_IDF_TARGET_ESP32) && (ESP_IDF_VERSION_MAJOR >= 5) /* * Bootloop workaround for classic ESP32 on esp-idf 5.x (WLED V5): * AR still uses the legacy I2S driver (driver/i2s.h) which pulls in the legacy ADC driver. @@ -24,14 +24,14 @@ #include // Stub: would configure the (removed) I2S built-in ADC mode. Never called for digital mics. -extern "C" esp_err_t adc_i2s_mode_init(int adc_unit, int channel) { - (void)adc_unit; (void)channel; +extern "C" esp_err_t adc_i2s_mode_init(int adcUnit, int channel) { + (void)adcUnit; (void)channel; return ESP_ERR_NOT_SUPPORTED; } // Stub: would select the ADC data source for I2S DMA. Never called for digital mics. -extern "C" esp_err_t adc_set_i2s_data_source(int adc_unit, int pattern) { - (void)adc_unit; (void)pattern; +extern "C" esp_err_t adc_set_i2s_data_source(int source) { + (void)source; return ESP_ERR_NOT_SUPPORTED; } @@ -41,8 +41,7 @@ extern "C" esp_err_t adc1_dma_mode_acquire(void) { } // Stub: would release the legacy ADC1 lock. No lock is ever taken, so nothing to do. -extern "C" esp_err_t adc1_lock_release(int adc_unit) { - (void)adc_unit; +extern "C" esp_err_t adc1_lock_release(void) { return ESP_OK; } #endif diff --git a/wled00/util.cpp b/wled00/util.cpp index 4e4b01ad1e..f370d1e2dc 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -1332,30 +1332,165 @@ String computeSHA1(const String& input) { #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4,4,7) // backwards compatibility patch #define ADC_ATTEN_DB_12 ADC_ATTEN_DB_11 #endif +#else // IDF V5 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 +// Functions to reproduce the legacy ADC calibration factors to be used as "salt" for device ID +// AI: below section was (mostly) generated by an AI, tested and confirmed working as intended on all targets +#if CONFIG_IDF_TARGET_ESP32 +// ESP32 legacy ADC calibration factors Line Fitting + LUT (LUT is consolidated into a single value) +#include "soc/soc.h" +#include "soc/efuse_reg.h" +#define VREF_REG EFUSE_BLK0_RDATA4_REG +#define VREF_MASK 0x1F +#define VREF_STEP_SIZE 7 +#define VREF_OFFSET 1100 +#define TP_REG EFUSE_BLK3_RDATA3_REG +#define BLK3_RESERVED_REG EFUSE_BLK0_RDATA3_REG +#define TP_LOW1_OFFSET 278 +#define TP_LOW_MASK 0x7F +#define TP_LOW_VOLTAGE 150 +#define TP_HIGH1_OFFSET 3265 +#define TP_HIGH_MASK 0x1FF +#define TP_HIGH_VOLTAGE 850 +#define TP_STEP_SIZE 4 +#define ADC_12_BIT_RES 4096 +// Hardcoded legacy constants for ADC_ATTEN_DB_12 (Index 3) +constexpr uint32_t TP_ATTEN_SCALE_DB12 = 224310; +constexpr uint32_t TP_ATTEN_OFFSET_DB12 = 54; +constexpr uint32_t VREF_ATTEN_SCALE_DB12 = 196602; +constexpr uint32_t VREF_ATTEN_OFFSET_DB12 = 142; +// Compile-time pre-calculated XOR sums of the first 8 elements of the legacy 20-point LUTs (replaces the V4 XOR for-loop) +constexpr uint32_t LUT_ADC1_LOW_XOR_8 = 2240 ^ 2297 ^ 2352 ^ 2405 ^ 2457 ^ 2512 ^ 2564 ^ 2616; +constexpr uint32_t LUT_ADC1_HIGH_XOR_8 = 2667 ^ 2706 ^ 2745 ^ 2780 ^ 2813 ^ 2844 ^ 2873 ^ 2901; + +static inline int32_t decodeBits(uint32_t bits, uint32_t mask, bool twosComplement) { + if (bits & (~(mask >> 1) & mask)) { + return twosComplement ? -(int32_t)(((~bits) + 1) & (mask >> 1)) : -(int32_t)(bits & (mask >> 1)); + } + return (int32_t)(bits & (mask >> 1)); +} + +static void getLegacyAdcCoeffs(uint32_t *coeff_a, uint32_t *coeff_b) { + bool tpBurned = (REG_GET_FIELD(BLK3_RESERVED_REG, EFUSE_RD_BLK3_PART_RESERVE) != 0) && + (REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_LOW) != 0) && + (REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_HIGH) != 0); + + if (tpBurned) { + uint32_t lowBits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_LOW); + uint32_t highBits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_HIGH); + + uint32_t low = TP_LOW1_OFFSET + decodeBits(lowBits, TP_LOW_MASK, true) * TP_STEP_SIZE; + uint32_t high = TP_HIGH1_OFFSET + decodeBits(highBits, TP_HIGH_MASK, true) * TP_STEP_SIZE; + + uint32_t delta_x = high - low; + uint32_t delta_v = TP_HIGH_VOLTAGE - TP_LOW_VOLTAGE; + + *coeff_a = (delta_v * TP_ATTEN_SCALE_DB12 + delta_x / 2) / delta_x; + *coeff_b = TP_HIGH_VOLTAGE - ((delta_v * high + delta_x / 2) / delta_x) + TP_ATTEN_OFFSET_DB12; + } else { + bool vrefBurned = (REG_GET_FIELD(VREF_REG, EFUSE_RD_ADC_VREF) != 0); + uint32_t vrefBits = REG_GET_FIELD(VREF_REG, EFUSE_ADC_VREF); + uint32_t vref = vrefBurned ? (VREF_OFFSET + decodeBits(vrefBits, VREF_MASK, false) * VREF_STEP_SIZE) : 1100; + + *coeff_a = (vref * VREF_ATTEN_SCALE_DB12) / ADC_12_BIT_RES; + *coeff_b = VREF_ATTEN_OFFSET_DB12; + } +} #endif + +#if CONFIG_IDF_TARGET_ESP32S2 +#include "hal/adc_types.h" +#include "esp_efuse_rtc_table.h" +// note: this is confirmed working on v2 calib S2 chips, had no v1 S2 to test +static void getLegacyAdcCoeffs(uint32_t *coeff_a, uint32_t *coeff_b) { + *coeff_a = 0; + *coeff_b = 0; + static const uint32_t v_high = 2000; // Hardcoded legacy constant for ADC_ATTEN_DB_12 + const uint32_t v_low = 250; + const int atten = ADC_ATTEN_DB_12; // 3 + + int version = esp_efuse_rtc_table_read_calib_version(); + if (version == 1) { + int tag_l = esp_efuse_rtc_table_get_tag(1, ADC_UNIT_1, atten, RTCCALIB_V1_PARAM_VLOW); + int tag_h = esp_efuse_rtc_table_get_tag(1, ADC_UNIT_1, atten, RTCCALIB_V1_PARAM_VHIGH); + uint32_t low = (uint32_t)esp_efuse_rtc_table_get_parsed_efuse_value(tag_l, false); + uint32_t high = (uint32_t)esp_efuse_rtc_table_get_parsed_efuse_value(tag_h, false); + uint32_t delta = high - low; + if (delta == 0) return; + // identical operand types/order to v4.4 characterize_using_two_point() + *coeff_a = 65536u * (v_high - v_low) / delta; + *coeff_b = 1024u * (v_low * high - v_high * low) / delta; // non-zero on v1 chips! + } else if (version == 2) { + int tag = esp_efuse_rtc_table_get_tag(2, ADC_UNIT_1, atten, RTCCALIB_V2_PARAM_VHIGH); + uint32_t high = (uint32_t)esp_efuse_rtc_table_get_parsed_efuse_value(tag, false); + if (high != 0) *coeff_a = 65536u * v_high / high; + // v4.4: coeff_b = 0 + } +} +#endif +// ESP32-S3 & ESP32-C3 coefficient extraction matching IDF V4 +#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 +#include "hal/adc_types.h" +#include "esp_efuse_rtc_calib.h" + +static void getLegacyAdcCoeffs(uint32_t *coeff_a, uint32_t *coeff_b) { + *coeff_a = 0; + *coeff_b = 0; // v4.4: coeff_b = 0 on both targets + int ver = esp_efuse_rtc_calib_get_ver(); + if (ver != 1) return; // v4.4: ESP_ADC_CAL_VAL_NOT_SUPPORTED + + uint32_t digi = 0, voltage = 0; + // C3 ignores the unit arg (V1 calib exists only for ADC1); S3 uses it + esp_err_t ret = esp_efuse_rtc_calib_get_cal_voltage(ver, ADC_UNIT_1, ADC_ATTEN_DB_12, &digi, &voltage); + if (ret != ESP_OK || digi == 0) return; + + #if CONFIG_IDF_TARGET_ESP32S3 + *coeff_a = 1000000u * voltage / digi; // v4.4 S3: coeff_a_scaling = 1000000 + #else + *coeff_a = 65536u * voltage / digi; // v4.4 C3: coeff_a_scaling = 65536 + #endif +} +#endif // S3 or C3 +#else // not ESP32, S2, C3 or S3 and V5: read data from efuse BLOCK2 as salt +uint32_t get_calib_entropy(void) { + // Bytes 0-15 are OPTIONAL_UNIQUE_ID, which may be all-zero (undocumented feature) + // Bytes 16+ fall in the calibration-trim region (temp calib, ADC init codes, etc.), + // which IS reliably burned on every chip and varies die-to-die due to manufacturing variance. + uint8_t sys_data[32] = {0}; + esp_efuse_read_block(EFUSE_BLK2, sys_data, 0, sizeof(sys_data) * 8); // size is in bits + uint32_t entropy = 0; + for (int i = 16; i < 32; i++) entropy = entropy * 16777619u ^ sys_data[i]; + return entropy; +} +#endif // ESP32, S2, C3, S3 +#endif // IDF V5 +// AI: end + String generateDeviceFingerprint() { uint32_t fp[2] = {0, 0}; // create 64 bit fingerprint esp_chip_info_t chip_info; esp_chip_info(&chip_info); esp_efuse_mac_get_default((uint8_t*)fp); fp[1] ^= ESP.getFlashChipSize(); -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) fp[0] ^= chip_info.full_revision | (chip_info.model << 16); -#else + #else fp[0] ^= chip_info.revision | (chip_info.model << 16); -#endif + #endif -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) - // mix in ADC calibration data - legacy adc calibration API is not supported on new MCUs (-C5, -C6, -C61, -P4) + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + // mix in ADC calibration data - legacy adc calibration API is not supported on new MCUs (-C5, -C6, -C61, -P4) esp_adc_cal_characteristics_t ch; #if (SOC_ADC_MAX_BITWIDTH == 13) || (CONFIG_SOC_ADC_RTC_MAX_BITWIDTH == 13) // S2 has 13 bit ADC constexpr auto myBIT_WIDTH = ADC_WIDTH_BIT_13; #else constexpr auto myBIT_WIDTH = ADC_WIDTH_BIT_12; #endif - esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, myBIT_WIDTH, 1100, &ch); + esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, myBIT_WIDTH, 1100, &ch); // note: deprecated in IDF V5 hence the complicated workaround fp[0] ^= ch.coeff_a; fp[1] ^= ch.coeff_b; + // note: these curves are LUT, hardcoded and only on ESP32 if (ch.low_curve) { for (int i = 0; i < 8; i++) { fp[0] ^= ch.low_curve[i]; @@ -1366,11 +1501,24 @@ String generateDeviceFingerprint() { fp[1] ^= ch.high_curve[i]; } } -#else - // some extra salt, instead of ADC calibration - fp[0] ^= chip_info.features | chip_info.cores << 16; + #else // V5 + uint32_t coeff_a = 0, coeff_b = 0; + // get equivalent to V4 adc coefficients without using the deprecated esp_adc_cal_characterize() + getLegacyAdcCoeffs(&coeff_a, &coeff_b); // use ADC calibration coefficients + fp[0] ^= coeff_a; + fp[1] ^= coeff_b; // note: is zero on S3 and C3 as well as S2 "v2" + #if CONFIG_IDF_TARGET_ESP32 + // Mix in the pre-calculated LUT XOR sums to match pre 17.0 fingerprint + fp[0] ^= LUT_ADC1_LOW_XOR_8; + fp[1] ^= LUT_ADC1_HIGH_XOR_8; + #endif // ESP32 + #endif // V4 or V5 + + #else // ESP32 family but not classic ESP32, S2, S3 or C3 + fp[0] ^= get_calib_entropy(); // add BLOCK2 efuse values containing calibration data + fp[0] ^= chip_info.features | chip_info.cores << 16; // some extra salt fp[1] ^= ESP.getFlashSourceFrequencyMHz() | ESP.getFlashClockDivider() << 8 ; -#endif + #endif char fp_string[17]; // 16 hex chars + null terminator sprintf(fp_string, "%08X%08X", fp[1], fp[0]); return String(fp_string); From b09e0242e1a4e485aa6cde831aec9d99c90c6c7d Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 23 Jul 2026 06:36:24 +0200 Subject: [PATCH 5/6] add missing include just in case (seems not necessary for tested C6) --- wled00/util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/util.cpp b/wled00/util.cpp index f370d1e2dc..8ac46c77df 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -1452,6 +1452,7 @@ static void getLegacyAdcCoeffs(uint32_t *coeff_a, uint32_t *coeff_b) { } #endif // S3 or C3 #else // not ESP32, S2, C3 or S3 and V5: read data from efuse BLOCK2 as salt +#include "esp_efuse.h" uint32_t get_calib_entropy(void) { // Bytes 0-15 are OPTIONAL_UNIQUE_ID, which may be all-zero (undocumented feature) // Bytes 16+ fall in the calibration-trim region (temp calib, ADC init codes, etc.), From 1ccae3a5c3e8695886c0e6639e293223add0ac18 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 26 Jul 2026 19:34:22 +0200 Subject: [PATCH 6/6] re enable AR on ESP32 as bootloop is fixed --- platformio.ini | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/platformio.ini b/platformio.ini index 47da21b92e..9f69bf67bd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -772,8 +772,7 @@ board = esp32dev platform = ${esp32_idf_V5.platform} platform_packages = ${esp32_idf_V5.platform_packages} build_unflags = ${esp32_idf_V5.build_unflags} -;;custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds -custom_usermods = ;; AR usermod causes bootloops on classic esp32 +custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32\" #-D WLED_DISABLE_BROWNOUT_DET -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 lib_deps = ${esp32_idf_V5.lib_deps} @@ -787,7 +786,7 @@ extends = env:esp32dev ;;build_type = debug ;; disabled - leads to stack smashing in ArduinoJSON "Unhandled debug exception: Stack canary watchpoint triggered (loopTask)" monitor_filters = esp32_exception_decoder upload_speed = 921600 -custom_usermods = ;; audioreactive usermod crashes on classic esp32 +custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds build_unflags = ${esp32_idf_V5.build_unflags} -D WLED_RELEASE_NAME=\"ESP32\" ;; -DCORE_DEBUG_LEVEL=0 @@ -808,8 +807,7 @@ lib_ignore = ${esp32_idf_V5.lib_ignore} board = esp32dev platform = ${esp32_idf_V5.platform} platform_packages = ${esp32_idf_V5.platform_packages} -;;custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds -custom_usermods = ;; AR usermod causes bootloops on classic esp32 +custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds build_unflags = ${esp32_idf_V5.build_unflags} build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_8M\" #-D WLED_DISABLE_BROWNOUT_DET -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 @@ -825,8 +823,7 @@ board_upload.maximum_size = 8388608 board = esp32dev platform = ${esp32_idf_V5.platform} platform_packages = ${esp32_idf_V5.platform_packages} -;;custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds -custom_usermods = ;; AR usermod causes bootloops on classic esp32 +custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds build_unflags = ${esp32_idf_V5.build_unflags} build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_16M\" #-D WLED_DISABLE_BROWNOUT_DET -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 @@ -862,8 +859,7 @@ board = esp32-poe platform = ${esp32_idf_V5.platform} platform_packages = ${esp32_idf_V5.platform_packages} upload_speed = 921600 -;;custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds -custom_usermods = ;; AR usermod causes bootloops on classic esp32 +custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds build_unflags = ${esp32_idf_V5.build_unflags} build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_Ethernet\" -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 -D SR_DMTYPE=-1 -D AUDIOPIN=-1 -D I2S_SDPIN=-1 -D I2S_WSPIN=-1 -D I2S_CKPIN=-1 -D MCLK_PIN=-1 ;; force AR to not allocate any PINs at startup @@ -882,8 +878,7 @@ board = ttgo-t7-v14-mini32 board_build.f_flash = 80000000L board_build.flash_mode = qio board_build.partitions = ${esp32.extended_partitions} -;;custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds -custom_usermods = ;; AR usermod causes bootloops on classic esp32 +custom_usermods = ${common.default_usermods} ;; warning: audioreactive analog mic support had to be removed in V5 builds build_unflags = ${esp32_idf_V5.build_unflags} build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} -D WLED_RELEASE_NAME=\"ESP32_WROVER\" -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3