\r
/*\r
* Demonstrates how to create FreeRTOS objects using pre-allocated memory,\r
- * rather than the normal dynamically allocated memory. Currently only tasks\r
- * are being allocated statically.\r
+ * rather than the normal dynamically allocated memory.\r
*\r
* Two buffers are required by a task - one that is used by the task as its\r
* stack, and one that holds the task's control block (TCB).\r
- * prvStaticallyAllocatedTaskCreator() creates and deletes tasks with all\r
+ * prvStaticallyAllocatedCreator() creates and deletes tasks with all\r
* possible combinations of statically allocated and dynamically allocated\r
* stacks and TCBs.\r
*/\r
/* Scheduler include files. */\r
#include "FreeRTOS.h"\r
#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
\r
/* Demo program include files. */\r
#include "StaticAllocation.h"\r
/* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */\r
#if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
\r
-#define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
+/* The priority at which the task that performs the tests is created. */\r
+#define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
+\r
+/* The length of the queue, in items, not bytes, used in the queue static\r
+allocation tests. */\r
+#define staticQUEUE_LENGTH_IN_ITEMS ( 5 )\r
+\r
+/* A block time of 0 simply means "don't block". */\r
+#define staticDONT_BLOCK ( ( TickType_t ) 0 )\r
+\r
+/* Binary semaphores have a maximum count of 1. */\r
+#define staticBINARY_SEMAPHORE_MAX_COUNT ( 1 )\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
\r
/*\r
- * A task that is created multiple times, using both statically and dynamically\r
- * allocated stack and TCB.\r
+ * A task that is created and deleted multiple times, using both statically and\r
+ * dynamically allocated stack and TCB.\r
*/\r
static void prvStaticallyAllocatedTask( void *pvParameters );\r
\r
/*\r
- * The task that creates and deletes the prvStaticallyAllocatedTask() task,\r
- * using various priorities, and sometimes with statically and sometimes\r
- * dynamically allocated stack and TCB.\r
+ * The task that repeatedly creates and deletes statically allocated tasks, and\r
+ * other RTOS objects.\r
*/\r
-static void prvStaticallyAllocatedTaskCreator( void *pvParameters );\r
+static void prvStaticallyAllocatedCreator( void *pvParameters );\r
\r
/*\r
* Utility function to create pseudo random numbers.\r
*/\r
static UBaseType_t prvRand( void );\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
+ */\r
+static void prvCreateAndDeleteStaticallyAllocatedTasks( 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
+ */\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
+ */\r
+static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( 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 TickType_t prvGetNextDelayTime( void );\r
\r
+/*\r
+ * Checks the basic operation of a queue after it has been created.\r
+ */\r
+static void prvCheckQueueFunction( QueueHandle_t xQueue );\r
+\r
+/*\r
+ * Checks the basic operation of a binary semaphore after it has been created.\r
+ */\r
+static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount );\r
+\r
/*-----------------------------------------------------------*/\r
\r
-/* DummyTCB_t is a publicly accessible structure that has the same size and\r
+/* StaticTCB_t is a publicly accessible structure that has the same size and\r
alignment requirements as the real TCB structure. It is provided as a mechanism\r
for applications to know the size of the TCB (which is dependent on the\r
architecture and configuration file settings) without breaking the strict data\r
-hiding policy by exposing the real TCB. This DummyTCB_t variable is passed into\r
-the xTaskCreateStatic() function, and will hold the task's TCB. */\r
-static DummyTCB_t xTCBBuffer;\r
-\r
-/* This is the stack that will be used by the task. The alignment requirements\r
-for the stack depend on the architecture, and the method of forcing an alignment\r
-is dependent on the compiler, but any bad alignment is corrected inside the\r
-FreeRTOS code. */\r
-static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];\r
+hiding policy by exposing the real TCB. This StaticTCB_t variable is passed\r
+into the xTaskCreateStatic() function that creates the\r
+prvStaticallyAllocatedCreator() task, and will hold the TCB of the created\r
+tasks. */\r
+static StaticTCB_t xCreatorTaskTCBBuffer;\r
+\r
+/* This is the stack that will be used by the prvStaticallyAllocatedCreator()\r
+task, which is itself created using statically allocated buffers (so without any\r
+dynamic memory allocation). */\r
+static StackType_t uxCreatorTaskStackBuffer[ configMINIMAL_STACK_SIZE ];\r
\r
/* Used by the pseudo random number generating function. */\r
static uint32_t ulNextRand = 0;\r
stalled. */\r
static volatile UBaseType_t uxCycleCounter = 0;\r
\r
+/* A variable that gets set to pdTRUE if an error is detected. */\r
+static BaseType_t xErrorOccurred = pdFALSE;\r
+\r
/*-----------------------------------------------------------*/\r
\r
void vStartStaticallyAllocatedTasks( void )\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
- xTaskCreate( prvStaticallyAllocatedTaskCreator, "StatCreate", configMINIMAL_STACK_SIZE, NULL, staticTASK_PRIORITY, NULL );\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
+ configMINIMAL_STACK_SIZE, /* Size of the buffer passed in as the stack - in words, not bytes! */\r
+ NULL, /* Parameter passed into the task - not used in this case. */\r
+ staticTASK_PRIORITY, /* Priority of the task. */\r
+ NULL, /* Handle of the task being created, not used in this case. */\r
+ &( uxCreatorTaskStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */\r
+ &xCreatorTaskTCBBuffer ); /* The variable that will hold the task's TCB. */\r
\r
/* Pseudo seed the random number generator. */\r
ulNextRand = ( uint32_t ) prvRand;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvStaticallyAllocatedTaskCreator( void *pvParameters )\r
+static void prvStaticallyAllocatedCreator( void *pvParameters )\r
{\r
-TaskHandle_t xCreatedTask;\r
-BaseType_t xReturned;\r
-\r
/* Avoid compiler warnings. */\r
( void ) pvParameters;\r
\r
for( ;; )\r
{\r
- /* Create the task. xTaskCreateStatic() has two more parameters than\r
- the usual xTaskCreate() function. The first new parameter is a pointer to\r
- the pre-allocated stack. The second new parameter is a pointer to the\r
- DummyTCB_t structure that will hold the task's TCB. If either pointer is\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
-\r
- /* Check the task was created correctly, then delete the task. */\r
- configASSERT( xReturned == pdPASS );\r
- ( void ) xReturned; /* In case configASSERT() is not defined. */\r
- vTaskDelete( xCreatedTask );\r
-\r
- /* Ensure lower priority tasks get CPU time. */\r
- vTaskDelay( prvGetNextDelayTime() );\r
-\r
- /* Create and delete the task a few times again - testing both static and\r
- dynamic allocation for the stack and TCB. */\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
- staticTASK_PRIORITY + 1, /* The priority of the task. */\r
- &xCreatedTask, /* Handle of the task being created. */\r
- NULL, /* This time, dynamically allocate the stack. */\r
- &xTCBBuffer ); /* The variable that will hold that task's TCB. */\r
-\r
- configASSERT( xReturned == pdPASS );\r
- ( void ) xReturned; /* In case configASSERT() is not defined. */\r
- vTaskDelete( xCreatedTask );\r
-\r
- /* Just to show the check task that this task is still executing. */\r
- uxCycleCounter++;\r
-\r
- /* Ensure lower priority tasks get CPU time. */\r
- vTaskDelay( prvGetNextDelayTime() );\r
-\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
- staticTASK_PRIORITY - 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
- NULL ); /* This time dynamically allocate the TCB. */\r
-\r
- configASSERT( xReturned == pdPASS );\r
- ( void ) xReturned; /* In case configASSERT() is not defined. */\r
- vTaskDelete( xCreatedTask );\r
-\r
- /* Ensure lower priority tasks get CPU time. */\r
- vTaskDelay( prvGetNextDelayTime() );\r
-\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
- staticTASK_PRIORITY, /* The priority of the task. */\r
- &xCreatedTask, /* Handle of the task being created. */\r
- NULL, /* This time dynamically allocate the stack and TCB. */\r
- NULL ); /* This time dynamically allocate the stack and TCB. */\r
-\r
- configASSERT( xReturned == pdPASS );\r
- ( void ) xReturned; /* In case configASSERT() is not defined. */\r
- vTaskDelete( xCreatedTask );\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
+ prvCreateAndDeleteStaticallyAllocatedTasks();\r
+ prvCreateAndDeleteStaticallyAllocatedQueues();\r
+ prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckSemaphoreFunction( 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( ( 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( ( 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 prvCheckQueueFunction( 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 prvCreateAndDeleteStaticallyAllocatedQueues( void )\r
+{\r
+QueueHandle_t xQueue;\r
+\r
+/* StaticQueue_t is a publicly accessible structure that has the same size and\r
+alignment requirements as the real queue structure. It is provided as a\r
+mechanism for applications to know the size of the queue (which is dependent on\r
+the architecture and configuration file settings) without breaking the strict\r
+data hiding policy by exposing the real queue internals. This StaticQueue_t\r
+variable is passed into the xQueueCreateStatic() function calls within this\r
+function. */\r
+static StaticQueue_t xStaticQueue;\r
+\r
+/* The queue storage area must be large enough to hold the maximum number of\r
+items it is possible for the queue to hold at any one time, which equals the\r
+queue length (in items, not bytes) multiplied by the size of each item. In this\r
+case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items. See\r
+http://www.freertos.org/Embedded-RTOS-Queues.html */\r
+static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ];\r
+\r
+ /* Create the queue. xQueueCreateStatic() has two more parameters than the\r
+ usual xQueueCreate() function. The first new paraemter is a pointer to the\r
+ pre-allocated queue storage area. The second new parameter is a pointer to\r
+ the StaticQueue_t structure that will hold the queue state information in\r
+ an anonymous way. If either pointer is passed as NULL then the respective\r
+ data will be allocated dynamically as if xQueueCreate() had been called. */\r
+ xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
+ sizeof( uint64_t ), /* The size of each item. */\r
+ ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
+ &xStaticQueue ); /* The static queue structure that will hold the state of the queue. */\r
+\r
+ /* The queue handle should equal the static queue structure passed into the\r
+ xQueueCreateStatic() function. */\r
+ configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
+\r
+ /* Ensure the queue passes a few sanity checks as a valid queue. */\r
+ prvCheckQueueFunction( xQueue );\r
+\r
+ /* Delete the queue again so the buffers can be reused. */\r
+ vQueueDelete( xQueue );\r
+\r
+\r
+ /* The queue created above had a statically allocated queue storage area and\r
+ queue structure. Repeat the above with three more times - with different\r
+ combinations of static and dynamic allocation. */\r
+\r
+ xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
+ sizeof( uint64_t ), /* The size of each item. */\r
+ NULL, /* Allocate the buffer used to hold items within the queue dynamically. */\r
+ &xStaticQueue ); /* The static queue structure that will hold the state of the queue. */\r
+\r
+ configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
+ prvCheckQueueFunction( xQueue );\r
+ vQueueDelete( xQueue );\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
+ xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
+ sizeof( uint64_t ), /* The size of each item. */\r
+ ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
+ NULL ); /* The queue structure is allocated dynamically. */\r
+\r
+ prvCheckQueueFunction( xQueue );\r
+ vQueueDelete( xQueue );\r
+\r
+ xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
+ sizeof( uint64_t ), /* The size of each item. */\r
+ NULL, /* Allocate the buffer used to hold items within the queue dynamically. */\r
+ NULL ); /* The queue structure is allocated dynamically. */\r
+\r
+ prvCheckQueueFunction( xQueue );\r
+ vQueueDelete( xQueue );\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
+\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 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
+static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
+\r
+ /* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more\r
+ parameter than the usual xSemaphoreCreateBinary() 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 xSemaphoreCreateBinary() is called. */\r
+ xSemaphore = xSemaphoreCreateBinaryStatic( &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, 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 xSemaphoreCreateBinaryStatic()\r
+ parameter so the queue structure is instead allocated dynamically. */\r
+ xSemaphore = xSemaphoreCreateBinaryStatic( NULL );\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
+\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
+ vSemaphoreCreateBinary( xSemaphore );\r
+\r
+ /* The macro starts with the binary semaphore available, but the test\r
+ function expects it to be unavailable. */\r
+ if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+\r
+ prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\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 prvCreateAndDeleteStaticallyAllocatedTasks( void )\r
+{\r
+TaskHandle_t xCreatedTask;\r
+BaseType_t xReturned;\r
+\r
+/* The variable that will hold the TCB of tasks created by this function. See\r
+the comments above the declaration of the xCreatorTaskTCBBuffer variable for\r
+more information. */\r
+static StaticTCB_t xTCBBuffer; /* Static so it does not use too much stack space. */\r
+\r
+/* This buffer that will be used as the stack of tasks created by this function.\r
+See the comments above the declaration of the uxCreatorTaskStackBuffer[] array\r
+above for more information. */\r
+static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];\r
+\r
+ /* Create the task. xTaskCreateStatic() has two more parameters than\r
+ the usual xTaskCreate() function. The first new parameter is a pointer to\r
+ the pre-allocated stack. The second new parameter is a pointer to the\r
+ StaticTCB_t structure that will hold the task's TCB. If either pointer is\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
+\r
+ /* Check the task was created correctly, then delete the task. */\r
+ configASSERT( xReturned == pdPASS );\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ vTaskDelete( xCreatedTask );\r
+\r
+ /* Ensure lower priority tasks get CPU time. */\r
+ vTaskDelay( prvGetNextDelayTime() );\r
+\r
+ /* Create and delete the task a few times again - testing both static and\r
+ dynamic allocation for the stack and TCB. */\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
+ staticTASK_PRIORITY + 1, /* The priority of the task. */\r
+ &xCreatedTask, /* Handle of the task being created. */\r
+ NULL, /* This time, dynamically allocate the stack. */\r
+ &xTCBBuffer ); /* The variable that will hold that task's TCB. */\r
+\r
+ configASSERT( xReturned == pdPASS );\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ vTaskDelete( xCreatedTask );\r
+\r
+ /* Just to show the check task that this task is still executing. */\r
+ uxCycleCounter++;\r
+\r
+ /* Ensure lower priority tasks get CPU time. */\r
+ vTaskDelay( prvGetNextDelayTime() );\r
+\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
+ staticTASK_PRIORITY - 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
+ NULL ); /* This time dynamically allocate the TCB. */\r
+\r
+ configASSERT( xReturned == pdPASS );\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ vTaskDelete( xCreatedTask );\r
+\r
+ /* Ensure lower priority tasks get CPU time. */\r
+ vTaskDelay( prvGetNextDelayTime() );\r
+\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
+ staticTASK_PRIORITY, /* The priority of the task. */\r
+ &xCreatedTask, /* Handle of the task being created. */\r
+ NULL, /* This time dynamically allocate the stack and TCB. */\r
+ NULL ); /* This time dynamically allocate the stack and TCB. */\r
+\r
+ configASSERT( xReturned == pdPASS );\r
+ if( xReturned != pdPASS )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ vTaskDelete( xCreatedTask );\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
BaseType_t xReturn;\r
\r
if( uxCycleCounter == uxLastCycleCounter )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ }\r
+ else\r
+ {\r
+ uxLastCycleCounter = uxCycleCounter;\r
+ }\r
+\r
+ if( xErrorOccurred != pdFALSE )\r
{\r
xReturn = pdFAIL;\r
}\r
else\r
{\r
xReturn = pdPASS;\r
- uxLastCycleCounter = uxCycleCounter;\r
}\r
\r
return xReturn;\r