High priority, uninterruptible ISR interrupt [ESP32]

Hi everyone,
I’m working on a project with Mongoose OS and trying to achieve temporal dithering with the WS2812B LEDs .

Everything is working using the mgos_set_hw_timer function (running at about 500Hz) but I noticed that sometimes (especially when there is a lot of network traffic) the function hangs for ~1/2 uS and this disrupts the ws2812b bit-banging causing flashes of color on the LED strip. This has been confirmed by using a logic analyzer: the timing gets completely disrupted.

Futher info: the ESP32 runs at 240MHz, the bit-banging part takes ~300uS to complete.

I’ve tried to enclose the function mgos_neopixel_show in taskENTER_CRITICAL_ISR(&mux); as well as raising the interrupt handler level but without luck. I also tried to pin the hw timer to the core 0 but then the glitches were even more.

Using mgos_lock and mgos_unlock caused a core dump.

Is there a way to actually make a block of code running in ISR context actually uninterruptible?

I’m no expert on ESP32 hardware.
Is your interrupt delayed and occurs after proper time, or is your interrupt preempted by a higher priority interrupt ? I guess you mean this latter case.
What you need is some form of raising the priority of your desired interrupt above all other exceptions, or even disabling interrupts while servicing the one handling your LEDs; what you probably already did. This may work or may wreak havoc at the WiFi level or the RTOS level. Perhaps you should work with the IDF and freeRTOS tools for handling critical sections outside mOS (another independent freeRTOS task) (use spinlocks/etc. to disable other interrupts).
Given today’s microcontroller prices devoting an 8-bitter for this task might be a better/simpler solution, or use one of the built-in peripherals to reduce the timing criticality to more manageable levels.

1 Like

I saw this same behaviour, and the worst part was it was almost impossible to know when it would case an issue. I started a thread here that I think may help you solve the Neopixel issue by using the RMT feature to drive the leds.

I never got around to contributing the code back to the neopixel library as it was basically a rewrite of the bit-bang method so didn’t seem like a straightforward fix, plus I had no idea how to properly fix the ESP-IDF dependency.
@TheCrypt0 if you’re struggling let me know and I’ll find a way to share it with you.

1 Like

Thank you for the suggestion! Honestly I haven’t thought about it, but if it’s <0.5$ it might be worth considering.
Honestly at that price price range I only worked with the AtTiny85, but I’m not sure if it could handle driving the WS2812B at ~500Hz as well as handling some form of communication with the main MCU.

Do you happen to have any suggestion for any uC that could fit the purpose?

Great, thank you! Never thought about using the RMT peripheral this way. I managed to port the neopixel library to include the ESP-IDF ws2812b RMT library and it seems like the problem has now been reduced but not completely eliminated. After testing it I still see some flashes of light (although much less frequently!) and some inconsistencies with the timing.

From what I can see the functions of the RMT peripheral can’t be called from ISR context (crash with following core dump), so I had to move them to an RTOS Task. Unfortunately the latter is much more inconsistent with the timings (even when the priority is raised) than using an hw timed interrupt.

Have you encountered the same issues? If not, it is entirely possible that I’m doing something wrong.

Lots of microcontrollers in that price range, unless you’re thinking of buying just 1.

That sucks. I’ve not seen this as yet, but I’m not updating the LEDs very frequently.

Just a thought, but when when I was trying to debug I found it quite useful to test the hardware limitations using Arduino as there were way more libraries and examples/experience. In my case the limitation was not in hardware but software, so I managed to work around it with the RMT feature.