adafruit / Adafruit_NeoPixel

Arduino library for controlling single-wire LED pixels (NeoPixel, WS2812, etc.)
GNU Lesser General Public License v3.0
3.07k stars 1.27k forks source link

ESP32 WROOM-32 WDT timeout arduino framework 2.0.0 #357

Closed sascha432 closed 1 year ago

sascha432 commented 1 year ago

Hi,

I recently compiled my ESP8266 code for ESP32 and had trouble with FastLED and multiple PINs. So I gave NeoPixel a shot, but I ran into issues with a single PIN.

The versions I tried were master, 1.11.0, 1.10.7 and 1.6.1. 1.6.1 seem to behave differently, but since it is old I did not play around with it a lot.

After starting, it seems to update the LEDs (16) one time, but the colors seem wrong. After one second (or less) they turn off and I get a WDT timeout and reset. There is not much information, no trace or anything...

All code runs in the loop() functions, no timers for animations or updating (show, setBrightness). So it should be running on core 1 only.

It is a custom board with a SN74AHCT125DR level shifter, so the timings are very accurate. The ESP8266 works with a single mosfet level shifter, timings are pretty bad compared to the SN74, but the same code works with FastLED, NeoPixel and my own implementation.

FastLED works fine with a single channel, accurate colors, no timeouts etc... I also tried WLED to rule out any hardware issues and there it works with all 4 channels and many LEDs (I tried 4x512). I did not write my own RMT driver for ESP32 yet.

Here is the info about the framework and hardware

NEO_GRB + NEO_KHZ800 (WS2812B)
Framework Arduino ESP32 2.0.0
ESP-IDF version v4.4-dev-2313-gc69f0ec32
Free heap/fragmentation: 139371 / 0
CPU frequency: 240MHz
Chip model ESP32 (ESP32-D0WDQ6)

The serial output

ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1100
ho 0 tail 12 room 4
load:0x40078000,len:12280
ho 0 tail 12 room 4
load:0x40080400,len:3076
entry 0x400805ec
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1100
ho 0 tail 12 room 4
load:0x40078000,len:12280
ho 0 tail 12 room 4
load:0x40080400,len:3076
entry 0x400805ec
sascha432 commented 1 year ago

Finally I got a stack trace .. it crashed in ESP32RMTController::interruptHandler(void *arg) of FastLED. Seems I called FastLED.show() before using NeoPixel. Removing the show() call fixed the issue.

I added a method to deinitialize FastLED, that I can switch back and forth.

void ESP32RMTController::deinit()
{
    if (!gInitialized) return;

    if (gTX_sem) {
        xSemaphoreTake(gTX_sem, portMAX_DELAY);
    }

    if ( ! FASTLED_RMT_BUILTIN_DRIVER) {
        // -- Deallocate the interrupt if we have one
        if (gRMT_intr_handle != NULL)
            esp_intr_free(gRMT_intr_handle);
            gRMT_intr_handle = NULL;
    }

    if (gTX_sem != NULL) {
        xSemaphoreGive(gTX_sem);
        vSemaphoreDelete(gTX_sem);
        gTX_sem = NULL;
    }

    for (int i = 0; i < gMaxChannel; i += gMemBlocks) {
        gOnChannel[i] = NULL;

        if (FASTLED_RMT_BUILTIN_DRIVER) {
            rmt_driver_uninstall(rmt_channel_t(i));
        } else {
            // -- Disable the RMT transfer
            rmt_set_tx_thr_intr_en(rmt_channel_t(i), false, PULSES_PER_FILL);
        }
    }

    // the next show() call will initialize the RMT controller again
    gInitialized = false;
    gNumStarted = 0;
}