Mutex Semaphores Failing After Multiple xSemaphoreTake

Hello, I am using FreeRTOS 7.3 on an ARM processor. I am trying to create a semaphore mutex to protect some hardware devices, but I am not currently having a whole lot of success as the mutex’s are not holding the state like they should and multiple access to the same hardware device is causing a bus collision. I declare them ~~~ volatile xSemaphoreHandle Sema1; volatile xSemaphoreHandle Sema2; ~~~ And then initialize with ~~~ Sema1 = xSemaphoreCreateMutex(); Sema2 = xSemaphoreCreateMutex(); ~~~ As seen in the example https://www.freertos.org/a00122.html I then want to check that they have been initialized and I should be able to take the semaphore right away. ~~~ int semainit(void){ if( Sema1 == NULL ){ /* Insufficient FreeRTOS heap to create */ return -1; } else { /* Semaphore can now be used */ xSemaphoreTake(Sema1, portMAXDELAY); } if( Sema2 == NULL ){ /* Insufficient FreeRTOS heap to create / return -1; } else { / Semaphore can now be used */ xSemaphoreTake(Sema1, portMAX_DELAY); } } ~~~ In my code, I then call an open routine in order to “hold” each device and prevent the other one from carrying out its task on that hardware device. ~~~ void deviceopen(int device){ switch(device){ case device1: xSemaphoreTake(Sema1, portMAXDELAY); break; case device2: xSemaphoreTake(Sema2, portMAX_DELAY); break; } } ~~~ And the close routine: ~~~ void device_close(int device){ switch(device){ case device1: xSemaphoreGive(Sema1); break; case device2: xSemaphoreGive(Sema2); break; } } ~~~ After following this discussion, I thought I could take the mutex multiple times. With this solution, the code crashes immediately on the second take. That is, when I switch on device1 in the device_open() routine it fails. However, when I leave out the xSemaphoreTake() in the initialization, the semaphores do not hold the device properly and allow for bus interference! What is the proper way to implement these mutex semaphores so that device2 cannot initialize until device1 has finished its routine? Thank you for your time!

Mutex Semaphores Failing After Multiple xSemaphoreTake

If you want to be able to take a given mutex multiple times by the same thread and succeed (and then give it back the same number of times) you need to use a Recursive Mutex.

Mutex Semaphores Failing After Multiple xSemaphoreTake

Sorry for the beginner question but how does this differ from the functionality of a binary semaphore?

Mutex Semaphores Failing After Multiple xSemaphoreTake

A Binary Semaphore is an object that has a flag that says it is either ready or not (or Full or Empty). A take operation will wait for the flag to be ‘ready’ and then make it not ready. A put operation will wait for it to be not ready and then make it ready. This can be used as a method of exclusive access by starting the flag ready and then when a task wants the resource it takes the flag, and when done if gives the flag. It can also be used to syncronize a task with anther task (or ISR), by the task waiting for the flag, and then the other task (or ISR) giving it. One issue with using a semaphore for mutual exclusion is if a low priority task takes the mutex, and then a high priority want it, it must wait, and even if a task with a middle priority starts to run, the middle priority task will run, delaying the high priority task, this is called priority inversion. A mutex is a specialization on this to solve this issue. A mutex should only be used for mutual exclusion (which is what its name is a contraction of). A task wanting that resource takes the flag, and when done it gives the flag back. Unlike a semaphore, the mutex remembers who has the flag, and that is who is supposed to give it back, so it can’t be used in the second sort of operation. It gets around the priority inversion condition by when the high priority task requests the mutex, the low priority task is temporarily given the priority of the high priority task. With a reqular mutex, when a task takes the flag, the mutex is not ready, even if the same task ask for the flag again, so it will wait/deadlock. A modification on this is a recursive mutex. The recursive mutex will always be ready for the task that currently has the flag, and the flag is only actually given back when that task has given the flag back as many times as it was taken. This is not the default behavior in FreeRTOS due to the way they are implemented.

Mutex Semaphores Failing After Multiple xSemaphoreTake

Thank you for your explanation. It definitely makes sense given the priorities since this is a shared hardware bus. It doesn’t matter whether a higher priority task comes along if a lower priority task is currently on the bus – it is to prevent the corruption of this kind of information. This solution worked and I did not have to use a recursive mutex – just a single mutex for the hardware application. Thank you!