Internals of Synchronization
In modern embedded systems, there are two very vital synchronization primitives called Mutex and Semaphore. These two primitives are provided by RTOSs but they can be applied to bare-metal systems. Firmware engineers who are highly experienced consider it best practice to use these primitives as they can improve the logic flow and make the code easier to use and understand.
Generally, mutexes support two basic functions: lock and unlock. The functions that a semaphore supports are take and give. Mutexes are used for the protection of individual resources. A mutex functions as a lock and it is owned by a single process. On the other hand, semaphores can be used for shared access to multiple resources, and since they are used to coordinate multiple resources, they are not owned by a single process.
Give and take are the two operations that a semaphore supports. The “take” function can block calling codes until a resource is available. The “give” function, on the other hand, cannot block, and once a resource is available, the function informs a task that is waiting. Both the functions for mutex (lock & unlock) and for the semaphore (take and give) must take place in matching pairs.