Makuna / NeoPixelBus

An Arduino NeoPixel support library supporting a large variety of individually addressable LEDs. Please refer to the Wiki for more details. Please use the GitHub Discussions to ask questions as the GitHub Issues feature is used for bug tracking.
GNU Lesser General Public License v3.0
1.18k stars 264 forks source link

ESP32 I2S#1 8x parallel driving and audio input on I2S#0 #697

Closed softhack007 closed 1 year ago

softhack007 commented 1 year ago

Describe the bug using NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1X8Ws2812xMethod> alone works well (and very good framerates :-) ), however my firmware becomes unstable if I also use I2S#0 for microphone input.

this is a sample crash dump. The first two lines are WLED debug info:

heap 141292
loopTask min free stack 4276

abort() was called at PC 0x401ded6b on core 1

Backtrace:0x4008494d:0x3ffb25400x4008dbf5:0x3ffb2560 0x40093b25:0x3ffb2580 0x401ded6b:0x3ffb2600 0x401dedb2:0x3ffb2620 0x401df0f3:0x3ffb2640 0x401df052:0x3ffb2660 0x401df15d:0x3ffb2680 0x401532a2:0x3ffb26a0 0x4012f011:0x3ffb26e0 0x40141427:0x3ffb27c0 0x40141589:0x3ffb2800 0x4016a951:0x3ffb2820 

  #0  0x4008494d:0x3ffb2540 in panic_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/panic.c:402
  #1  0x4008dbf5:0x3ffb2560 in esp_system_abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/esp_system.c:128
  #2  0x40093b25:0x3ffb2580 in abort at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/newlib/abort.c:46
  #3  0x401ded6b:0x3ffb2600 in __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:47
  #4  0x401dedb2:0x3ffb2620 in std::terminate() at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:57
  #5  0x401df0f3:0x3ffb2640 in __cxa_throw at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:95
  #6  0x401df052:0x3ffb2660 in operator new(unsigned int) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54
  #7  0x401df15d:0x3ffb2680 in operator new[](unsigned int) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/new_opv.cc:32
  #8  0x401532a2:0x3ffb26a0 in WiFiUDP::parsePacket() at C:/Users/Frank/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src/WiFiUdp.cpp:210
  #9  0x4012f011:0x3ffb26e0 in handleNotifications() at wled00/udp.cpp:235
  #10 0x40141427:0x3ffb27c0 in WLED::loop() at wled00/wled.cpp:111
  #11 0x40141589:0x3ffb2800 in loop() at D:/ARDUINO_Work/WORK/#ESP32/WLED_soundreactive-GitHub_DEV/WLED_MoonModules/WLED_mdev_clean/wled00/wled00.ino:20
  #12 0x4016a951:0x3ffb2820 in loopTask(void*) at C:/Users/Frank/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:50

--> It seems that the crash happens in WiFiUdp.cpp:210, however it only happens when I also use I2S#0 for microphone, so there seems to be some side-effects or I2S arbitration "troubles". I'll provide more information in the next days...

To Reproduce

Possibly I'm over-greedy on DMA buffers? I can check later if the crash happens also with a "normal" (8 buffers @ 128 samples each) config.

NB: I know this is not the best way to help analyze what's going wrong. I'll add more information later. Need some time to strip-down WLED to make a "reproducible example" out of it.

Expected behavior It should be possible to use NeoEsp32I2s1X8 (on I2S#1) and at the same time use I2S#0 for audio.

Development environment (please complete the following information): NeoPixelBus 2.7.5, using NeoPixelBrightnessBus.h (not sure if it will happen with NeoPixelBusLg.h, too) platformio (platform = espressif32@ ~5.2.0)

PLATFORM: Espressif 32 (5.2.0) > ESP32 16MB PACKAGES:

  • framework-arduinoespressif32 @ 3.20005.220925 (2.0.5)
  • tool-esptoolpy @ 1.40201.0 (4.2.1)
  • toolchain-riscv32-esp @ 8.4.0+2021r2-patch5
  • toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch3

Minimal Sketch that reproduced the problem: I'll need some more time to make the crash reproducible without my WLED dev version. Maybe you already have an idea, so investigation can start already?

Additional context It works without problem when using NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1Ws2812xMethod> on I2S#1, and microphone input on I2S#0 (same parameters).

softhack007 commented 1 year ago

I could also use I2S#1 for audio, and try I2S#0 with Neopixelbus. Do you think it might make a difference to swap busses?

Makuna commented 1 year ago

I2s0 has some quirks to it. It doesn't really have a x8 mode so avoid it as you will waist memory unless you are using x16 mode.

Note that memory use for the parallel mode is times 8 (in x8 mode) of the longest strip. So, if possible, spread the LEDs across strips rather than a single large strip with a bunch of smaller strips.

It is really throwing an exception, not a crash per se. Checking eh_throw.cc:95 might tell you what exception it is throwing. But more than likely out of memory.

What is at "libraries/WiFi/src/WiFiUdp.cpp:210" ? It looks like it is allocating memory using new and this is failing due to not enough memory (or large enough single free memory block).

Check your free memory, you may be running into that the ESP32 just can't support what you are asking of it.
If your available free memory is good, then you are running into fragmentation issues where a single free memory block is not large enough. This isn't that uncommon if you have things (libraries/your code) allocating memory and freeing it often (like UDP packets?). There are approaches to abstract allocations of common sized items, memory allocation pools.

NeoPixelBus allocates all needed memory by the time strip.Begin() returns; and doesn't allocate more within the Bus after that.

softhack007 commented 1 year ago

Yes it could be a memory problem, as my crash dump is completely unrelated to NeoPixelBus. WiFiUdp.cpp:210 does char * buf = new char[1460]; which should work as there should be plenty of RAM left.

The only strange thing is the crash does not occur when using NeoEsp32I2s1 or NeoEsp32RmtN instead of NeoEsp32I2s1X8. I'll keep digging during the next week or so, and let you know in case I find a clearer relation to NPB I2S#1 8x.

Please consider this report as "unconfirmed" for the time being.

Thanks for sharing your thoughts 👍

Makuna commented 1 year ago

BTW, your source for WiFiUdp.cpp doesn't match mine. The line number isn't at the same spot (a few lines off) and the code on mine isn't using new.

(line 212) char *buf = (char *)malloc(1460);

Are you using a newer version or older version? I have v2.0.8 board support for Arduino IDE.

softhack007 commented 1 year ago

Are you using a newer version or older version? I have v2.0.8 board support for Arduino IDE.

I'm using v2.0.5 - if your v2.0.8 source is different, than maybe espressif has fixed a memory leak in the function; I'll take a look, thanks again 👍

Update: yes it was a bugfix in v2.0.8:

softhack007 commented 1 year ago

Hi, I'll close this one, as it seems that all my problems were related to low heap and heap fragmentation.

For comparison, I've used a test config with 5 x 480 LEDs (ws2812b); 2400 Leds in total, equally distributed over 5 pins. --> 4 x RMT driver + I2S#1 driver -> loop time: 20ms - 21ms; Free heap: 125932, min free: 121524 --> I2S#1 8x parallel driver, utilizing 5 pins -> loop time: 3ms - 20ms; free heap: 66940, min free: 42196

consequences of low heap: -> WifiUDP throwing errors on new or malloc --> fix in arduino-esp32 2.0.9 -> Wifi dies due to low memory. -> other system instabilities.

So as you already explained, the new driver is much more CPU efficient in this setup, however it also reduces free memory dramatically compared to other ESP32 methods we use in WLED.