2 // close group struct osMutexAttr_t
3 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
4 // ==== Mutex Management ====
6 \addtogroup CMSIS_RTOS_MutexMgmt Mutexes
8 \brief Synchronize resource access using Mutual Exclusion (Mutex).
10 <b>Mutual exclusion</b> (widely known as \b Mutex) is used in various operating systems for resource management. Many
11 resources in a microcontroller device can be used repeatedly, but only by one thread at a time (for example communication
12 channels, memory, and files). Mutexes are used to protect access to a shared resource. A mutex is created and then passed
13 between the threads (they can acquire and release the mutex).
15 \image html "Mutex.png" "CMSIS-RTOS Mutex"
17 A mutex is a special version of a \ref CMSIS_RTOS_SemaphoreMgmt "semaphore". Like the semaphore, it is a container for
18 tokens. But instead of being able to have multiple tokens, a mutex can only carry one (representing the resource). Thus, a
19 mutex token is binary and bounded. The advantage of a mutex is that it introduces thread ownership. When a thread acquires a
20 mutex and becomes its owner, subsequent mutex acquires from that thread will succeed immediately without any latency. Thus,
21 mutex acquires/releases can be nested.
24 - Mutex management functions cannot be called from interrupt service routines (ISR), unlike a binary semaphore that can be
29 To use mutexes, you need to follow these steps for creating and using them:
30 -# Declare the mutex container and initialize the mutex:
32 osMutexId (uart_mutex_id); // Mutex ID
34 -# Create the mutex in a thread:
36 uart_mutex_id = osMutexNew(NULL);
38 -# Acquire the mutex when peripheral access is required:
40 osMutexAcquire(uart_mutex_id, osWaitForever);
42 -# When finished with the peripheral access, release the mutex:
44 osMutexRelease(uart_mutex_id);
49 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
55 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
57 \def osMutexPrioInherit
61 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
67 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
73 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
81 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
83 \fn osMutexId_t osMutexNew (const osMutexAttr_t *attr)
85 Create and initialize a Mutex object.
87 \note Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
91 #include "cmsis_os2.h"
95 void CreateMutex (void) {
97 mutex_id = osMutexNew(NULL);
98 if (mutex_id != NULL) {
99 // Mutex object created
104 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
106 \fn osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout)
108 Wait until a Mutex becomes available. If no other thread has obtained the Mutex, the function instantly returns and blocks the mutex object.
110 The argument \a millisec specifies how long the system waits for a mutex.
111 While the system waits the thread that is calling this function is put into the state \b BLOCKED.
112 The \a millisec timeout can have the following values:
113 - when \a millisec is 0, the function returns instantly.
114 - when \a millisec is set to \b osWaitForever the function will wait for an infinite time until the mutex becomes available.
115 - all other values specify a time in millisecond for a timeout.
117 \ref osStatus_t return values:
118 - \em osOK: the mutex has been obtained.
119 - \em osErrorTimeoutResource: the mutex could not be obtained in the given time.
120 - \em osErrorResource: the mutex could not be obtained when no timeout was specified.
121 - \em osErrorParameter: the parameter \a mutex_id is incorrect.
122 - \em osErrorISR: cannot be called from interrupt service routines.
124 \note Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
128 #include "cmsis_os2.h"
130 void WaitMutex (void) {
131 osMutexId_t mutex_id;
134 mutex_id = osMutexNew(NULL);
135 if (mutex_id != NULL) {
136 status = osMutexAcquire(mutex_id, 0);
137 if (status != osOK) {
138 // handle failure code
144 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
146 \fn osStatus_t osMutexRelease (osMutexId_t mutex_id)
148 Release a Mutex that was obtained with \ref osMutexAcquire. Other threads that currently wait for the same mutex will be now put into the state \b READY.
150 \ref osStatus_t return values:
151 - \em osOK: the mutex has been correctly released.
152 - \em osErrorResource: the mutex was not obtained before.
153 - \em osErrorParameter: the parameter \a mutex_id is incorrect.
154 - \em osErrorISR: \ref osMutexRelease cannot be called from interrupt service routines.
156 \note Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
160 #include "cmsis_os2.h"
162 osMutexId_t mutex_id; // Mutex id populated by the function CreateMutex()
164 void ReleaseMutex (osMutexId_t mutex_id) {
167 if (mutex_id != NULL) {
168 status = osMutexRelease(mutex_id);
169 if (status != osOK) {
170 // handle failure code
176 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
178 \fn osThreadId_t osMutexGetOwner (osMutexId_t mutex_id)
180 Returns the \ref osThreadId_t of the thread that acquired a mutex.
182 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
184 \fn osStatus_t osMutexDelete (osMutexId_t mutex_id)
186 Delete a Mutex object. The function releases internal memory obtained for Mutex handling. After this call the \a mutex_id is no longer valid and cannot be
187 used. The Mutex may be created again using the function \ref osMutexNew.
189 \ref osStatus_t return values:
190 - \em osOK: the mutex object has been deleted.
191 - \em osErrorISR: \ref osMutexDelete cannot be called from interrupt service routines.
192 - \em osErrorResource: all tokens have already been released.
193 - \em osErrorParameter: the parameter \a mutex_id is incorrect.
195 \note Cannot be called from \ref CMSIS_RTOS_ISR_Calls "Interrupt Service Routines".
199 #include "cmsis_os2.h"
201 osMutexId_t mutex_id; // Mutex id populated by the function CreateMutex()
203 void DeleteMutex (osMutexId_t mutex_id) {
206 if (mutex_id != NULL) {
207 status = osMutexDelete(mutex_id);
208 if (status != osOK) {
209 // handle failure code
217 // these struct members must stay outside the group to avoid double entries in documentation
219 \var osMutexAttr_t::attr_bits
221 The following predefined bit masks can be assigned to set options for a mutex object.
223 Bit Mask | Description
224 :---------------------------|:------------------
225 \token{osMutexRecursive} | Mutex is recursive. The same thread can consume a mutex multiple times without locking itself.
226 \token{osMutexPrioInherit} | Priority inheritance protocol. While a thread owns this mutex it cannot be preempted by a higher priority thread to avoid starvation.
227 \token{osMutexRobust} | Robust mutex. Notify threads that acquire a mutex if the previous owner was terminated.
231 \var osMutexAttr_t::cb_mem
233 Pointer to a memory location for the mutex object. This can optionally be used for custom memory management systems.
234 Specify NULL to use the kernel memory management.
237 \var osMutexAttr_t::cb_size
239 The size of the memory block passed with \ref cb_mem. Must be the size of a mutex object or larger.
242 \var osMutexAttr_t::name
244 String with a human readable name of the mutex object.
247 osMutexId_t mid_Thread_Mutex; // mutex id
249 const osMutexAttr_t Thread_Mutex_attr = {
251 osMutexRecursive | osMutexPrioInherit, // attr_bits
252 NULL, // memory for control block
253 NULL // size for control block
255 mid_Mutex = osMutexNew (&Thread_Mutex_attr);