Page 1 of 1

Need for CRITICAL sections on ESP32 freeRTOS/SMP?

Posted: 14 Jan 2024, 11:23
by martinus
Question not directly related to ESPEasy firmware, but more coding for ESP32 in general.

I'm working on an updated version of my custom ESPNOW protocol handling because a single variable would sometimes loose an event from the callback routine if the main loop is too busy.
So i've implemented a ringBuffer queue to store incoming events for later processing. It works but a few times per day, it shows an incorrect buffer overload state, likely due to not properly protecting the pointer updates that would be needed on a freeRTOS/SMP environment.

After some further reading, it seems that the ESPNOW callback is done from a high-prio Wifi task running on CPU0 while the main app loop is running on CPU1.
This could impose unpredictable result on the shared ringBuffer being updated/checked from different cores/tasks.

So i've implemented this approach:

portENTER_CRITICAL(&mux);
.. manipulate buffer pointers and structure data
portEXIT_CRITICAL(&mux);

That solves the issues, but is this the best and proper way to protect the global datastructure for the SMP RTOS environment that runs on ESP32?
It seems that many comments found on the internet like just using atomic variable, using taskdelay and such, only apply to stock freeRTOS on a single core MCU.

Re: Need for CRITICAL sections on ESP32 freeRTOS/SMP?

Posted: 14 Jan 2024, 13:47
by TD-er
You can also store your data in pre-allocated buffers and set a (volatile) flag indicating you need to inspect it from the other thread/core/task
This way you don't need to use critical sections, which may cause some odd side-effects.
N.B. critical section on SDK2.x (ESP-IDF 4.3 and earlier) did appear to have a non working critical section, at least when using the Arduino code.
This caused all kinds of issues when it suddenly was fixed :)