Repository navigation
The FastLed RMT driver makes extensive use of interrupts. The comments in the FastLED driver hint at least one per 32 bits of data out. The driver does all the sending in one hit so that even with multiple controllers (as we have in this demo) it is only when the last one is called does it finally does the work. I am uncertain what might happen if only one controller that is not the last one is called. (For a future experiment). On a send, it waits 50 microseconds to signal a start, then starts the channels for each controller. It then sets a semaphore which is then released when the final channel on the final controller is complete. It appears that rarely something goes wrong here, and presumably, that interrupt is swallowed by the Esp32 system. The result is that ESP32RMTController::showPixels() waits forever for the semaphore to be released (which it never will be) so we have a hang. Note that this hang will occur minutes or hours into a run, depending on other factors (like load or power), and is essentially out of the control of the FastLED driver.
The quick and dirty fix is simply to assign some timeout value to the semaphore take rather than portMAX_DELAY (line 204 for version 3.6.0 and line 223 for version 3.7.0).
We do this by this change by defining FASTLED_RMT_MAX_TICKS_FOR_GTX_SEM to a value like (2000/portTICK_PERIOD_MS) before we call FastLED.h (see clockless_rmt_esp32.h). Alternatively, we can call GiveGTX_sem(); which has been added to clockless_rmt_esp32.cpp so we can programmatically decide on the wait time.