*/\r
static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );\r
\r
+/*\r
+ * A function that demonstrates and tests the xSemaphoreCreateMutexStatic() API\r
+ * macro by creating and then deleting mutexes with both dynamically and\r
+ * statically allocated semaphore structures.\r
+ */\r
+static void prvCreateAndDeleteStaticallyAllocatedMutexes( void );\r
+\r
+/*\r
+ * A function that demonstrates and tests the xSemaphoreCreateCountingStatic()\r
+ * API macro by creating and then deleting counting semaphores with both\r
+ * dynamically and statically allocated semaphore structures.\r
+ */\r
+static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void );\r
+\r
+/*\r
+ * A function that demonstrates and tests the\r
+ * xSemaphoreCreateRecursiveMutexStatic() API macro by creating and then\r
+ * deleting recursive mutexes with both dynamically and statically allocated\r
+ * semaphore structures.\r
+ */\r
+static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );\r
+\r
/*\r
* The task that creates and deletes other tasks has to delay occasionally to\r
* ensure lower priority tasks are not starved of processing time. A pseudo\r
*/\r
static void prvCheckQueueFunction( QueueHandle_t xQueue );\r
\r
+/*\r
+ * Checks the basic operation of a recursive mutex after it has been created.\r
+ */\r
+static void prvCheckRecursiveSemaphoreFunction( SemaphoreHandle_t xSemaphore );\r
+\r
/*\r
* Checks the basic operation of a binary semaphore after it has been created.\r
*/\r
\r
for( ;; )\r
{\r
+ /* Loop, running functions that create and delete the various objects\r
+ that can be optionally created using either static or dynamic memory\r
+ allocation. */\r
prvCreateAndDeleteStaticallyAllocatedTasks();\r
prvCreateAndDeleteStaticallyAllocatedQueues();\r
prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();\r
+ prvCreateAndDeleteStaticallyAllocatedCountingSemaphores();\r
+ prvCreateAndDeleteStaticallyAllocatedMutexes();\r
+ prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes();\r
}\r
}\r
/*-----------------------------------------------------------*/\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvCheckRecursiveSemaphoreFunction( SemaphoreHandle_t xSemaphore )\r
+{\r
+const BaseType_t xLoops = 5;\r
+BaseType_t x, xReturned;\r
+\r
+ /* A very basic test that the recursive semaphore behaved like a recursive\r
+ semaphore. First the semaphore should not be able to be given, as it has not\r
+ yet been taken. */\r
+ xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
+\r
+ if( xReturned != pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Now it should be possible to take the mutex a number of times. */\r
+ for( x = 0; x < xLoops; x++ )\r
+ {\r
+ xReturned = xSemaphoreTakeRecursive( xSemaphore, staticDONT_BLOCK );\r
+\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Should be possible to give the semaphore the same number of times as it\r
+ was given in the loop above. */\r
+ for( x = 0; x < xLoops; x++ )\r
+ {\r
+ xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
+\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* No more gives should be possible though. */\r
+ xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
+\r
+ if( xReturned != pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void )\r
+{\r
+SemaphoreHandle_t xSemaphore;\r
+const UBaseType_t uxMaxCount = ( UBaseType_t ) 10;\r
+\r
+/* StaticSemaphore_t is a publicly accessible structure that has the same size\r
+and alignment requirements as the real semaphore structure. It is provided as a\r
+mechanism for applications to know the size of the semaphore (which is dependent\r
+on the architecture and configuration file settings) without breaking the strict\r
+data hiding policy by exposing the real semaphore internals. This\r
+StaticSemaphore_t variable is passed into the xSemaphoreCreateCountingStatic()\r
+function calls within this function. NOTE: In most usage scenarios now it is\r
+faster and more memory efficient to use a direct to task notification instead of\r
+a counting semaphore. http://www.freertos.org/RTOS-task-notifications.html */\r
+static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
+\r
+ /* Create the semaphore. xSemaphoreCreateCountingStatic() has one more\r
+ parameter than the usual xSemaphoreCreateCounting() function. The paraemter\r
+ is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
+ hold information on the semaphore in an anonymous way. If the pointer is\r
+ passed as NULL then the structure will be allocated dynamically, just as\r
+ when xSemaphoreCreateCounting() is called. */\r
+ xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, &xSemaphoreBuffer );\r
+\r
+ /* The semaphore handle should equal the static semaphore structure passed\r
+ into the xSemaphoreCreateBinaryStatic() function. */\r
+ configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
+\r
+ /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
+ prvCheckSemaphoreFunction( xSemaphore, uxMaxCount );\r
+\r
+ /* Delete the semaphore again so the buffers can be reused. */\r
+ vSemaphoreDelete( xSemaphore );\r
+\r
+\r
+ /* The semaphore created above had a statically allocated semaphore\r
+ structure. Repeat the above using NULL as the third\r
+ xSemaphoreCreateCountingStatic() parameter so the semaphore structure is\r
+ instead allocated dynamically. */\r
+ xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, NULL );\r
+\r
+ /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
+ prvCheckSemaphoreFunction( xSemaphore, uxMaxCount );\r
+\r
+ /* Delete the semaphore again so the buffers can be reused. */\r
+ vSemaphoreDelete( xSemaphore );\r
+\r
+ /* Ensure lower priority tasks get CPU time. */\r
+ vTaskDelay( prvGetNextDelayTime() );\r
+\r
+ /* Just to show the check task that this task is still executing. */\r
+ uxCycleCounter++;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void )\r
+{\r
+SemaphoreHandle_t xSemaphore;\r
+\r
+/* StaticSemaphore_t is a publicly accessible structure that has the same size\r
+and alignment requirements as the real semaphore structure. It is provided as a\r
+mechanism for applications to know the size of the semaphore (which is dependent\r
+on the architecture and configuration file settings) without breaking the strict\r
+data hiding policy by exposing the real semaphore internals. This\r
+StaticSemaphore_t variable is passed into the\r
+xSemaphoreCreateRecursiveMutexStatic() function calls within this function. */\r
+static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
+\r
+ /* Create the semaphore. xSemaphoreCreateRecursiveMutexStatic() has one\r
+ more parameter than the usual xSemaphoreCreateRecursiveMutex() function.\r
+ The parameter is a pointer to the pre-allocated StaticSemaphore_t structure,\r
+ which will hold information on the semaphore in an anonymous way. If the\r
+ pointer is passed as NULL then the structure will be allocated dynamically,\r
+ just as when xSemaphoreCreateRecursiveMutex() is called. */\r
+ xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );\r
+\r
+ /* The semaphore handle should equal the static semaphore structure passed\r
+ into the xSemaphoreCreateBinaryStatic() function. */\r
+ configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
+\r
+ /* Ensure the semaphore passes a few sanity checks as a valid\r
+ recursive semaphore. */\r
+ prvCheckRecursiveSemaphoreFunction( xSemaphore );\r
+\r
+ /* Delete the semaphore again so the buffers can be reused. */\r
+ vSemaphoreDelete( xSemaphore );\r
+\r
+\r
+ /* The semaphore created above had a statically allocated semaphore\r
+ structure. Repeat the above using NULL as the\r
+ xSemaphoreCreateRecursiveMutexStatic() parameter so the semaphore structure\r
+ is instead allocated dynamically. */\r
+ xSemaphore = xSemaphoreCreateRecursiveMutexStatic( NULL );\r
+\r
+ /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
+ prvCheckRecursiveSemaphoreFunction( xSemaphore );\r
+\r
+ /* Delete the semaphore again so the buffers can be reused. */\r
+ vSemaphoreDelete( xSemaphore );\r
+\r
+ /* Ensure lower priority tasks get CPU time. */\r
+ vTaskDelay( prvGetNextDelayTime() );\r
+\r
+ /* Just to show the check task that this task is still executing. */\r
+ uxCycleCounter++;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
static void prvCreateAndDeleteStaticallyAllocatedQueues( void )\r
{\r
QueueHandle_t xQueue;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvCreateAndDeleteStaticallyAllocatedMutexes( void )\r
+{\r
+SemaphoreHandle_t xSemaphore;\r
+BaseType_t xReturned;\r
+\r
+/* StaticSemaphore_t is a publicly accessible structure that has the same size\r
+and alignment requirements as the real semaphore structure. It is provided as a\r
+mechanism for applications to know the size of the semaphore (which is dependent\r
+on the architecture and configuration file settings) without breaking the strict\r
+data hiding policy by exposing the real semaphore internals. This\r
+StaticSemaphore_t variable is passed into the xSemaphoreCreateMutexStatic()\r
+function calls within this function. */\r
+static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
+\r
+ /* Create the semaphore. xSemaphoreCreateMutexStatic() has one more\r
+ parameter than the usual xSemaphoreCreateMutex() function. The paraemter\r
+ is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
+ hold information on the semaphore in an anonymous way. If the pointer is\r
+ passed as NULL then the structure will be allocated dynamically, just as\r
+ when xSemaphoreCreateMutex() is called. */\r
+ xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );\r
+\r
+ /* The semaphore handle should equal the static semaphore structure passed\r
+ into the xSemaphoreCreateMutexStatic() function. */\r
+ configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
+\r
+ /* Take the mutex so the mutex is in the state expected by the\r
+ prvCheckSemaphoreFunction() function. */\r
+ xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
+\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
+ prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
+\r
+ /* Delete the semaphore again so the buffers can be reused. */\r
+ vSemaphoreDelete( xSemaphore );\r
+\r
+\r
+ /* The semaphore created above had a statically allocated semaphore\r
+ structure. Repeat the above using NULL as the xSemaphoreCreateMutexStatic()\r
+ parameter so the semaphore structure is instead allocated dynamically. */\r
+ xSemaphore = xSemaphoreCreateMutexStatic( NULL );\r
+\r
+ /* Take the mutex so the mutex is in the state expected by the\r
+ prvCheckSemaphoreFunction() function. */\r
+ xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
+\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
+ prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
+\r
+ /* Delete the semaphore again so the buffers can be reused. */\r
+ vSemaphoreDelete( xSemaphore );\r
+\r
+ /* Ensure lower priority tasks get CPU time. */\r
+ vTaskDelay( prvGetNextDelayTime() );\r
+\r
+ /* Just to show the check task that this task is still executing. */\r
+ uxCycleCounter++;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )\r
{\r
SemaphoreHandle_t xSemaphore;\r
mechanism for applications to know the size of the semaphore (which is dependent\r
on the architecture and configuration file settings) without breaking the strict\r
data hiding policy by exposing the real semaphore internals. This\r
-StaticSemaphore_t variable is passed into the xSemaphoreCreateBinary() function\r
-calls within this function. NOTE: In most usage scenarios now it is faster and\r
-more memory efficient to use a direct to task notification instead of a binary\r
-semaphore. http://www.freertos.org/RTOS-task-notifications.html */\r
+StaticSemaphore_t variable is passed into the xSemaphoreCreateBinaryStatic()\r
+function calls within this function. NOTE: In most usage scenarios now it is\r
+faster and more memory efficient to use a direct to task notification instead of\r
+a binary semaphore. http://www.freertos.org/RTOS-task-notifications.html */\r
static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
\r
/* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more\r
\r
/* The semaphore created above had a statically allocated semaphore\r
structure. Repeat the above using NULL as the xSemaphoreCreateBinaryStatic()\r
- parameter so the queue structure is instead allocated dynamically. */\r
+ parameter so the semaphore structure is instead allocated dynamically. */\r
xSemaphore = xSemaphoreCreateBinaryStatic( NULL );\r
\r
/* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
#if( ( configASSERT_DEFINED == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
{\r
/* Sanity check that the size of the structure used to declare a\r
- variable of type StaticQueue_t or StaticSemaphore_t equals the size of \r
+ variable of type StaticQueue_t or StaticSemaphore_t equals the size of\r
the real queue and semaphore structures. */\r
volatile size_t xSize = sizeof( StaticQueue_t );\r
configASSERT( xSize == sizeof( Queue_t ) );\r
\r
#if ( configUSE_MUTEXES == 1 )\r
\r
- QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )\r
+ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue )\r
{\r
Queue_t *pxNewQueue;\r
+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;\r
\r
/* Prevent compiler warnings about unused parameters if\r
configUSE_TRACE_FACILITY does not equal 1. */\r
( void ) ucQueueType;\r
\r
+ pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );\r
+\r
/* Allocate the new queue structure. */\r
- pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );\r
if( pxNewQueue != NULL )\r
{\r
- /* Information required for priority inheritance. */\r
+ /* xQueueGenericCreate() will set all the queue structure members\r
+ correctly for a generic queue, but this function is creating a\r
+ mutex. Overwrite those members that need to be set differently -\r
+ in particular the information required for priority inheritance. */\r
pxNewQueue->pxMutexHolder = NULL;\r
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;\r
\r
- /* Queues used as a mutex no data is actually copied into or out\r
- of the queue. */\r
- pxNewQueue->pcWriteTo = NULL;\r
- pxNewQueue->u.pcReadFrom = NULL;\r
-\r
- /* Each mutex has a length of 1 (like a binary semaphore) and\r
- an item size of 0 as nothing is actually copied into or out\r
- of the mutex. */\r
- pxNewQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;\r
- pxNewQueue->uxLength = ( UBaseType_t ) 1U;\r
- pxNewQueue->uxItemSize = ( UBaseType_t ) 0U;\r
- pxNewQueue->xRxLock = queueUNLOCKED;\r
- pxNewQueue->xTxLock = queueUNLOCKED;\r
-\r
- #if ( configUSE_TRACE_FACILITY == 1 )\r
- {\r
- pxNewQueue->ucQueueType = ucQueueType;\r
- }\r
- #endif\r
-\r
- #if ( configUSE_QUEUE_SETS == 1 )\r
- {\r
- pxNewQueue->pxQueueSetContainer = NULL;\r
- }\r
- #endif\r
-\r
- /* Ensure the event queues start with the correct state. */\r
- vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );\r
- vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );\r
+ /* In case this is a recursive mutex. */\r
+ pxNewQueue->u.uxRecursiveCallCount = 0;\r
\r
traceCREATE_MUTEX( pxNewQueue );\r
\r
uxRecursiveCallCount member. */\r
( pxMutex->u.uxRecursiveCallCount )--;\r
\r
- /* Have we unwound the call count? */\r
+ /* Has the recursive call count unwound to 0? */\r
if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 )\r
{\r
/* Return the mutex. This will automatically unblock any other\r
\r
#if ( configUSE_COUNTING_SEMAPHORES == 1 )\r
\r
- QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )\r
+ QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue )\r
{\r
QueueHandle_t xHandle;\r
\r
configASSERT( uxMaxCount != 0 );\r
configASSERT( uxInitialCount <= uxMaxCount );\r
\r
- xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, NULL, queueQUEUE_TYPE_COUNTING_SEMAPHORE );\r
+ xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );\r
\r
if( xHandle != NULL )\r
{\r