Need for CRITICAL sections on ESP32 freeRTOS/SMP?
Posted: 14 Jan 2024, 11:23
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.
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.