I have a battery powered product with a Task Alarm.
It is listening to notifications with a value, the value means how many times the alarm melody should be played.
I had the issue that my microcontroller goToSleep() function puts itself to sleep while the melody was not fully played.
My idea was to work with a binary semaphore take/give so my goToSleep() function could check if the melody is done playing.
As soon as I put xSemaphoreTake() into the code, no alarm will ever played.
The AlarmMelodyBusySemaphore != NULL is True.
Its the next line xSemaphoreTake that somehow is not True
Did you make sure the semaphore was given originally? If I remember right, depending on how you create the semaphore will determine if it is created taken or given.
I have to do a Give on top of my alarm task (above the while(1))
My semaphore is created in my main loop and Taken by default.
So why are Binary semaphore already taken on creation?
I found the following documentation:
Note that binary semaphores created using the vSemaphoreCreateBinary() macro are created in a state such that the first call to âtakeâ the semaphore would pass, whereas binary semaphores created using xSemaphoreCreateBinary() are created in a state such that the the semaphore must first be âgivenâ before it can be âtakenâ.
But most examples on freertos donât show this âgive before takeâ order
[UPDATE] The xSemaphoreGive and xSemaphoreTake documentation examples are using mutex and not binary semaphores. A bit confusing.
You use Give (in task A) triggering a Take (in task B) as a typical data-ready signal, which is the actual main use of semaphores, and that wants the semaphore to start in the Taken state. When using it as an alternative to a Mutex, which would be preferred for that purpose, you would want it to start in the Given state.
I would say that in my code, almost all of the uses of semaphore are in cases where I want the semaphore to start in the taken state.
(Note, xSemaphoreGive and xSemaphoreTake are used for non-recursive mutexs.)
It is not only about debugging. If you unconditionally release a mutex/semaphore in the âclaim successâ return branch (meaning also when it has not been taken successfully), your results may be unpredictable.
Also, I second Richardâs observations of semaphores vs. muteces. Unfortunately, the term âsemaphoreâ has found its way into multithreading folklore as the âone concept fits allâ solution to sync problems, supported among other things by FreeRTOSâ naming of the claim/release functions (as well as the historic tidbit that when Dijkstra introduced semaphores into computing many moons ago, there simply wasn 't anything else). As Richard points out correctly, in many many cases where semaphores are being used in practice, muteces would be the superior solution.
Actually, I see it as âSemaphoreâ is used as a very generic term relating to a general form of synchronization primitive. Note, FreeRTOS doesnât have a way to create a âplainâ Semaphore, but you create one with a specific nature of Binary, Counting, Mutex, or RecursiveMutex. The Give/Take functions work for all the types except RecursiveMutex, which needs its own routines.
So, when @sprucify created his Semaphore, it seems they created a âBinaryâ Semaphore, which has two different create routines, a much older one supported for legacy code that creates the semaphore âgivenâ, and the current one that creates it âtakenâ. I wouldnât be surprized if the older one predates the addition of Mutexes to FreeRTOS, in which case âgivenâ might well be the most wanted state. Now that we have Mutexes, and they should be used in most cases needing a Mutex, the âtakenâ state of the âcurrentâ version is much more likely.