Skip to content

Classic ESP32: GPIO17 is not needed to be reserved for chips with in-package PSRAM#5338

Open
wled-install wants to merge 2 commits intowled:mainfrom
wled-install:patch-3
Open

Classic ESP32: GPIO17 is not needed to be reserved for chips with in-package PSRAM#5338
wled-install wants to merge 2 commits intowled:mainfrom
wled-install:patch-3

Conversation

@wled-install
Copy link
Contributor

@wled-install wled-install commented Feb 2, 2026

Fix for #5334

Edit (softhack007): The change relies on the framework knowing about the "ESP32-D0WDR2-V3" chip model - available since arduino-esp32 v2.0.7. It means that only "V4" builds will allow using GPIO17. WLED 0.15.3 is still using the older framework, only WLED 0.16 will be able to detect the "ESP32-D0WDR2-V3" chip properly.

Summary by CodeRabbit

  • Bug Fixes
    • Improved GPIO compatibility checks for ESP32 devices with external memory, enhancing detection of available pins across different module variants and memory configurations. This update better handles device-model-specific cases to reduce false negatives and ensure more reliable pin availability reporting on affected hardware.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 2, 2026

Walkthrough

Refined ESP32 pin validation in the pin manager: GPIO16 now uses a direct PSRAM absence check; GPIO17 gains a chip-model branch permitting it on ESP32-D0WDR2-V3 while other variants follow PSRAM-based rules. Other pin behaviors remain unchanged.

Changes

Cohort / File(s) Summary
Pin manager update
wled00/pin_manager.cpp
Reworked ESP32-specific pin validation: split handling for GPIO16 and GPIO17, added model-specific branch for ESP32-D0WDR2-V3 to allow GPIO17, retained PSRAM-based checks for other cases.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: GPIO17 handling for ESP32 chips with in-package PSRAM, which aligns with the code changes that add model-aware branching for GPIO 17.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Failure to add the new IP will result in interrupted reviews.


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.

@softhack007
Copy link
Member

softhack007 commented Feb 2, 2026

I think we need more testing with classic esp32 that have psram, to confirm that pin17 is only allowed when the board supports it.

The test can be quite simple

  1. change led pin to 17 -> if it crashes, the change is not good enough.
  2. change led pin to 17, create a large 2D setup where the buffer usually is going into PSRAM -> if it crashes, ...

I have a wrover-b and a lilygo-t7 with psram in my collection, but I'll need a few days before I can test. If anybody else has another classic esp32 with PSRAM, please feel invited to test.


Edit:
First tests (but we need more tests with other boards!)

  • Lilygo T7 v1.5 identifies as "ESP32-D0WD-V3" (rev 3.0), needs GPIO 16&17 for PSRAM - crashes (bootloop) when assigning GPIO17 to LEDs
  • Freenove wrover-E-cam identifies as either "ESP32-D0WDQ5" (older framework) or "ESP32-D0WD-V3" (newer frameworks), needs GPIO 16&17 for PSRAM
  • noname WROVER-B: identifies as "ESP32-D0WD" (rev.1 chip, without "V3")

@softhack007 softhack007 added enhancement board request PR adding support for a specific board. Awaiting testing labels Feb 2, 2026
@wled-install
Copy link
Contributor Author

@softhack007
Thank you for results!!! So, the proposed solution should work as your boards with off-package PSRAM should use GPIO17, so you cannot use it for LEDs. As they are not reported as ESP32-D0WDR2-V3, everything fine.

Actually in my tests only WLED 0.16.x works reliable with PSRAM, 0.15.x (if not esp-idf4 used) crashes whatever I do.

@softhack007
Copy link
Member

Thank you for results!!! So, the proposed solution should work as your boards with off-package PSRAM should use GPIO17, so you cannot use it for LEDs. As they are not reported as ESP32-D0WDR2-V3, everything fine.

@wled-install yes for all the 3 boards in my collection the change is safe.
I hope that another maintainer also has a classic esp32 with PSRAM. If we get a few more "ok" tests, then the change can be merged.

Actually, in my tests only WLED 0.16.x works reliable with PSRAM, 0.15.x (if not esp-idf4 used) crashes whatever I do.

same here - I never got any PSRAM boards working with the old "AC" framework. It seems that PSRAM boards always need a V4 build.

@DedeHai
Copy link
Collaborator

DedeHai commented Feb 4, 2026

I have one classic WROVER, not sure which model. will check.
btw. I at one point did remove psramFound() as all it really does is to check if BOARD_HAS_PSRAM is defined. I either did not commit that or it got stuck in PR limbo.

@softhack007
Copy link
Member

softhack007 commented Feb 4, 2026

psramFound() as all it really does is to check if BOARD_HAS_PSRAM is defined.

@DedeHai side-discussion:
I just tried to follow the logic in esp32-hal-psram.c (arduino-esp32 v2.0.9) - the code i found is a bit more complicated.

My understanding is:

  • if you don't have BOARD_HAS_PSRAM, psramFound() is always false
  • psramFound() = false can also happen if your firmware was build with BOARD_HAS_PSRAM, but the chip does not have PSRAM.
  • if CONFIG_SPIRAM_BOOT_INIT is set (?bootloader aborts if no PSRAM?), all checks in psramInit() are skipped.
  • (!) otherwise the returned value depends on some EFUSEs, plus a short functional test with testSPIRAM().

-> psramFound() == false might also indicate that support is available (BOARD_HAS_PSRAM), but PSRAM is not working

-> For PIN allocation, relying on psramFound() might be dangerous in one case: a broken PSRAM chip does not mean you can use PSRAM pins freely
-> ps_malloc() internally checks psramFound(), and returns NULL when no PSRAM. I think that heap_caps_malloc_prefer(...) can also handle "no PSRAM" gracefully.


bool ARDUINO_ISR_ATTR psramFound(){
    return spiramDetected;
}

void ARDUINO_ISR_ATTR *ps_malloc(size_t size){
    if(!spiramDetected){
        return NULL;
    }
    return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
}
void initArduino()
{
#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
    psramInit();
#endif
static volatile bool spiramDetected = false;

bool psramInit(){
    if (spiramDetected) {
        return true;
    }
#ifndef CONFIG_SPIRAM_BOOT_INIT
    if (spiramFailed) {
        return false;
    }
#if CONFIG_IDF_TARGET_ESP32
    uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
    uint32_t pkg_ver = chip_ver & 0x7;
    if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
        spiramFailed = true;               // <-- HERE  check failed
        log_w("PSRAM not supported!");
        return false;
    }
#elif CONFIG_IDF_TARGET_ESP32S2
    extern void esp_config_data_cache_mode(void);
    esp_config_data_cache_mode();
    Cache_Enable_DCache(0);
#endif
    if (esp_spiram_init() != ESP_OK) {
        spiramFailed = true;               // <-- HERE check failed
        log_w("PSRAM init failed!");
#if CONFIG_IDF_TARGET_ESP32
        if (pkg_ver != EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
            pinMatrixOutDetach(16, false, false);
            pinMatrixOutDetach(17, false, false);
        }
#endif
        return false;
    }
    esp_spiram_init_cache();
    //testSPIRAM() allows user to bypass SPI RAM test routine
    if (!testSPIRAM()) {
        spiramFailed = true;               // <-- HERE  check failed
        log_e("PSRAM test failed!");
        return false;
    }
    if (esp_spiram_add_to_heapalloc() != ESP_OK) {
        spiramFailed = true;              // <-- HERE check failed
        log_e("PSRAM could not be added to the heap!");
        return false;
    }
#if CONFIG_SPIRAM_USE_MALLOC && !CONFIG_ARDUINO_ISR_IRAM
    heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
#endif
#endif /* CONFIG_SPIRAM_BOOT_INIT */
    log_i("PSRAM enabled");
    spiramDetected = true;                // <-- HERE all checks passed
    return true;
}

@DedeHai
Copy link
Collaborator

DedeHai commented Feb 4, 2026

my info may be outdated, at the time (few months ago), I think it was discussed several times but no conclusion reached: if PSRAM is enabled on ESP32, it also requires that compile fix to support the chips with that silicon bug. I am not sure on the best way to solve it in general (not this PR). Ideally we would have one single build for all ESP32 classic variants, no matter if it has PSRAM or not, I am not aware of all pitfalls for that though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Awaiting testing board request PR adding support for a specific board. enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants