]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/StaticAllocation.c
Implement functionality that allows the memory required to create a queue or semaphor...
[freertos] / FreeRTOS / Demo / Common / Minimal / StaticAllocation.c
1 /*\r
2     FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 \r
71 /*\r
72  * Demonstrates how to create FreeRTOS objects using pre-allocated memory,\r
73  * rather than the normal dynamically allocated memory.\r
74  *\r
75  * Two buffers are required by a task - one that is used by the task as its\r
76  * stack, and one that holds the task's control block (TCB).\r
77  * prvStaticallyAllocatedCreator() creates and deletes tasks with all\r
78  * possible combinations of statically allocated and dynamically allocated\r
79  * stacks and TCBs.\r
80  */\r
81 \r
82 /* Scheduler include files. */\r
83 #include "FreeRTOS.h"\r
84 #include "task.h"\r
85 #include "queue.h"\r
86 #include "semphr.h"\r
87 \r
88 /* Demo program include files. */\r
89 #include "StaticAllocation.h"\r
90 \r
91 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */\r
92 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
93 \r
94 /* The priority at which the task that performs the tests is created. */\r
95 #define staticTASK_PRIORITY                                     ( tskIDLE_PRIORITY + 2 )\r
96 \r
97 /* The length of the queue, in items, not bytes, used in the queue static\r
98 allocation tests. */\r
99 #define staticQUEUE_LENGTH_IN_ITEMS                     ( 5 )\r
100 \r
101 /* A block time of 0 simply means "don't block". */\r
102 #define staticDONT_BLOCK                                        ( ( TickType_t ) 0 )\r
103 \r
104 /* Binary semaphores have a maximum count of 1. */\r
105 #define staticBINARY_SEMAPHORE_MAX_COUNT        ( 1 )\r
106 \r
107 \r
108 /*-----------------------------------------------------------*/\r
109 \r
110 /*\r
111  * A task that is created and deleted multiple times, using both statically and\r
112  * dynamically allocated stack and TCB.\r
113  */\r
114 static void prvStaticallyAllocatedTask( void *pvParameters );\r
115 \r
116 /*\r
117  * The task that repeatedly creates and deletes statically allocated tasks, and\r
118  * other RTOS objects.\r
119  */\r
120 static void prvStaticallyAllocatedCreator( void *pvParameters );\r
121 \r
122 /*\r
123  * Utility function to create pseudo random numbers.\r
124  */\r
125 static UBaseType_t prvRand( void );\r
126 \r
127 /*\r
128  * A function that demonstrates and tests the xTaskCreateStatic() API function\r
129  * by creating and then deleting tasks with both dynamically and statically\r
130  * allocated TCBs and stacks.\r
131  */\r
132 static void prvCreateAndDeleteStaticallyAllocatedTasks( void );\r
133 \r
134 /*\r
135  * A function that demonstrates and tests the xQueueCreateStatic() API function\r
136  * by creating and then deleting queues with both dynamically and statically\r
137  * allocated queue structures and queue storage areas.\r
138  */\r
139 static void prvCreateAndDeleteStaticallyAllocatedQueues( void );\r
140 \r
141 /*\r
142  * A function that demonstrates and tests the xSemaphoreCreateBinaryStatic() API\r
143  * macro by creating and then deleting binary semaphores with both dynamically\r
144  * and statically allocated semaphore structures.\r
145  */\r
146 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );\r
147 \r
148 /*\r
149  * The task that creates and deletes other tasks has to delay occasionally to\r
150  * ensure lower priority tasks are not starved of processing time.  A pseudo\r
151  * random delay time is used just to add a little bit of randomisation into the\r
152  * execution pattern.  prvGetNextDelayTime() generates the pseudo random delay.\r
153  */\r
154 static TickType_t prvGetNextDelayTime( void );\r
155 \r
156 /*\r
157  * Checks the basic operation of a queue after it has been created.\r
158  */\r
159 static void prvCheckQueueFunction( QueueHandle_t xQueue );\r
160 \r
161 /*\r
162  * Checks the basic operation of a binary semaphore after it has been created.\r
163  */\r
164 static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount );\r
165 \r
166 /*-----------------------------------------------------------*/\r
167 \r
168 /* StaticTCB_t is a publicly accessible structure that has the same size and\r
169 alignment requirements as the real TCB structure.  It is provided as a mechanism\r
170 for applications to know the size of the TCB (which is dependent on the\r
171 architecture and configuration file settings) without breaking the strict data\r
172 hiding policy by exposing the real TCB.  This StaticTCB_t variable is passed\r
173 into the xTaskCreateStatic() function that creates the\r
174 prvStaticallyAllocatedCreator() task, and will hold the TCB of the created\r
175 tasks. */\r
176 static StaticTCB_t xCreatorTaskTCBBuffer;\r
177 \r
178 /* This is the stack that will be used by the prvStaticallyAllocatedCreator()\r
179 task, which is itself created using statically allocated buffers (so without any\r
180 dynamic memory allocation). */\r
181 static StackType_t uxCreatorTaskStackBuffer[ configMINIMAL_STACK_SIZE ];\r
182 \r
183 /* Used by the pseudo random number generating function. */\r
184 static uint32_t ulNextRand = 0;\r
185 \r
186 /* Used so a check task can ensure this test is still executing, and not\r
187 stalled. */\r
188 static volatile UBaseType_t uxCycleCounter = 0;\r
189 \r
190 /* A variable that gets set to pdTRUE if an error is detected. */\r
191 static BaseType_t xErrorOccurred = pdFALSE;\r
192 \r
193 /*-----------------------------------------------------------*/\r
194 \r
195 void vStartStaticallyAllocatedTasks( void  )\r
196 {\r
197         /* Create a single task, which then repeatedly creates and deletes the\r
198         task implemented by prvStaticallyAllocatedTask() at various different\r
199         priorities, and both with and without statically allocated TCB and stack. */\r
200         xTaskCreateStatic( prvStaticallyAllocatedCreator,       /* The function that implements the task being created. */\r
201                                            "StatCreate",                                                /* Text name for the task - not used by the RTOS, its just to assist debugging. */\r
202                                            configMINIMAL_STACK_SIZE,                    /* Size of the buffer passed in as the stack - in words, not bytes! */\r
203                                            NULL,                                                                /* Parameter passed into the task - not used in this case. */\r
204                                            staticTASK_PRIORITY,                                 /* Priority of the task. */\r
205                                            NULL,                                                                /* Handle of the task being created, not used in this case. */\r
206                                            &( uxCreatorTaskStackBuffer[ 0 ] ),  /* The buffer to use as the task's stack. */\r
207                                            &xCreatorTaskTCBBuffer );                    /* The variable that will hold the task's TCB. */\r
208 \r
209         /* Pseudo seed the random number generator. */\r
210         ulNextRand = ( uint32_t ) prvRand;\r
211 }\r
212 /*-----------------------------------------------------------*/\r
213 \r
214 static void prvStaticallyAllocatedCreator( void *pvParameters )\r
215 {\r
216         /* Avoid compiler warnings. */\r
217         ( void ) pvParameters;\r
218 \r
219         for( ;; )\r
220         {\r
221                 prvCreateAndDeleteStaticallyAllocatedTasks();\r
222                 prvCreateAndDeleteStaticallyAllocatedQueues();\r
223                 prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();\r
224         }\r
225 }\r
226 /*-----------------------------------------------------------*/\r
227 \r
228 static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )\r
229 {\r
230 BaseType_t xReturned;\r
231 UBaseType_t x;\r
232 const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );\r
233 TickType_t xTickCount;\r
234 \r
235         /* The binary semaphore should start 'empty', so a call to xSemaphoreTake()\r
236         should fail. */\r
237         xTickCount = xTaskGetTickCount();\r
238         xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
239 \r
240         if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )\r
241         {\r
242                 /* Did not block on the semaphore as long as expected. */\r
243                 xErrorOccurred = pdTRUE;\r
244         }\r
245 \r
246         if( xReturned != pdFAIL )\r
247         {\r
248                 xErrorOccurred = pdTRUE;\r
249         }\r
250 \r
251         /* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount\r
252         times. */\r
253         for( x = 0; x < uxMaxCount; x++ )\r
254         {\r
255                 xReturned = xSemaphoreGive( xSemaphore );\r
256 \r
257                 if( xReturned == pdFAIL )\r
258                 {\r
259                         xErrorOccurred = pdTRUE;\r
260                 }\r
261         }\r
262 \r
263         /* Giving the semaphore again should fail, as it is 'full'. */\r
264         xReturned = xSemaphoreGive( xSemaphore );\r
265 \r
266         if( xReturned != pdFAIL )\r
267         {\r
268                 xErrorOccurred = pdTRUE;\r
269         }\r
270 \r
271         configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );\r
272 \r
273         /* Should now be possible to 'take' the semaphore up to a maximum of\r
274         uxMaxCount times without blocking. */\r
275         for( x = 0; x < uxMaxCount; x++ )\r
276         {\r
277                 xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
278 \r
279                 if( xReturned == pdFAIL )\r
280                 {\r
281                         xErrorOccurred = pdTRUE;\r
282                 }\r
283         }\r
284 \r
285         /* Back to the starting condition, where the semaphore should not be\r
286         available. */\r
287         xTickCount = xTaskGetTickCount();\r
288         xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
289 \r
290         if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )\r
291         {\r
292                 /* Did not block on the semaphore as long as expected. */\r
293                 xErrorOccurred = pdTRUE;\r
294         }\r
295 \r
296         if( xReturned != pdFAIL )\r
297         {\r
298                 xErrorOccurred = pdTRUE;\r
299         }\r
300 \r
301         configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );\r
302 }\r
303 /*-----------------------------------------------------------*/\r
304 \r
305 static void prvCheckQueueFunction( QueueHandle_t xQueue )\r
306 {\r
307 uint64_t ull, ullRead;\r
308 BaseType_t xReturned, xLoop;\r
309 \r
310         /* This test is done twice to ensure the queue storage area wraps. */\r
311         for( xLoop = 0; xLoop < 2; xLoop++ )\r
312         {\r
313                 /* A very basic test that the queue can be written to and read from as\r
314                 expected.  First the queue should be empty. */\r
315                 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
316                 if( xReturned != errQUEUE_EMPTY )\r
317                 {\r
318                         xErrorOccurred = pdTRUE;\r
319                 }\r
320 \r
321                 /* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS\r
322                 times. */\r
323                 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
324                 {\r
325                         xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
326                         if( xReturned != pdPASS )\r
327                         {\r
328                                 xErrorOccurred = pdTRUE;\r
329                         }\r
330                 }\r
331 \r
332                 /* Should not now be possible to write to the queue again. */\r
333                 xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
334                 if( xReturned != errQUEUE_FULL )\r
335                 {\r
336                         xErrorOccurred = pdTRUE;\r
337                 }\r
338 \r
339                 /* Now read back from the queue to ensure the data read back matches that\r
340                 written. */\r
341                 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
342                 {\r
343                         xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );\r
344 \r
345                         if( xReturned != pdPASS )\r
346                         {\r
347                                 xErrorOccurred = pdTRUE;\r
348                         }\r
349 \r
350                         if( ullRead != ull )\r
351                         {\r
352                                 xErrorOccurred = pdTRUE;\r
353                         }\r
354                 }\r
355 \r
356                 /* The queue should be empty again. */\r
357                 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
358                 if( xReturned != errQUEUE_EMPTY )\r
359                 {\r
360                         xErrorOccurred = pdTRUE;\r
361                 }\r
362         }\r
363 }\r
364 /*-----------------------------------------------------------*/\r
365 \r
366 static void prvCreateAndDeleteStaticallyAllocatedQueues( void )\r
367 {\r
368 QueueHandle_t xQueue;\r
369 \r
370 /* StaticQueue_t is a publicly accessible structure that has the same size and\r
371 alignment requirements as the real queue structure.  It is provided as a\r
372 mechanism for applications to know the size of the queue (which is dependent on\r
373 the architecture and configuration file settings) without breaking the strict\r
374 data hiding policy by exposing the real queue internals.  This StaticQueue_t\r
375 variable is passed into the xQueueCreateStatic() function calls within this\r
376 function. */\r
377 static StaticQueue_t xStaticQueue;\r
378 \r
379 /* The queue storage area must be large enough to hold the maximum number of\r
380 items it is possible for the queue to hold at any one time, which equals the\r
381 queue length (in items, not bytes) multiplied by the size of each item.  In this\r
382 case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items.  See\r
383 http://www.freertos.org/Embedded-RTOS-Queues.html */\r
384 static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ];\r
385 \r
386         /* Create the queue.  xQueueCreateStatic() has two more parameters than the\r
387         usual xQueueCreate() function.  The first new paraemter is a pointer to the\r
388         pre-allocated queue storage area.  The second new parameter is a pointer to\r
389         the StaticQueue_t structure that will hold the queue state information in\r
390         an anonymous way.  If either pointer is passed as NULL then the respective\r
391         data will be allocated dynamically as if xQueueCreate() had been called. */\r
392         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
393                                                                  sizeof( uint64_t ), /* The size of each item. */\r
394                                                                  ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
395                                                                  &xStaticQueue );        /* The static queue structure that will hold the state of the queue. */\r
396 \r
397         /* The queue handle should equal the static queue structure passed into the\r
398         xQueueCreateStatic() function. */\r
399         configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
400 \r
401         /* Ensure the queue passes a few sanity checks as a valid queue. */\r
402         prvCheckQueueFunction( xQueue );\r
403 \r
404         /* Delete the queue again so the buffers can be reused. */\r
405         vQueueDelete( xQueue );\r
406 \r
407 \r
408         /* The queue created above had a statically allocated queue storage area and\r
409         queue structure.  Repeat the above with three more times - with different\r
410         combinations of static and dynamic allocation. */\r
411 \r
412         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
413                                                                  sizeof( uint64_t ), /* The size of each item. */\r
414                                                                  NULL,                           /* Allocate the buffer used to hold items within the queue dynamically. */\r
415                                                                  &xStaticQueue );        /* The static queue structure that will hold the state of the queue. */\r
416 \r
417         configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
418         prvCheckQueueFunction( xQueue );\r
419         vQueueDelete( xQueue );\r
420 \r
421         /* Ensure lower priority tasks get CPU time. */\r
422         vTaskDelay( prvGetNextDelayTime() );\r
423 \r
424         /* Just to show the check task that this task is still executing. */\r
425         uxCycleCounter++;\r
426 \r
427         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
428                                                                  sizeof( uint64_t ), /* The size of each item. */\r
429                                                                  ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
430                                                                  NULL );                         /* The queue structure is allocated dynamically. */\r
431 \r
432         prvCheckQueueFunction( xQueue );\r
433         vQueueDelete( xQueue );\r
434 \r
435         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
436                                                                  sizeof( uint64_t ), /* The size of each item. */\r
437                                                                  NULL,                           /* Allocate the buffer used to hold items within the queue dynamically. */\r
438                                                                  NULL );                         /* The queue structure is allocated dynamically. */\r
439 \r
440         prvCheckQueueFunction( xQueue );\r
441         vQueueDelete( xQueue );\r
442 \r
443         /* Ensure lower priority tasks get CPU time. */\r
444         vTaskDelay( prvGetNextDelayTime() );\r
445 \r
446         /* Just to show the check task that this task is still executing. */\r
447         uxCycleCounter++;\r
448 }\r
449 /*-----------------------------------------------------------*/\r
450 \r
451 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )\r
452 {\r
453 SemaphoreHandle_t xSemaphore;\r
454 \r
455 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
456 and alignment requirements as the real semaphore structure.  It is provided as a\r
457 mechanism for applications to know the size of the semaphore (which is dependent\r
458 on the architecture and configuration file settings) without breaking the strict\r
459 data hiding policy by exposing the real semaphore internals.  This\r
460 StaticSemaphore_t variable is passed into the xSemaphoreCreateBinary() function\r
461 calls within this function.  NOTE: In most usage scenarios now it is faster and\r
462 more memory efficient to use a direct to task notification instead of a binary\r
463 semaphore.  http://www.freertos.org/RTOS-task-notifications.html */\r
464 static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
465 \r
466         /* Create the semaphore.  xSemaphoreCreateBinaryStatic() has one more\r
467         parameter than the usual xSemaphoreCreateBinary() function.  The paraemter\r
468         is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
469         hold information on the semaphore in an anonymous way.  If the pointer is\r
470         passed as NULL then the structure will be allocated dynamically, just as\r
471         when xSemaphoreCreateBinary() is called. */\r
472         xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );\r
473 \r
474         /* The semaphore handle should equal the static semaphore structure passed\r
475         into the xSemaphoreCreateBinaryStatic() function. */\r
476         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
477 \r
478         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
479         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
480 \r
481         /* Delete the semaphore again so the buffers can be reused. */\r
482         vSemaphoreDelete( xSemaphore );\r
483 \r
484 \r
485         /* The semaphore created above had a statically allocated semaphore\r
486         structure.  Repeat the above using NULL as the xSemaphoreCreateBinaryStatic()\r
487         parameter so the queue structure is instead allocated dynamically. */\r
488         xSemaphore = xSemaphoreCreateBinaryStatic( NULL );\r
489 \r
490         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
491         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
492 \r
493         /* Delete the semaphore again so the buffers can be reused. */\r
494         vSemaphoreDelete( xSemaphore );\r
495 \r
496 \r
497 \r
498         /* There isn't a static version of the old and deprecated\r
499         vSemaphoreCreateBinary() macro (because its deprecated!), but check it is\r
500         still functioning correctly when configSUPPORT_STATIC_ALLOCATION is set to\r
501         1. */\r
502         vSemaphoreCreateBinary( xSemaphore );\r
503 \r
504         /* The macro starts with the binary semaphore available, but the test\r
505         function expects it to be unavailable. */\r
506         if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL )\r
507         {\r
508                 xErrorOccurred = pdTRUE;\r
509         }\r
510 \r
511         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
512         vSemaphoreDelete( xSemaphore );\r
513 \r
514         /* Ensure lower priority tasks get CPU time. */\r
515         vTaskDelay( prvGetNextDelayTime() );\r
516 \r
517         /* Just to show the check task that this task is still executing. */\r
518         uxCycleCounter++;\r
519 }\r
520 /*-----------------------------------------------------------*/\r
521 \r
522 static void prvCreateAndDeleteStaticallyAllocatedTasks( void )\r
523 {\r
524 TaskHandle_t xCreatedTask;\r
525 BaseType_t xReturned;\r
526 \r
527 /* The variable that will hold the TCB of tasks created by this function.  See\r
528 the comments above the declaration of the xCreatorTaskTCBBuffer variable for\r
529 more information. */\r
530 static StaticTCB_t xTCBBuffer; /* Static so it does not use too much stack space. */\r
531 \r
532 /* This buffer that will be used as the stack of tasks created by this function.\r
533 See the comments above the declaration of the uxCreatorTaskStackBuffer[] array\r
534 above for more information. */\r
535 static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];\r
536 \r
537         /* Create the task.  xTaskCreateStatic() has two more parameters than\r
538         the usual xTaskCreate() function.  The first new parameter is a pointer to\r
539         the pre-allocated stack.  The second new parameter is a pointer to the\r
540         StaticTCB_t structure that will hold the task's TCB.  If either pointer is\r
541         passed as NULL then the respective object will be allocated dynamically as\r
542         if xTaskCreate() had been called. */\r
543         xReturned = xTaskCreateStatic(\r
544                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
545                                                 "Static",                                       /* Human readable name for the task. */\r
546                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
547                                                 NULL,                                           /* Parameter to pass into the task. */\r
548                                                 tskIDLE_PRIORITY,                       /* The priority of the task. */\r
549                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
550                                                 &( uxStackBuffer[ 0 ] ),        /* The buffer to use as the task's stack. */\r
551                                                 &xTCBBuffer );                          /* The variable that will hold that task's TCB. */\r
552 \r
553         /* Check the task was created correctly, then delete the task. */\r
554         configASSERT( xReturned == pdPASS );\r
555         if( xReturned != pdPASS )\r
556         {\r
557                 xErrorOccurred = pdTRUE;\r
558         }\r
559         vTaskDelete( xCreatedTask );\r
560 \r
561         /* Ensure lower priority tasks get CPU time. */\r
562         vTaskDelay( prvGetNextDelayTime() );\r
563 \r
564         /* Create and delete the task a few times again - testing both static and\r
565         dynamic allocation for the stack and TCB. */\r
566         xReturned = xTaskCreateStatic(\r
567                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
568                                                 "Static",                                       /* Human readable name for the task. */\r
569                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
570                                                 NULL,                                           /* Parameter to pass into the task. */\r
571                                                 staticTASK_PRIORITY + 1,        /* The priority of the task. */\r
572                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
573                                                 NULL,                                           /* This time, dynamically allocate the stack. */\r
574                                                 &xTCBBuffer );                          /* The variable that will hold that task's TCB. */\r
575 \r
576         configASSERT( xReturned == pdPASS );\r
577         if( xReturned != pdPASS )\r
578         {\r
579                 xErrorOccurred = pdTRUE;\r
580         }\r
581         vTaskDelete( xCreatedTask );\r
582 \r
583         /* Just to show the check task that this task is still executing. */\r
584         uxCycleCounter++;\r
585 \r
586         /* Ensure lower priority tasks get CPU time. */\r
587         vTaskDelay( prvGetNextDelayTime() );\r
588 \r
589         xReturned = xTaskCreateStatic(\r
590                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
591                                                 "Static",                                       /* Human readable name for the task. */\r
592                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
593                                                 NULL,                                           /* Parameter to pass into the task. */\r
594                                                 staticTASK_PRIORITY - 1,        /* The priority of the task. */\r
595                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
596                                                 &( uxStackBuffer[ 0 ] ),        /* The buffer to use as the task's stack. */\r
597                                                 NULL );                                         /* This time dynamically allocate the TCB. */\r
598 \r
599         configASSERT( xReturned == pdPASS );\r
600         if( xReturned != pdPASS )\r
601         {\r
602                 xErrorOccurred = pdTRUE;\r
603         }\r
604         vTaskDelete( xCreatedTask );\r
605 \r
606         /* Ensure lower priority tasks get CPU time. */\r
607         vTaskDelay( prvGetNextDelayTime() );\r
608 \r
609         xReturned = xTaskCreateStatic(\r
610                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
611                                                 "Static",                                       /* Human readable name for the task. */\r
612                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
613                                                 NULL,                                           /* Parameter to pass into the task. */\r
614                                                 staticTASK_PRIORITY,            /* The priority of the task. */\r
615                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
616                                                 NULL,                                           /* This time dynamically allocate the stack and TCB. */\r
617                                                 NULL );                                         /* This time dynamically allocate the stack and TCB. */\r
618 \r
619         configASSERT( xReturned == pdPASS );\r
620         if( xReturned != pdPASS )\r
621         {\r
622                 xErrorOccurred = pdTRUE;\r
623         }\r
624         vTaskDelete( xCreatedTask );\r
625 \r
626         /* Ensure lower priority tasks get CPU time. */\r
627         vTaskDelay( prvGetNextDelayTime() );\r
628 \r
629         /* Just to show the check task that this task is still executing. */\r
630         uxCycleCounter++;\r
631 }\r
632 /*-----------------------------------------------------------*/\r
633 \r
634 static void prvStaticallyAllocatedTask( void *pvParameters )\r
635 {\r
636         ( void ) pvParameters;\r
637 \r
638         /* The created task doesn't do anything - just waits to get deleted. */\r
639         vTaskSuspend( NULL );\r
640 }\r
641 /*-----------------------------------------------------------*/\r
642 \r
643 static UBaseType_t prvRand( void )\r
644 {\r
645 const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;\r
646 \r
647         /* Utility function to generate a pseudo random number. */\r
648         ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;\r
649         return( ( ulNextRand >> 16UL ) & 0x7fffUL );\r
650 }\r
651 /*-----------------------------------------------------------*/\r
652 \r
653 static TickType_t prvGetNextDelayTime( void )\r
654 {\r
655 TickType_t xNextDelay;\r
656 const TickType_t xMaxDelay = pdMS_TO_TICKS( ( TickType_t ) 150 );\r
657 const TickType_t xMinDelay = pdMS_TO_TICKS( ( TickType_t ) 75 );\r
658 const TickType_t xTinyDelay = pdMS_TO_TICKS( ( TickType_t ) 2 );\r
659 \r
660         /* Generate the next delay time.  This is kept within a narrow band so as\r
661         not to disturb the timing of other tests - but does add in some pseudo\r
662         randomisation into the tests. */\r
663         do\r
664         {\r
665                 xNextDelay = prvRand() % xMaxDelay;\r
666 \r
667                 /* Just in case this loop is executed lots of times. */\r
668                 vTaskDelay( xTinyDelay );\r
669 \r
670         } while ( xNextDelay < xMinDelay );\r
671 \r
672         return xNextDelay;\r
673 }\r
674 /*-----------------------------------------------------------*/\r
675 \r
676 BaseType_t xAreStaticAllocationTasksStillRunning( void )\r
677 {\r
678 static UBaseType_t uxLastCycleCounter = 0;\r
679 BaseType_t xReturn;\r
680 \r
681         if( uxCycleCounter == uxLastCycleCounter )\r
682         {\r
683                 xErrorOccurred = pdTRUE;\r
684         }\r
685         else\r
686         {\r
687                 uxLastCycleCounter = uxCycleCounter;\r
688         }\r
689 \r
690         if( xErrorOccurred != pdFALSE )\r
691         {\r
692                 xReturn = pdFAIL;\r
693         }\r
694         else\r
695         {\r
696                 xReturn = pdPASS;\r
697         }\r
698 \r
699         return xReturn;\r
700 }\r
701 /*-----------------------------------------------------------*/\r
702 \r
703 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */\r
704 #endif /* configSUPPORT_STATIC_ALLOCATION == 1 */\r