* portTickType xBlockTime \r
* )</pre>\r
*\r
- * <i>Macro</i> to obtain a semaphore. The semaphore must of been created using \r
- * vSemaphoreCreateBinary ().\r
+ * <i>Macro</i> to obtain a semaphore. The semaphore must have previously been\r
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or\r
+ * xSemaphoreCreateCounting().\r
*\r
- * @param xSemaphore A handle to the semaphore being obtained. This is the\r
- * handle returned by vSemaphoreCreateBinary ();\r
+ * @param xSemaphore A handle to the semaphore being taken - obtained when\r
+ * the semaophore was created.\r
*\r
* @param xBlockTime The time in ticks to wait for the semaphore to become\r
* available. The macro portTICK_RATE_MS can be used to convert this to a\r
- * real time. A block time of zero can be used to poll the semaphore.\r
+ * real time. A block time of zero can be used to poll the semaphore. A block\r
+ * time of portMAX_DELAY can be used to block indefinately (provided\r
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).\r
*\r
- * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime\r
- * expired without the semaphore becoming available.\r
+ * @return pdTRUE if the semaphore was obtained. pdFALSE\r
+ * if xBlockTime expired without the semaphore becoming available.\r
*\r
* Example usage:\r
<pre>\r
*/\r
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )\r
\r
+/**\r
+ * semphr. h\r
+ * xSemaphoreTakeRecursive( \r
+ * xSemaphoreHandle xMutex, \r
+ * portTickType xBlockTime \r
+ * )\r
+ *\r
+ * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore. \r
+ * The mutex must have previously been created using a call to \r
+ * xSemaphoreCreateRecursiveMutex();\r
+ * \r
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this\r
+ * macro to be available.\r
+ * \r
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().\r
+ *\r
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex \r
+ * doesn't become available again until the owner has called \r
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example, \r
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will \r
+ * not be avilable to any other task until it has also 'given' the mutex back\r
+ * exactly five times.\r
+ *\r
+ * @param xMutex A handle to the mutex being obtained. This is the\r
+ * handle returned by xSemaphoreCreateMutex();\r
+ *\r
+ * @param xBlockTime The time in ticks to wait for the semaphore to become\r
+ * available. The macro portTICK_RATE_MS can be used to convert this to a\r
+ * real time. A block time of zero can be used to poll the semaphore. If\r
+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will\r
+ * return immediately nomatter what the value of xBlockTime. \r
+ *\r
+ * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime\r
+ * expired without the semaphore becoming available.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ xSemaphoreHandle xMutex = NULL;\r
+\r
+ // A task that creates a mutex.\r
+ void vATask( void * pvParameters )\r
+ {\r
+ // Create the mutex to guard a shared resource.\r
+ xMutex = xSemaphoreCreateRecursiveMutex();\r
+ }\r
+\r
+ // A task that uses the mutex.\r
+ void vAnotherTask( void * pvParameters )\r
+ {\r
+ // ... Do other things.\r
+\r
+ if( xMutex != NULL )\r
+ {\r
+ // See if we can obtain the mutex. If the mutex is not available\r
+ // wait 10 ticks to see if it becomes free. \r
+ if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )\r
+ {\r
+ // We were able to obtain the mutex and can now access the\r
+ // shared resource.\r
+\r
+ // ...\r
+ // For some reason due to the nature of the code further calls to \r
+ // xSemaphoreTakeRecursive() are made on the same mutex. In real\r
+ // code these would not be just sequential calls as this would make\r
+ // no sense. Instead the calls are likely to be buried inside\r
+ // a more complex call structure.\r
+ xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+ xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+\r
+ // The mutex has now been 'taken' three times, so will not be \r
+ // available to another task until it has also been given back\r
+ // three times. Again it is unlikely that real code would have\r
+ // these calls sequentially, but instead buried in a more complex\r
+ // call structure. This is just for illustrative puproses.\r
+ xSemaphoreGiveRecursive( xSemaphore );\r
+ xSemaphoreGiveRecursive( xSemaphore );\r
+ xSemaphoreGiveRecursive( xSemaphore );\r
+\r
+ // Now the mutex can be taken by other tasks.\r
+ }\r
+ else\r
+ {\r
+ // We could not obtain the mutex and can therefore not access\r
+ // the shared resource safely.\r
+ }\r
+ }\r
+ }\r
+ </pre>\r
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive\r
+ * \ingroup Semaphores\r
+ */\r
+#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( xMutex, xBlockTime )\r
+\r
+\r
/* \r
* xSemaphoreAltTake() is an alternative version of xSemaphoreTake().\r
*\r
* semphr. h\r
* <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre>\r
*\r
- * <i>Macro</i> to release a semaphore. The semaphore must of been created using \r
- * vSemaphoreCreateBinary (), and obtained using sSemaphoreTake ().\r
+ * <i>Macro</i> to release a semaphore. The semaphore must have previously been\r
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or\r
+ * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().\r
*\r
- * This must not be used from an ISR. See xSemaphoreGiveFromISR () for\r
+ * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for\r
* an alternative which can be used from an ISR.\r
*\r
+ * This macro must also not be used on semaphores created using \r
+ * xSemaphoreCreateRecursiveMutex().\r
+ *\r
* @param xSemaphore A handle to the semaphore being released. This is the\r
- * handle returned by vSemaphoreCreateBinary ();\r
+ * handle returned when the semaphore was created.\r
*\r
* @return pdTRUE if the semaphore was released. pdFALSE if an error occurred.\r
* Semaphores are implemented using queues. An error can occur if there is\r
*/\r
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )\r
\r
+/**\r
+ * semphr. h\r
+ * <pre>xSemaphoreGiveRecursive( xSemaphoreHandle xSemaphore )</pre>\r
+ *\r
+ * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore.\r
+ * The mutex must have previously been created using a call to \r
+ * xSemaphoreCreateRecursiveMutex();\r
+ * \r
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this\r
+ * macro to be available.\r
+ *\r
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().\r
+ * \r
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex \r
+ * doesn't become available again until the owner has called \r
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example, \r
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will \r
+ * not be avilable to any other task until it has also 'given' the mutex back\r
+ * exactly five times.\r
+ *\r
+ * @param xMutex A handle to the mutex being released, or 'given'. This is the\r
+ * handle returned by xSemaphoreCreateMutex();\r
+ *\r
+ * @return pdTRUE if the semaphore was given.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ xSemaphoreHandle xMutex = NULL;\r
+\r
+ // A task that creates a mutex.\r
+ void vATask( void * pvParameters )\r
+ {\r
+ // Create the mutex to guard a shared resource.\r
+ xMutex = xSemaphoreCreateRecursiveMutex();\r
+ }\r
+\r
+ // A task that uses the mutex.\r
+ void vAnotherTask( void * pvParameters )\r
+ {\r
+ // ... Do other things.\r
+\r
+ if( xMutex != NULL )\r
+ {\r
+ // See if we can obtain the mutex. If the mutex is not available\r
+ // wait 10 ticks to see if it becomes free. \r
+ if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )\r
+ {\r
+ // We were able to obtain the mutex and can now access the\r
+ // shared resource.\r
+\r
+ // ...\r
+ // For some reason due to the nature of the code further calls to \r
+ // xSemaphoreTakeRecursive() are made on the same mutex. In real\r
+ // code these would not be just sequential calls as this would make\r
+ // no sense. Instead the calls are likely to be buried inside\r
+ // a more complex call structure.\r
+ xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+ xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+\r
+ // The mutex has now been 'taken' three times, so will not be \r
+ // available to another task until it has also been given back\r
+ // three times. Again it is unlikely that real code would have\r
+ // these calls sequentially, it would be more likely that the calls\r
+ // to xSemaphoreGiveRecursive() would be called as a call stack\r
+ // unwound. This is just for demonstrative purposes.\r
+ xSemaphoreGiveRecursive( xSemaphore );\r
+ xSemaphoreGiveRecursive( xSemaphore );\r
+ xSemaphoreGiveRecursive( xSemaphore );\r
+\r
+ // Now the mutex can be taken by other tasks.\r
+ }\r
+ else\r
+ {\r
+ // We could not obtain the mutex and can therefore not access\r
+ // the shared resource safely.\r
+ }\r
+ }\r
+ }\r
+ </pre>\r
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive\r
+ * \ingroup Semaphores\r
+ */\r
+#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( xMutex )\r
+\r
/* \r
* xSemaphoreAltGive() is an alternative version of xSemaphoreGive().\r
*\r
portSHORT sTaskPreviouslyWoken \r
)</pre>\r
*\r
- * <i>Macro</i> to release a semaphore. The semaphore must of been created using \r
- * vSemaphoreCreateBinary (), and obtained using xSemaphoreTake ().\r
+ * <i>Macro</i> to release a semaphore. The semaphore must have previously been\r
+ * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting().\r
*\r
* Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())\r
* must not be used with this macro.\r
* This macro can be used from an ISR.\r
*\r
* @param xSemaphore A handle to the semaphore being released. This is the\r
- * handle returned by vSemaphoreCreateBinary ();\r
+ * handle returned when the semaphore was created.\r
*\r
* @param sTaskPreviouslyWoken This is included so an ISR can make multiple calls\r
* to xSemaphoreGiveFromISR () from a single interrupt. The first call\r
{\r
for( ;; )\r
{\r
- // We want this task to run every 10 ticks or a timer. The semaphore \r
- // was created before this task was started\r
+ // We want this task to run every 10 ticks of a timer. The semaphore \r
+ // was created before this task was started.\r
\r
// Block waiting for the semaphore to become available.\r
if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )\r
\r
// We have finished our task. Return to the top of the loop where\r
// we will block on the semaphore until it is time to execute \r
- // again.\r
+ // again. Note when using the semaphore for synchronisation with an\r
+ // ISR in this manner there is no need to 'give' the semaphore back.\r
}\r
}\r
}\r
if( ucLocalTickCount >= TICKS_TO_WAIT )\r
{\r
// Unblock the task by releasing the semaphore.\r
- xSemaphoreGiveFromISR( xSemaphore, xTaskWoken );\r
+ xTaskWoken = xSemaphoreGiveFromISR( xSemaphore, xTaskWoken );\r
\r
// Reset the count so we release the semaphore again in 10 ticks time.\r
ucLocalTickCount = 0;\r
}\r
+\r
+ if( xTaskWoken != pdFALSE )\r
+ {\r
+ // We can force a context switch here. Context switching from an\r
+ // ISR uses port specific syntax. Check the demo task for your port\r
+ // to find the syntax required.\r
+ }\r
}\r
</pre>\r
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR\r
* <i>Macro</i> that implements a mutex semaphore by using the existing queue \r
* mechanism.\r
*\r
+ * Mutexes created using this macro can be accessed using the xSemaphoreTake()\r
+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and \r
+ * xSemaphoreGiveRecursive() macros should not be used.\r
+ * \r
* This type of semaphore uses a priority inheritance mechanism so a task \r
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the \r
* semaphore it is no longer required. \r
* \ingroup Semaphores\r
*/\r
#define xSemaphoreCreateMutex() xQueueCreateMutex()\r
+\r
+\r
+/**\r
+ * semphr. h\r
+ * <pre>xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )</pre>\r
+ *\r
+ * <i>Macro</i> that implements a recursive mutex by using the existing queue \r
+ * mechanism.\r
+ *\r
+ * Mutexes created using this macro can be accessed using the \r
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The \r
+ * xSemaphoreTake() and xSemaphoreGive() macros should not be used.\r
+ *\r
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex \r
+ * doesn't become available again until the owner has called \r
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example, \r
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will \r
+ * not be avilable to any other task until it has also 'given' the mutex back\r
+ * exactly five times.\r
+ * \r
+ * This type of semaphore uses a priority inheritance mechanism so a task \r
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the \r
+ * semaphore it is no longer required. \r
+ *\r
+ * Mutex type semaphores cannot be used from within interrupt service routines. \r
+ *\r
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be \r
+ * used for pure synchronisation (where one task or interrupt always 'gives' the \r
+ * semaphore and another always 'takes' the semaphore) and from within interrupt \r
+ * service routines.\r
+ *\r
+ * @return xSemaphore Handle to the created mutex semaphore. Should be of type \r
+ * xSemaphoreHandle.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ xSemaphoreHandle xSemaphore;\r
+\r
+ void vATask( void * pvParameters )\r
+ {\r
+ // Semaphore cannot be used before a call to xSemaphoreCreateMutex().\r
+ // This is a macro so pass the variable in directly.\r
+ xSemaphore = xSemaphoreCreateRecursiveMutex();\r
+\r
+ if( xSemaphore != NULL )\r
+ {\r
+ // The semaphore was created successfully.\r
+ // The semaphore can now be used. \r
+ }\r
+ }\r
+ </pre>\r
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex\r
+ * \ingroup Semaphores\r
+ */\r
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex()\r
\r
/**\r
*/\r
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount )\r
\r
-#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( xMutex, xBlockTime )\r
-#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( xMutex )\r
\r
#endif /* SEMAPHORE_H */\r
\r