Kaisha wrote:
I'm trying to understand the difference (if there is one) between the Free RTOS portMUX_TYPE mutex and the SemaphoreHandle_t mutex. Are they both the same thing 'under the hood'?
No they are not.
- portMUX_TYPE is a spinlock (name is a bit confusing). Spinlocks are a form of hardware mutual exclusion which prevents both CPUs on the ESP32 from accessing the same piece of shared data A spinlock is simply a hardware bit which a CPU must set (i.e., take the lock) before it can access shared data. If both CPUs simultaneously take the spinlock, one CPU will spin (busy wait) until the lock is released by the other CPU. Both CPUs have their interrupts disabled whilst holding/contesting the spinlock.
- SemaphoreHandle_t is a handle to either a FreeRTOS Binary Semaphore, FreeRTOS Counting Semaphore, or FreeRTOS Mutex. A FreeRTOS mutex implements mutual exclusion at the task level (i.e., two or more tasks are allowed to simultaneously hold a mutex). If a task attempts to take an already taken mutex, that task will block until the mutex is released. This allows the CPU to schedule another task.
Kaisha wrote:
On various forums it has been suggested to use a local portMUX_TYPE mutex to disable the Free RTOS scheduler, does that also work with SemaphoreHandle_t type mutexs?
No, mutexes do not disable scheduling. Spinlocks are able to disable scheduling on a particular CPU because a spinlock disables interrupts. Scheduling requires interrupts to be enabled. Mutexes simply block a task if the task is unable to take the mutex. There is also some task priority inheritance that goes on in the background with FreeRTOS mutexes.
Kaisha wrote:
Is there a better way to prevent task switching for critical sections?
Depends on what type of "critical section" you want. Do you want mutual exclusion at the task level or had the hardware level? Or do you simply want to disable task switching?
- If you have data that is shared by both CPUs and between tasks and ISRs, use a spinlock portMUX_TYPE
- If you have data that is only shared between tasks, use a FreeRTOS mutex.
- If you simply want to run a piece of code with the task switching disabled for a while, use vTaskSuspendAll()