* rather than the normal dynamically allocated memory, and tests objects being\r
* created and deleted with both statically allocated memory and dynamically\r
* allocated memory.\r
+ *\r
+ * See http://www.FreeRTOS.org/Static_Vs_Dynamic_Memory_Allocation.html\r
*/\r
\r
/* Scheduler include files. */\r
static void prvStaticallyAllocatedTask( void *pvParameters );\r
\r
/*\r
- * A function that demonstrates and tests the xTaskCreateStatic() API function\r
- * by creating and then deleting tasks with both dynamically and statically\r
- * allocated TCBs and stacks.\r
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete tasks using both statically and dynamically allocated TCBs and stacks.\r
*/\r
static void prvCreateAndDeleteStaticallyAllocatedTasks( void );\r
\r
/*\r
- * A function that demonstrates and tests the xEventGroupCreateStatic() API\r
- * function by creating and then deleting event groups using both dynamically\r
- * and statically allocated event group structures.\r
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete event groups using both statically and dynamically allocated RAM.\r
*/\r
static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void );\r
\r
/*\r
- * A function that demonstrates and tests the xQueueCreateStatic() API function\r
- * by creating and then deleting queues with both dynamically and statically\r
- * allocated queue structures and queue storage areas.\r
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete queues using both statically and dynamically allocated RAM.\r
*/\r
static void prvCreateAndDeleteStaticallyAllocatedQueues( void );\r
\r
/*\r
- * A function that demonstrates and tests the xSemaphoreCreateBinaryStatic() API\r
- * macro by creating and then deleting binary semaphores with both dynamically\r
- * and statically allocated semaphore structures.\r
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete binary semaphores using both statically and dynamically allocated RAM.\r
*/\r
static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );\r
\r
/*\r
- * A function that demonstrates and tests the xTimerCreateStatic() API macro by\r
- * creating and then deleting software timers with both dynamically and\r
- * statically allocated timer structures.\r
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete software timers using both statically and dynamically allocated RAM.\r
*/\r
static void prvCreateAndDeleteStaticallyAllocatedTimers( 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
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete mutexes using both statically and dynamically allocated RAM.\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
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete counting semaphores using both statically and dynamically allocated\r
+ * RAM.\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
+ * A function that demonstrates and tests the API functions that create and\r
+ * delete recursive mutexes using both statically and dynamically allocated RAM.\r
*/\r
static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );\r
\r
\r
void vStartStaticallyAllocatedTasks( void )\r
{\r
- /* Create a single task, which then repeatedly creates and deletes the\r
- task implemented by prvStaticallyAllocatedTask() at various different\r
- priorities, and both with and without statically allocated TCB and stack. */\r
+ /* Create a single task, which then repeatedly creates and deletes the other\r
+ RTOS objects using both statically and dynamically allocated RAM. */\r
xTaskCreateStatic( prvStaticallyAllocatedCreator, /* The function that implements the task being created. */\r
"StatCreate", /* Text name for the task - not used by the RTOS, its just to assist debugging. */\r
staticCREATOR_TASK_STACK_SIZE, /* Size of the buffer passed in as the stack - in words, not bytes! */\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
+ /* Loop, running functions that create and delete the various RTOS\r
+ objects that can be optionally created using either static or dynamic\r
+ memory allocation. */\r
prvCreateAndDeleteStaticallyAllocatedTasks();\r
prvCreateAndDeleteStaticallyAllocatedQueues();\r
\r
- /* Ensure lower priority tasks get CPU time. */\r
+ /* Delay to ensure lower priority tasks get CPU time, and increment the\r
+ cycle counter so a 'check' task can determine that this task is still\r
+ executing. */\r
vTaskDelay( prvGetNextDelayTime() );\r
-\r
- /* Just to show the check task that this task is still executing. */\r
uxCycleCounter++;\r
\r
prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup )\r
-{\r
-EventBits_t xEventBits;\r
-const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( EventBits_t ) 0x55;\r
-\r
- /* The event group should not have any bits set yet. */\r
- xEventBits = xEventGroupGetBits( xEventGroup );\r
-\r
- if( xEventBits != ( EventBits_t ) 0 )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Some some bits, then read them back to check they are as expected. */\r
- xEventGroupSetBits( xEventGroup, xFirstTestBits );\r
-\r
- xEventBits = xEventGroupGetBits( xEventGroup );\r
-\r
- if( xEventBits != xFirstTestBits )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- xEventGroupSetBits( xEventGroup, xSecondTestBits );\r
-\r
- xEventBits = xEventGroupGetBits( xEventGroup );\r
-\r
- if( xEventBits != ( xFirstTestBits | xSecondTestBits ) )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Finally try clearing some bits too and check that operation proceeds as\r
- expected. */\r
- xEventGroupClearBits( xEventGroup, xFirstTestBits );\r
-\r
- xEventBits = xEventGroupGetBits( xEventGroup );\r
-\r
- if( xEventBits != xSecondTestBits )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )\r
-{\r
-BaseType_t xReturned;\r
-UBaseType_t x;\r
-const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );\r
-TickType_t xTickCount;\r
-\r
- /* The binary semaphore should start 'empty', so a call to xSemaphoreTake()\r
- should fail. */\r
- xTickCount = xTaskGetTickCount();\r
- xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
-\r
- if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )\r
- {\r
- /* Did not block on the semaphore as long as expected. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- if( xReturned != pdFAIL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount\r
- times. */\r
- for( x = 0; x < uxMaxCount; x++ )\r
- {\r
- xReturned = xSemaphoreGive( xSemaphore );\r
-\r
- if( xReturned == pdFAIL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
-\r
- /* Giving the semaphore again should fail, as it is 'full'. */\r
- xReturned = xSemaphoreGive( xSemaphore );\r
-\r
- if( xReturned != pdFAIL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );\r
-\r
- /* Should now be possible to 'take' the semaphore up to a maximum of\r
- uxMaxCount times without blocking. */\r
- for( x = 0; x < uxMaxCount; x++ )\r
- {\r
- xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
-\r
- if( xReturned == pdFAIL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
-\r
- /* Back to the starting condition, where the semaphore should not be\r
- available. */\r
- xTickCount = xTaskGetTickCount();\r
- xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
-\r
- if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )\r
- {\r
- /* Did not block on the semaphore as long as expected. */\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- if( xReturned != pdFAIL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue )\r
-{\r
-uint64_t ull, ullRead;\r
-BaseType_t xReturned, xLoop;\r
-\r
- /* This test is done twice to ensure the queue storage area wraps. */\r
- for( xLoop = 0; xLoop < 2; xLoop++ )\r
- {\r
- /* A very basic test that the queue can be written to and read from as\r
- expected. First the queue should be empty. */\r
- xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
- if( xReturned != errQUEUE_EMPTY )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS\r
- times. */\r
- for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
- {\r
- xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
- if( xReturned != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
-\r
- /* Should not now be possible to write to the queue again. */\r
- xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
- if( xReturned != errQUEUE_FULL )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- /* Now read back from the queue to ensure the data read back matches that\r
- written. */\r
- for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
- {\r
- xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );\r
-\r
- if( xReturned != pdPASS )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
-\r
- if( ullRead != ull )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
-\r
- /* The queue should be empty again. */\r
- xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
- if( xReturned != errQUEUE_EMPTY )\r
- {\r
- xErrorOccurred = pdTRUE;\r
- }\r
- }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvSanityCheckCreatedRecursiveMutex( 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
StaticSemaphore_t xSemaphoreBuffer;\r
\r
/* Create the semaphore. xSemaphoreCreateCountingStatic() has one more\r
- parameter than the usual xSemaphoreCreateCounting() function. The paraemter\r
+ parameter than the usual xSemaphoreCreateCounting() function. The parameter\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
\r
/* Delete the semaphore again so the buffers can be reused. */\r
vSemaphoreDelete( xSemaphore );\r
+\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ /* Now do the same but using dynamically allocated buffers to ensure the\r
+ delete functions are working correctly in both the static and dynamic\r
+ allocation cases. */\r
+ xSemaphore = xSemaphoreCreateCounting( uxMaxCount, 0 );\r
+ configASSERT( xSemaphore != NULL );\r
+ prvSanityCheckCreatedSemaphore( xSemaphore, uxMaxCount );\r
+ vSemaphoreDelete( xSemaphore );\r
+ }\r
+ #endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
/* Delete the semaphore again so the buffers can be reused. */\r
vSemaphoreDelete( xSemaphore );\r
+\r
+ /* Now do the same using dynamically allocated buffers to ensure the delete\r
+ functions are working correctly in both the static and dynamic memory\r
+ allocation cases. */\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ xSemaphore = xSemaphoreCreateRecursiveMutex();\r
+ configASSERT( xSemaphore != NULL );\r
+ prvSanityCheckCreatedRecursiveMutex( xSemaphore );\r
+ vSemaphoreDelete( xSemaphore );\r
+ }\r
+ #endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
/* Delete the queue again so the buffers can be reused. */\r
vQueueDelete( xQueue );\r
+\r
+ /* Now do the same using a dynamically allocated queue to ensure the delete\r
+ function is working correctly in both the static and dynamic memory\r
+ allocation cases. */\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ xQueue = xQueueCreate( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
+ sizeof( uint64_t ) ); /* The size of each item. */\r
+\r
+ /* The queue handle should equal the static queue structure passed into the\r
+ xQueueCreateStatic() function. */\r
+ configASSERT( xQueue != NULL );\r
+\r
+ /* Ensure the queue passes a few sanity checks as a valid queue. */\r
+ prvSanityCheckCreatedQueue( xQueue );\r
+\r
+ /* Delete the queue again so the buffers can be reused. */\r
+ vQueueDelete( xQueue );\r
+ }\r
+ #endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
StaticSemaphore_t xSemaphoreBuffer;\r
\r
/* Create the semaphore. xSemaphoreCreateMutexStatic() has one more\r
- parameter than the usual xSemaphoreCreateMutex() function. The paraemter\r
+ parameter than the usual xSemaphoreCreateMutex() function. The parameter\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
\r
/* Delete the semaphore again so the buffers can be reused. */\r
vSemaphoreDelete( xSemaphore );\r
-}\r
-/*-----------------------------------------------------------*/\r
\r
-static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )\r
-{\r
+ /* Now do the same using a dynamically allocated mutex to ensure the delete\r
+ function is working correctly in both the static and dynamic allocation\r
+ cases. */\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ xSemaphore = xSemaphoreCreateMutex();\r
+\r
+ /* The semaphore handle should equal the static semaphore structure\r
+ passed into the xSemaphoreCreateMutexStatic() function. */\r
+ configASSERT( xSemaphore != NULL );\r
+\r
+ /* Take the mutex so the mutex is in the state expected by the\r
+ prvSanityCheckCreatedSemaphore() 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
+ prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
+\r
+ /* Delete the semaphore again so the buffers can be reused. */\r
+ vSemaphoreDelete( xSemaphore );\r
+ }\r
+ #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )\r
+{\r
SemaphoreHandle_t xSemaphore;\r
\r
/* StaticSemaphore_t is a publicly accessible structure that has the same size\r
StaticSemaphore_t xSemaphoreBuffer;\r
\r
/* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more\r
- parameter than the usual xSemaphoreCreateBinary() function. The paraemter\r
+ parameter than the usual xSemaphoreCreateBinary() function. The parameter\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
/* Delete the semaphore again so the buffers can be reused. */\r
vSemaphoreDelete( xSemaphore );\r
\r
+ /* Now do the same using a dynamically allocated semaphore to check the\r
+ delete function is working correctly in both the static and dynamic\r
+ allocation cases. */\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ xSemaphore = xSemaphoreCreateBinary();\r
+ configASSERT( xSemaphore != NULL );\r
+ prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
+ vSemaphoreDelete( xSemaphore );\r
+ }\r
+ #endif\r
\r
/* There isn't a static version of the old and deprecated\r
vSemaphoreCreateBinary() macro (because its deprecated!), but check it is\r
- still functioning correctly when configSUPPORT_STATIC_ALLOCATION is set to\r
- 1. */\r
+ still functioning correctly. */\r
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
{\r
vSemaphoreCreateBinary( xSemaphore );\r
UBaseType_t *puxVariableToIncrement;\r
BaseType_t xReturned;\r
\r
- /* Obtain the address of the variable to increment from the timer ID. */\r
+ /* The timer callback just demonstrates it is executing by incrementing a\r
+ variable - the address of which is passed into the timer as its ID. Obtain\r
+ the address of the variable to increment. */\r
puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );\r
\r
/* Increment the variable to show the timer callback has executed. */\r
timer. */\r
if( *puxVariableToIncrement == staticMAX_TIMER_CALLBACK_EXECUTIONS )\r
{\r
- /* This is called from a timer callback so must not block. */\r
+ /* This is called from a timer callback so must not block. See\r
+ http://www.FreeRTOS.org/FreeRTOS-timers-xTimerStop.html */\r
xReturned = xTimerStop( xExpiredTimer, staticDONT_BLOCK );\r
\r
if( xReturned != pdPASS )\r
\r
/* Just to show the check task that this task is still executing. */\r
uxCycleCounter++;\r
+\r
+ /* Now do the same using a dynamically allocated software timer to ensure\r
+ the delete function is working correctly in both the static and dynamic\r
+ allocation cases. */\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ xTimer = xTimerCreate( "T1", /* Text name for the task. Helps debugging only. Not used by FreeRTOS. */\r
+ xTimerPeriod, /* The period of the timer in ticks. */\r
+ pdTRUE, /* This is an auto-reload timer. */\r
+ ( void * ) &uxVariableToIncrement, /* The variable incremented by the test is passed into the timer callback using the timer ID. */\r
+ prvTimerCallback ); /* The function to execute when the timer expires. */\r
+\r
+ configASSERT( xTimer != NULL );\r
+\r
+ uxVariableToIncrement = 0;\r
+ xReturned = xTimerStart( xTimer, staticDONT_BLOCK );\r
+\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ vTaskDelay( xTimerPeriod * staticMAX_TIMER_CALLBACK_EXECUTIONS );\r
+\r
+ if( uxVariableToIncrement != staticMAX_TIMER_CALLBACK_EXECUTIONS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ xReturned = xTimerDelete( xTimer, staticDONT_BLOCK );\r
+\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+ #endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
/* Delete the event group again so the buffers can be reused. */\r
vEventGroupDelete( xEventGroup );\r
+\r
+ /* Now do the same using a dynamically allocated event group to ensure the\r
+ delete function is working correctly in both the static and dynamic\r
+ allocation cases. */\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ xEventGroup = xEventGroupCreate();\r
+ configASSERT( xEventGroup != NULL );\r
+ prvSanityCheckCreatedEventGroup( xEventGroup );\r
+ vEventGroupDelete( xEventGroup );\r
+ }\r
+ #endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
passed as NULL then the respective object will be allocated dynamically as\r
if xTaskCreate() had been called. */\r
xReturned = xTaskCreateStatic(\r
- prvStaticallyAllocatedTask, /* Function that implements the task. */\r
- "Static", /* Human readable name for the task. */\r
- configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */\r
- NULL, /* Parameter to pass into the task. */\r
- tskIDLE_PRIORITY, /* The priority of the task. */\r
- &xCreatedTask, /* Handle of the task being created. */\r
- &( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */\r
- &xTCBBuffer ); /* The variable that will hold that task's TCB. */\r
+ prvStaticallyAllocatedTask, /* Function that implements the task. */\r
+ "Static", /* Human readable name for the task. */\r
+ configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */\r
+ NULL, /* Parameter to pass into the task. */\r
+ uxTaskPriorityGet( NULL ) + 1, /* The priority of the task. */\r
+ &xCreatedTask, /* Handle of the task being created. */\r
+ &( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */\r
+ &xTCBBuffer ); /* The variable that will hold that task's TCB. */\r
+\r
+ /* The created task had a higher priority so should have executed and\r
+ suspended itself by now. */\r
+ if( eTaskGetState( xCreatedTask ) != eSuspended )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
\r
/* Check the task was created correctly, then delete the task. */\r
configASSERT( xReturned == pdPASS );\r
xErrorOccurred = pdTRUE;\r
}\r
vTaskDelete( xCreatedTask );\r
+\r
+ /* Now do the same using a dynamically allocated task to ensure the delete\r
+ function is working correctly in both the static and dynamic allocation\r
+ cases. */\r
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
+ {\r
+ xReturned = xTaskCreate(\r
+ prvStaticallyAllocatedTask, /* Function that implements the task. */\r
+ "Static", /* Human readable name for the task. */\r
+ configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */\r
+ NULL, /* Parameter to pass into the task. */\r
+ uxTaskPriorityGet( NULL ) + 1, /* The priority of the task. */\r
+ &xCreatedTask ); /* Handle of the task being created. */\r
+\r
+ if( eTaskGetState( xCreatedTask ) != eSuspended )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ configASSERT( xReturned == pdPASS );\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ vTaskDelete( xCreatedTask );\r
+ }\r
+ #endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
{\r
( void ) pvParameters;\r
\r
- /* The created task doesn't do anything - just waits to get deleted. */\r
+ /* The created task just suspends itself to wait to get deleted. The task\r
+ that creates this task checks this task is in the expected Suspended state\r
+ before deleting it. */\r
vTaskSuspend( NULL );\r
}\r
/*-----------------------------------------------------------*/\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup )\r
+{\r
+EventBits_t xEventBits;\r
+const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( EventBits_t ) 0x55;\r
+\r
+ /* The event group should not have any bits set yet. */\r
+ xEventBits = xEventGroupGetBits( xEventGroup );\r
+\r
+ if( xEventBits != ( EventBits_t ) 0 )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Some some bits, then read them back to check they are as expected. */\r
+ xEventGroupSetBits( xEventGroup, xFirstTestBits );\r
+\r
+ xEventBits = xEventGroupGetBits( xEventGroup );\r
+\r
+ if( xEventBits != xFirstTestBits )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ xEventGroupSetBits( xEventGroup, xSecondTestBits );\r
+\r
+ xEventBits = xEventGroupGetBits( xEventGroup );\r
+\r
+ if( xEventBits != ( xFirstTestBits | xSecondTestBits ) )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Finally try clearing some bits too and check that operation proceeds as\r
+ expected. */\r
+ xEventGroupClearBits( xEventGroup, xFirstTestBits );\r
+\r
+ xEventBits = xEventGroupGetBits( xEventGroup );\r
+\r
+ if( xEventBits != xSecondTestBits )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )\r
+{\r
+BaseType_t xReturned;\r
+UBaseType_t x;\r
+const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );\r
+TickType_t xTickCount;\r
+\r
+ /* The binary semaphore should start 'empty', so a call to xSemaphoreTake()\r
+ should fail. */\r
+ xTickCount = xTaskGetTickCount();\r
+ xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
+\r
+ if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )\r
+ {\r
+ /* Did not block on the semaphore as long as expected. */\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ if( xReturned != pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount\r
+ times. */\r
+ for( x = 0; x < uxMaxCount; x++ )\r
+ {\r
+ xReturned = xSemaphoreGive( xSemaphore );\r
+\r
+ if( xReturned == pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Giving the semaphore again should fail, as it is 'full'. */\r
+ xReturned = xSemaphoreGive( xSemaphore );\r
+\r
+ if( xReturned != pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );\r
+\r
+ /* Should now be possible to 'take' the semaphore up to a maximum of\r
+ uxMaxCount times without blocking. */\r
+ for( x = 0; x < uxMaxCount; x++ )\r
+ {\r
+ xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
+\r
+ if( xReturned == pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Back to the starting condition, where the semaphore should not be\r
+ available. */\r
+ xTickCount = xTaskGetTickCount();\r
+ xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
+\r
+ if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )\r
+ {\r
+ /* Did not block on the semaphore as long as expected. */\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ if( xReturned != pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue )\r
+{\r
+uint64_t ull, ullRead;\r
+BaseType_t xReturned, xLoop;\r
+\r
+ /* This test is done twice to ensure the queue storage area wraps. */\r
+ for( xLoop = 0; xLoop < 2; xLoop++ )\r
+ {\r
+ /* A very basic test that the queue can be written to and read from as\r
+ expected. First the queue should be empty. */\r
+ xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
+ if( xReturned != errQUEUE_EMPTY )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS\r
+ times. */\r
+ for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
+ {\r
+ xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* Should not now be possible to write to the queue again. */\r
+ xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
+ if( xReturned != errQUEUE_FULL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ /* Now read back from the queue to ensure the data read back matches that\r
+ written. */\r
+ for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
+ {\r
+ xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );\r
+\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ if( ullRead != ull )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+\r
+ /* The queue should be empty again. */\r
+ xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
+ if( xReturned != errQUEUE_EMPTY )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSanityCheckCreatedRecursiveMutex( 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
BaseType_t xAreStaticAllocationTasksStillRunning( void )\r
{\r
static UBaseType_t uxLastCycleCounter = 0;\r