]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/StaticAllocation.c
Continue to add the ability to create RTOS objects using static rather than dynamic...
[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  * A function that demonstrates and tests the xSemaphoreCreateMutexStatic() API\r
150  * macro by creating and then deleting mutexes with both dynamically and\r
151  * statically allocated semaphore structures.\r
152  */\r
153 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void );\r
154 \r
155 /*\r
156  * A function that demonstrates and tests the xSemaphoreCreateCountingStatic()\r
157  * API macro by creating and then deleting counting semaphores with both\r
158  * dynamically and statically allocated semaphore structures.\r
159  */\r
160 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void );\r
161 \r
162 /*\r
163  * A function that demonstrates and tests the\r
164  * xSemaphoreCreateRecursiveMutexStatic() API macro by creating and then\r
165  * deleting recursive mutexes with both dynamically and statically allocated\r
166  * semaphore structures.\r
167  */\r
168 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );\r
169 \r
170 /*\r
171  * The task that creates and deletes other tasks has to delay occasionally to\r
172  * ensure lower priority tasks are not starved of processing time.  A pseudo\r
173  * random delay time is used just to add a little bit of randomisation into the\r
174  * execution pattern.  prvGetNextDelayTime() generates the pseudo random delay.\r
175  */\r
176 static TickType_t prvGetNextDelayTime( void );\r
177 \r
178 /*\r
179  * Checks the basic operation of a queue after it has been created.\r
180  */\r
181 static void prvCheckQueueFunction( QueueHandle_t xQueue );\r
182 \r
183 /*\r
184  * Checks the basic operation of a recursive mutex after it has been created.\r
185  */\r
186 static void prvCheckRecursiveSemaphoreFunction( SemaphoreHandle_t xSemaphore );\r
187 \r
188 /*\r
189  * Checks the basic operation of a binary semaphore after it has been created.\r
190  */\r
191 static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount );\r
192 \r
193 /*-----------------------------------------------------------*/\r
194 \r
195 /* StaticTCB_t is a publicly accessible structure that has the same size and\r
196 alignment requirements as the real TCB structure.  It is provided as a mechanism\r
197 for applications to know the size of the TCB (which is dependent on the\r
198 architecture and configuration file settings) without breaking the strict data\r
199 hiding policy by exposing the real TCB.  This StaticTCB_t variable is passed\r
200 into the xTaskCreateStatic() function that creates the\r
201 prvStaticallyAllocatedCreator() task, and will hold the TCB of the created\r
202 tasks. */\r
203 static StaticTCB_t xCreatorTaskTCBBuffer;\r
204 \r
205 /* This is the stack that will be used by the prvStaticallyAllocatedCreator()\r
206 task, which is itself created using statically allocated buffers (so without any\r
207 dynamic memory allocation). */\r
208 static StackType_t uxCreatorTaskStackBuffer[ configMINIMAL_STACK_SIZE ];\r
209 \r
210 /* Used by the pseudo random number generating function. */\r
211 static uint32_t ulNextRand = 0;\r
212 \r
213 /* Used so a check task can ensure this test is still executing, and not\r
214 stalled. */\r
215 static volatile UBaseType_t uxCycleCounter = 0;\r
216 \r
217 /* A variable that gets set to pdTRUE if an error is detected. */\r
218 static BaseType_t xErrorOccurred = pdFALSE;\r
219 \r
220 /*-----------------------------------------------------------*/\r
221 \r
222 void vStartStaticallyAllocatedTasks( void  )\r
223 {\r
224         /* Create a single task, which then repeatedly creates and deletes the\r
225         task implemented by prvStaticallyAllocatedTask() at various different\r
226         priorities, and both with and without statically allocated TCB and stack. */\r
227         xTaskCreateStatic( prvStaticallyAllocatedCreator,       /* The function that implements the task being created. */\r
228                                            "StatCreate",                                                /* Text name for the task - not used by the RTOS, its just to assist debugging. */\r
229                                            configMINIMAL_STACK_SIZE,                    /* Size of the buffer passed in as the stack - in words, not bytes! */\r
230                                            NULL,                                                                /* Parameter passed into the task - not used in this case. */\r
231                                            staticTASK_PRIORITY,                                 /* Priority of the task. */\r
232                                            NULL,                                                                /* Handle of the task being created, not used in this case. */\r
233                                            &( uxCreatorTaskStackBuffer[ 0 ] ),  /* The buffer to use as the task's stack. */\r
234                                            &xCreatorTaskTCBBuffer );                    /* The variable that will hold the task's TCB. */\r
235 \r
236         /* Pseudo seed the random number generator. */\r
237         ulNextRand = ( uint32_t ) prvRand;\r
238 }\r
239 /*-----------------------------------------------------------*/\r
240 \r
241 static void prvStaticallyAllocatedCreator( void *pvParameters )\r
242 {\r
243         /* Avoid compiler warnings. */\r
244         ( void ) pvParameters;\r
245 \r
246         for( ;; )\r
247         {\r
248                 /* Loop, running functions that create and delete the various objects\r
249                 that can be optionally created using either static or dynamic memory\r
250                 allocation. */\r
251                 prvCreateAndDeleteStaticallyAllocatedTasks();\r
252                 prvCreateAndDeleteStaticallyAllocatedQueues();\r
253                 prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();\r
254                 prvCreateAndDeleteStaticallyAllocatedCountingSemaphores();\r
255                 prvCreateAndDeleteStaticallyAllocatedMutexes();\r
256                 prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes();\r
257         }\r
258 }\r
259 /*-----------------------------------------------------------*/\r
260 \r
261 static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )\r
262 {\r
263 BaseType_t xReturned;\r
264 UBaseType_t x;\r
265 const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );\r
266 TickType_t xTickCount;\r
267 \r
268         /* The binary semaphore should start 'empty', so a call to xSemaphoreTake()\r
269         should fail. */\r
270         xTickCount = xTaskGetTickCount();\r
271         xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
272 \r
273         if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )\r
274         {\r
275                 /* Did not block on the semaphore as long as expected. */\r
276                 xErrorOccurred = pdTRUE;\r
277         }\r
278 \r
279         if( xReturned != pdFAIL )\r
280         {\r
281                 xErrorOccurred = pdTRUE;\r
282         }\r
283 \r
284         /* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount\r
285         times. */\r
286         for( x = 0; x < uxMaxCount; x++ )\r
287         {\r
288                 xReturned = xSemaphoreGive( xSemaphore );\r
289 \r
290                 if( xReturned == pdFAIL )\r
291                 {\r
292                         xErrorOccurred = pdTRUE;\r
293                 }\r
294         }\r
295 \r
296         /* Giving the semaphore again should fail, as it is 'full'. */\r
297         xReturned = xSemaphoreGive( xSemaphore );\r
298 \r
299         if( xReturned != pdFAIL )\r
300         {\r
301                 xErrorOccurred = pdTRUE;\r
302         }\r
303 \r
304         configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );\r
305 \r
306         /* Should now be possible to 'take' the semaphore up to a maximum of\r
307         uxMaxCount times without blocking. */\r
308         for( x = 0; x < uxMaxCount; x++ )\r
309         {\r
310                 xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
311 \r
312                 if( xReturned == pdFAIL )\r
313                 {\r
314                         xErrorOccurred = pdTRUE;\r
315                 }\r
316         }\r
317 \r
318         /* Back to the starting condition, where the semaphore should not be\r
319         available. */\r
320         xTickCount = xTaskGetTickCount();\r
321         xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
322 \r
323         if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )\r
324         {\r
325                 /* Did not block on the semaphore as long as expected. */\r
326                 xErrorOccurred = pdTRUE;\r
327         }\r
328 \r
329         if( xReturned != pdFAIL )\r
330         {\r
331                 xErrorOccurred = pdTRUE;\r
332         }\r
333 \r
334         configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );\r
335 }\r
336 /*-----------------------------------------------------------*/\r
337 \r
338 static void prvCheckQueueFunction( QueueHandle_t xQueue )\r
339 {\r
340 uint64_t ull, ullRead;\r
341 BaseType_t xReturned, xLoop;\r
342 \r
343         /* This test is done twice to ensure the queue storage area wraps. */\r
344         for( xLoop = 0; xLoop < 2; xLoop++ )\r
345         {\r
346                 /* A very basic test that the queue can be written to and read from as\r
347                 expected.  First the queue should be empty. */\r
348                 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
349                 if( xReturned != errQUEUE_EMPTY )\r
350                 {\r
351                         xErrorOccurred = pdTRUE;\r
352                 }\r
353 \r
354                 /* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS\r
355                 times. */\r
356                 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
357                 {\r
358                         xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
359                         if( xReturned != pdPASS )\r
360                         {\r
361                                 xErrorOccurred = pdTRUE;\r
362                         }\r
363                 }\r
364 \r
365                 /* Should not now be possible to write to the queue again. */\r
366                 xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
367                 if( xReturned != errQUEUE_FULL )\r
368                 {\r
369                         xErrorOccurred = pdTRUE;\r
370                 }\r
371 \r
372                 /* Now read back from the queue to ensure the data read back matches that\r
373                 written. */\r
374                 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
375                 {\r
376                         xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );\r
377 \r
378                         if( xReturned != pdPASS )\r
379                         {\r
380                                 xErrorOccurred = pdTRUE;\r
381                         }\r
382 \r
383                         if( ullRead != ull )\r
384                         {\r
385                                 xErrorOccurred = pdTRUE;\r
386                         }\r
387                 }\r
388 \r
389                 /* The queue should be empty again. */\r
390                 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
391                 if( xReturned != errQUEUE_EMPTY )\r
392                 {\r
393                         xErrorOccurred = pdTRUE;\r
394                 }\r
395         }\r
396 }\r
397 /*-----------------------------------------------------------*/\r
398 \r
399 static void prvCheckRecursiveSemaphoreFunction( SemaphoreHandle_t xSemaphore )\r
400 {\r
401 const BaseType_t xLoops = 5;\r
402 BaseType_t x, xReturned;\r
403 \r
404         /* A very basic test that the recursive semaphore behaved like a recursive\r
405         semaphore. First the semaphore should not be able to be given, as it has not\r
406         yet been taken. */\r
407         xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
408 \r
409         if( xReturned != pdFAIL )\r
410         {\r
411                 xErrorOccurred = pdTRUE;\r
412         }\r
413 \r
414         /* Now it should be possible to take the mutex a number of times. */\r
415         for( x = 0; x < xLoops; x++ )\r
416         {\r
417                 xReturned = xSemaphoreTakeRecursive( xSemaphore, staticDONT_BLOCK );\r
418 \r
419                 if( xReturned != pdPASS )\r
420                 {\r
421                         xErrorOccurred = pdTRUE;\r
422                 }\r
423         }\r
424 \r
425         /* Should be possible to give the semaphore the same number of times as it\r
426         was given in the loop above. */\r
427         for( x = 0; x < xLoops; x++ )\r
428         {\r
429                 xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
430 \r
431                 if( xReturned != pdPASS )\r
432                 {\r
433                         xErrorOccurred = pdTRUE;\r
434                 }\r
435         }\r
436 \r
437         /* No more gives should be possible though. */\r
438         xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
439 \r
440         if( xReturned != pdFAIL )\r
441         {\r
442                 xErrorOccurred = pdTRUE;\r
443         }\r
444 }\r
445 /*-----------------------------------------------------------*/\r
446 \r
447 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void )\r
448 {\r
449 SemaphoreHandle_t xSemaphore;\r
450 const UBaseType_t uxMaxCount = ( UBaseType_t ) 10;\r
451 \r
452 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
453 and alignment requirements as the real semaphore structure.  It is provided as a\r
454 mechanism for applications to know the size of the semaphore (which is dependent\r
455 on the architecture and configuration file settings) without breaking the strict\r
456 data hiding policy by exposing the real semaphore internals.  This\r
457 StaticSemaphore_t variable is passed into the xSemaphoreCreateCountingStatic()\r
458 function calls within this function.  NOTE: In most usage scenarios now it is\r
459 faster and more memory efficient to use a direct to task notification instead of\r
460 a counting semaphore.  http://www.freertos.org/RTOS-task-notifications.html */\r
461 static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
462 \r
463         /* Create the semaphore.  xSemaphoreCreateCountingStatic() has one more\r
464         parameter than the usual xSemaphoreCreateCounting() function.  The paraemter\r
465         is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
466         hold information on the semaphore in an anonymous way.  If the pointer is\r
467         passed as NULL then the structure will be allocated dynamically, just as\r
468         when xSemaphoreCreateCounting() is called. */\r
469         xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, &xSemaphoreBuffer );\r
470 \r
471         /* The semaphore handle should equal the static semaphore structure passed\r
472         into the xSemaphoreCreateBinaryStatic() function. */\r
473         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
474 \r
475         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
476         prvCheckSemaphoreFunction( xSemaphore, uxMaxCount );\r
477 \r
478         /* Delete the semaphore again so the buffers can be reused. */\r
479         vSemaphoreDelete( xSemaphore );\r
480 \r
481 \r
482         /* The semaphore created above had a statically allocated semaphore\r
483         structure.  Repeat the above using NULL as the third\r
484         xSemaphoreCreateCountingStatic() parameter so the semaphore structure is\r
485         instead allocated dynamically. */\r
486         xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, NULL );\r
487 \r
488         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
489         prvCheckSemaphoreFunction( xSemaphore, uxMaxCount );\r
490 \r
491         /* Delete the semaphore again so the buffers can be reused. */\r
492         vSemaphoreDelete( xSemaphore );\r
493 \r
494         /* Ensure lower priority tasks get CPU time. */\r
495         vTaskDelay( prvGetNextDelayTime() );\r
496 \r
497         /* Just to show the check task that this task is still executing. */\r
498         uxCycleCounter++;\r
499 }\r
500 /*-----------------------------------------------------------*/\r
501 \r
502 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void )\r
503 {\r
504 SemaphoreHandle_t xSemaphore;\r
505 \r
506 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
507 and alignment requirements as the real semaphore structure.  It is provided as a\r
508 mechanism for applications to know the size of the semaphore (which is dependent\r
509 on the architecture and configuration file settings) without breaking the strict\r
510 data hiding policy by exposing the real semaphore internals.  This\r
511 StaticSemaphore_t variable is passed into the\r
512 xSemaphoreCreateRecursiveMutexStatic() function calls within this function. */\r
513 static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
514 \r
515         /* Create the semaphore.  xSemaphoreCreateRecursiveMutexStatic() has one\r
516         more parameter than the usual xSemaphoreCreateRecursiveMutex() function.\r
517         The parameter is a pointer to the pre-allocated StaticSemaphore_t structure,\r
518         which will hold information on the semaphore in an anonymous way.  If the\r
519         pointer is passed as NULL then the structure will be allocated dynamically,\r
520         just as when xSemaphoreCreateRecursiveMutex() is called. */\r
521         xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );\r
522 \r
523         /* The semaphore handle should equal the static semaphore structure passed\r
524         into the xSemaphoreCreateBinaryStatic() function. */\r
525         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
526 \r
527         /* Ensure the semaphore passes a few sanity checks as a valid\r
528         recursive semaphore. */\r
529         prvCheckRecursiveSemaphoreFunction( xSemaphore );\r
530 \r
531         /* Delete the semaphore again so the buffers can be reused. */\r
532         vSemaphoreDelete( xSemaphore );\r
533 \r
534 \r
535         /* The semaphore created above had a statically allocated semaphore\r
536         structure.  Repeat the above using NULL as the\r
537         xSemaphoreCreateRecursiveMutexStatic() parameter so the semaphore structure\r
538         is instead allocated dynamically. */\r
539         xSemaphore = xSemaphoreCreateRecursiveMutexStatic( NULL );\r
540 \r
541         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
542         prvCheckRecursiveSemaphoreFunction( xSemaphore );\r
543 \r
544         /* Delete the semaphore again so the buffers can be reused. */\r
545         vSemaphoreDelete( xSemaphore );\r
546 \r
547         /* Ensure lower priority tasks get CPU time. */\r
548         vTaskDelay( prvGetNextDelayTime() );\r
549 \r
550         /* Just to show the check task that this task is still executing. */\r
551         uxCycleCounter++;\r
552 }\r
553 /*-----------------------------------------------------------*/\r
554 \r
555 static void prvCreateAndDeleteStaticallyAllocatedQueues( void )\r
556 {\r
557 QueueHandle_t xQueue;\r
558 \r
559 /* StaticQueue_t is a publicly accessible structure that has the same size and\r
560 alignment requirements as the real queue structure.  It is provided as a\r
561 mechanism for applications to know the size of the queue (which is dependent on\r
562 the architecture and configuration file settings) without breaking the strict\r
563 data hiding policy by exposing the real queue internals.  This StaticQueue_t\r
564 variable is passed into the xQueueCreateStatic() function calls within this\r
565 function. */\r
566 static StaticQueue_t xStaticQueue;\r
567 \r
568 /* The queue storage area must be large enough to hold the maximum number of\r
569 items it is possible for the queue to hold at any one time, which equals the\r
570 queue length (in items, not bytes) multiplied by the size of each item.  In this\r
571 case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items.  See\r
572 http://www.freertos.org/Embedded-RTOS-Queues.html */\r
573 static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ];\r
574 \r
575         /* Create the queue.  xQueueCreateStatic() has two more parameters than the\r
576         usual xQueueCreate() function.  The first new paraemter is a pointer to the\r
577         pre-allocated queue storage area.  The second new parameter is a pointer to\r
578         the StaticQueue_t structure that will hold the queue state information in\r
579         an anonymous way.  If either pointer is passed as NULL then the respective\r
580         data will be allocated dynamically as if xQueueCreate() had been called. */\r
581         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
582                                                                  sizeof( uint64_t ), /* The size of each item. */\r
583                                                                  ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
584                                                                  &xStaticQueue );        /* The static queue structure that will hold the state of the queue. */\r
585 \r
586         /* The queue handle should equal the static queue structure passed into the\r
587         xQueueCreateStatic() function. */\r
588         configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
589 \r
590         /* Ensure the queue passes a few sanity checks as a valid queue. */\r
591         prvCheckQueueFunction( xQueue );\r
592 \r
593         /* Delete the queue again so the buffers can be reused. */\r
594         vQueueDelete( xQueue );\r
595 \r
596 \r
597         /* The queue created above had a statically allocated queue storage area and\r
598         queue structure.  Repeat the above with three more times - with different\r
599         combinations of static and dynamic allocation. */\r
600 \r
601         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
602                                                                  sizeof( uint64_t ), /* The size of each item. */\r
603                                                                  NULL,                           /* Allocate the buffer used to hold items within the queue dynamically. */\r
604                                                                  &xStaticQueue );        /* The static queue structure that will hold the state of the queue. */\r
605 \r
606         configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
607         prvCheckQueueFunction( xQueue );\r
608         vQueueDelete( xQueue );\r
609 \r
610         /* Ensure lower priority tasks get CPU time. */\r
611         vTaskDelay( prvGetNextDelayTime() );\r
612 \r
613         /* Just to show the check task that this task is still executing. */\r
614         uxCycleCounter++;\r
615 \r
616         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
617                                                                  sizeof( uint64_t ), /* The size of each item. */\r
618                                                                  ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
619                                                                  NULL );                         /* The queue structure is allocated dynamically. */\r
620 \r
621         prvCheckQueueFunction( xQueue );\r
622         vQueueDelete( xQueue );\r
623 \r
624         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
625                                                                  sizeof( uint64_t ), /* The size of each item. */\r
626                                                                  NULL,                           /* Allocate the buffer used to hold items within the queue dynamically. */\r
627                                                                  NULL );                         /* The queue structure is allocated dynamically. */\r
628 \r
629         prvCheckQueueFunction( xQueue );\r
630         vQueueDelete( xQueue );\r
631 \r
632         /* Ensure lower priority tasks get CPU time. */\r
633         vTaskDelay( prvGetNextDelayTime() );\r
634 \r
635         /* Just to show the check task that this task is still executing. */\r
636         uxCycleCounter++;\r
637 }\r
638 /*-----------------------------------------------------------*/\r
639 \r
640 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void )\r
641 {\r
642 SemaphoreHandle_t xSemaphore;\r
643 BaseType_t xReturned;\r
644 \r
645 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
646 and alignment requirements as the real semaphore structure.  It is provided as a\r
647 mechanism for applications to know the size of the semaphore (which is dependent\r
648 on the architecture and configuration file settings) without breaking the strict\r
649 data hiding policy by exposing the real semaphore internals.  This\r
650 StaticSemaphore_t variable is passed into the xSemaphoreCreateMutexStatic()\r
651 function calls within this function. */\r
652 static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
653 \r
654         /* Create the semaphore.  xSemaphoreCreateMutexStatic() has one more\r
655         parameter than the usual xSemaphoreCreateMutex() function.  The paraemter\r
656         is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
657         hold information on the semaphore in an anonymous way.  If the pointer is\r
658         passed as NULL then the structure will be allocated dynamically, just as\r
659         when xSemaphoreCreateMutex() is called. */\r
660         xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );\r
661 \r
662         /* The semaphore handle should equal the static semaphore structure passed\r
663         into the xSemaphoreCreateMutexStatic() function. */\r
664         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
665 \r
666         /* Take the mutex so the mutex is in the state expected by the\r
667         prvCheckSemaphoreFunction() function. */\r
668         xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
669 \r
670         if( xReturned != pdPASS )\r
671         {\r
672                 xErrorOccurred = pdTRUE;\r
673         }\r
674 \r
675         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
676         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
677 \r
678         /* Delete the semaphore again so the buffers can be reused. */\r
679         vSemaphoreDelete( xSemaphore );\r
680 \r
681 \r
682         /* The semaphore created above had a statically allocated semaphore\r
683         structure.  Repeat the above using NULL as the xSemaphoreCreateMutexStatic()\r
684         parameter so the semaphore structure is instead allocated dynamically. */\r
685         xSemaphore = xSemaphoreCreateMutexStatic( NULL );\r
686 \r
687         /* Take the mutex so the mutex is in the state expected by the\r
688         prvCheckSemaphoreFunction() function. */\r
689         xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
690 \r
691         if( xReturned != pdPASS )\r
692         {\r
693                 xErrorOccurred = pdTRUE;\r
694         }\r
695 \r
696         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
697         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
698 \r
699         /* Delete the semaphore again so the buffers can be reused. */\r
700         vSemaphoreDelete( xSemaphore );\r
701 \r
702         /* Ensure lower priority tasks get CPU time. */\r
703         vTaskDelay( prvGetNextDelayTime() );\r
704 \r
705         /* Just to show the check task that this task is still executing. */\r
706         uxCycleCounter++;\r
707 }\r
708 /*-----------------------------------------------------------*/\r
709 \r
710 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )\r
711 {\r
712 SemaphoreHandle_t xSemaphore;\r
713 \r
714 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
715 and alignment requirements as the real semaphore structure.  It is provided as a\r
716 mechanism for applications to know the size of the semaphore (which is dependent\r
717 on the architecture and configuration file settings) without breaking the strict\r
718 data hiding policy by exposing the real semaphore internals.  This\r
719 StaticSemaphore_t variable is passed into the xSemaphoreCreateBinaryStatic()\r
720 function calls within this function.  NOTE: In most usage scenarios now it is\r
721 faster and more memory efficient to use a direct to task notification instead of\r
722 a binary semaphore.  http://www.freertos.org/RTOS-task-notifications.html */\r
723 static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */\r
724 \r
725         /* Create the semaphore.  xSemaphoreCreateBinaryStatic() has one more\r
726         parameter than the usual xSemaphoreCreateBinary() function.  The paraemter\r
727         is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
728         hold information on the semaphore in an anonymous way.  If the pointer is\r
729         passed as NULL then the structure will be allocated dynamically, just as\r
730         when xSemaphoreCreateBinary() is called. */\r
731         xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );\r
732 \r
733         /* The semaphore handle should equal the static semaphore structure passed\r
734         into the xSemaphoreCreateBinaryStatic() function. */\r
735         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
736 \r
737         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
738         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
739 \r
740         /* Delete the semaphore again so the buffers can be reused. */\r
741         vSemaphoreDelete( xSemaphore );\r
742 \r
743 \r
744         /* The semaphore created above had a statically allocated semaphore\r
745         structure.  Repeat the above using NULL as the xSemaphoreCreateBinaryStatic()\r
746         parameter so the semaphore structure is instead allocated dynamically. */\r
747         xSemaphore = xSemaphoreCreateBinaryStatic( NULL );\r
748 \r
749         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
750         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
751 \r
752         /* Delete the semaphore again so the buffers can be reused. */\r
753         vSemaphoreDelete( xSemaphore );\r
754 \r
755 \r
756 \r
757         /* There isn't a static version of the old and deprecated\r
758         vSemaphoreCreateBinary() macro (because its deprecated!), but check it is\r
759         still functioning correctly when configSUPPORT_STATIC_ALLOCATION is set to\r
760         1. */\r
761         vSemaphoreCreateBinary( xSemaphore );\r
762 \r
763         /* The macro starts with the binary semaphore available, but the test\r
764         function expects it to be unavailable. */\r
765         if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL )\r
766         {\r
767                 xErrorOccurred = pdTRUE;\r
768         }\r
769 \r
770         prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
771         vSemaphoreDelete( xSemaphore );\r
772 \r
773         /* Ensure lower priority tasks get CPU time. */\r
774         vTaskDelay( prvGetNextDelayTime() );\r
775 \r
776         /* Just to show the check task that this task is still executing. */\r
777         uxCycleCounter++;\r
778 }\r
779 /*-----------------------------------------------------------*/\r
780 \r
781 static void prvCreateAndDeleteStaticallyAllocatedTasks( void )\r
782 {\r
783 TaskHandle_t xCreatedTask;\r
784 BaseType_t xReturned;\r
785 \r
786 /* The variable that will hold the TCB of tasks created by this function.  See\r
787 the comments above the declaration of the xCreatorTaskTCBBuffer variable for\r
788 more information. */\r
789 static StaticTCB_t xTCBBuffer; /* Static so it does not use too much stack space. */\r
790 \r
791 /* This buffer that will be used as the stack of tasks created by this function.\r
792 See the comments above the declaration of the uxCreatorTaskStackBuffer[] array\r
793 above for more information. */\r
794 static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];\r
795 \r
796         /* Create the task.  xTaskCreateStatic() has two more parameters than\r
797         the usual xTaskCreate() function.  The first new parameter is a pointer to\r
798         the pre-allocated stack.  The second new parameter is a pointer to the\r
799         StaticTCB_t structure that will hold the task's TCB.  If either pointer is\r
800         passed as NULL then the respective object will be allocated dynamically as\r
801         if xTaskCreate() had been called. */\r
802         xReturned = xTaskCreateStatic(\r
803                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
804                                                 "Static",                                       /* Human readable name for the task. */\r
805                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
806                                                 NULL,                                           /* Parameter to pass into the task. */\r
807                                                 tskIDLE_PRIORITY,                       /* The priority of the task. */\r
808                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
809                                                 &( uxStackBuffer[ 0 ] ),        /* The buffer to use as the task's stack. */\r
810                                                 &xTCBBuffer );                          /* The variable that will hold that task's TCB. */\r
811 \r
812         /* Check the task was created correctly, then delete the task. */\r
813         configASSERT( xReturned == pdPASS );\r
814         if( xReturned != pdPASS )\r
815         {\r
816                 xErrorOccurred = pdTRUE;\r
817         }\r
818         vTaskDelete( xCreatedTask );\r
819 \r
820         /* Ensure lower priority tasks get CPU time. */\r
821         vTaskDelay( prvGetNextDelayTime() );\r
822 \r
823         /* Create and delete the task a few times again - testing both static and\r
824         dynamic allocation for the stack and TCB. */\r
825         xReturned = xTaskCreateStatic(\r
826                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
827                                                 "Static",                                       /* Human readable name for the task. */\r
828                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
829                                                 NULL,                                           /* Parameter to pass into the task. */\r
830                                                 staticTASK_PRIORITY + 1,        /* The priority of the task. */\r
831                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
832                                                 NULL,                                           /* This time, dynamically allocate the stack. */\r
833                                                 &xTCBBuffer );                          /* The variable that will hold that task's TCB. */\r
834 \r
835         configASSERT( xReturned == pdPASS );\r
836         if( xReturned != pdPASS )\r
837         {\r
838                 xErrorOccurred = pdTRUE;\r
839         }\r
840         vTaskDelete( xCreatedTask );\r
841 \r
842         /* Just to show the check task that this task is still executing. */\r
843         uxCycleCounter++;\r
844 \r
845         /* Ensure lower priority tasks get CPU time. */\r
846         vTaskDelay( prvGetNextDelayTime() );\r
847 \r
848         xReturned = xTaskCreateStatic(\r
849                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
850                                                 "Static",                                       /* Human readable name for the task. */\r
851                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
852                                                 NULL,                                           /* Parameter to pass into the task. */\r
853                                                 staticTASK_PRIORITY - 1,        /* The priority of the task. */\r
854                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
855                                                 &( uxStackBuffer[ 0 ] ),        /* The buffer to use as the task's stack. */\r
856                                                 NULL );                                         /* This time dynamically allocate the TCB. */\r
857 \r
858         configASSERT( xReturned == pdPASS );\r
859         if( xReturned != pdPASS )\r
860         {\r
861                 xErrorOccurred = pdTRUE;\r
862         }\r
863         vTaskDelete( xCreatedTask );\r
864 \r
865         /* Ensure lower priority tasks get CPU time. */\r
866         vTaskDelay( prvGetNextDelayTime() );\r
867 \r
868         xReturned = xTaskCreateStatic(\r
869                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
870                                                 "Static",                                       /* Human readable name for the task. */\r
871                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
872                                                 NULL,                                           /* Parameter to pass into the task. */\r
873                                                 staticTASK_PRIORITY,            /* The priority of the task. */\r
874                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
875                                                 NULL,                                           /* This time dynamically allocate the stack and TCB. */\r
876                                                 NULL );                                         /* This time dynamically allocate the stack and TCB. */\r
877 \r
878         configASSERT( xReturned == pdPASS );\r
879         if( xReturned != pdPASS )\r
880         {\r
881                 xErrorOccurred = pdTRUE;\r
882         }\r
883         vTaskDelete( xCreatedTask );\r
884 \r
885         /* Ensure lower priority tasks get CPU time. */\r
886         vTaskDelay( prvGetNextDelayTime() );\r
887 \r
888         /* Just to show the check task that this task is still executing. */\r
889         uxCycleCounter++;\r
890 }\r
891 /*-----------------------------------------------------------*/\r
892 \r
893 static void prvStaticallyAllocatedTask( void *pvParameters )\r
894 {\r
895         ( void ) pvParameters;\r
896 \r
897         /* The created task doesn't do anything - just waits to get deleted. */\r
898         vTaskSuspend( NULL );\r
899 }\r
900 /*-----------------------------------------------------------*/\r
901 \r
902 static UBaseType_t prvRand( void )\r
903 {\r
904 const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;\r
905 \r
906         /* Utility function to generate a pseudo random number. */\r
907         ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;\r
908         return( ( ulNextRand >> 16UL ) & 0x7fffUL );\r
909 }\r
910 /*-----------------------------------------------------------*/\r
911 \r
912 static TickType_t prvGetNextDelayTime( void )\r
913 {\r
914 TickType_t xNextDelay;\r
915 const TickType_t xMaxDelay = pdMS_TO_TICKS( ( TickType_t ) 150 );\r
916 const TickType_t xMinDelay = pdMS_TO_TICKS( ( TickType_t ) 75 );\r
917 const TickType_t xTinyDelay = pdMS_TO_TICKS( ( TickType_t ) 2 );\r
918 \r
919         /* Generate the next delay time.  This is kept within a narrow band so as\r
920         not to disturb the timing of other tests - but does add in some pseudo\r
921         randomisation into the tests. */\r
922         do\r
923         {\r
924                 xNextDelay = prvRand() % xMaxDelay;\r
925 \r
926                 /* Just in case this loop is executed lots of times. */\r
927                 vTaskDelay( xTinyDelay );\r
928 \r
929         } while ( xNextDelay < xMinDelay );\r
930 \r
931         return xNextDelay;\r
932 }\r
933 /*-----------------------------------------------------------*/\r
934 \r
935 BaseType_t xAreStaticAllocationTasksStillRunning( void )\r
936 {\r
937 static UBaseType_t uxLastCycleCounter = 0;\r
938 BaseType_t xReturn;\r
939 \r
940         if( uxCycleCounter == uxLastCycleCounter )\r
941         {\r
942                 xErrorOccurred = pdTRUE;\r
943         }\r
944         else\r
945         {\r
946                 uxLastCycleCounter = uxCycleCounter;\r
947         }\r
948 \r
949         if( xErrorOccurred != pdFALSE )\r
950         {\r
951                 xReturn = pdFAIL;\r
952         }\r
953         else\r
954         {\r
955                 xReturn = pdPASS;\r
956         }\r
957 \r
958         return xReturn;\r
959 }\r
960 /*-----------------------------------------------------------*/\r
961 \r
962 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */\r
963 #endif /* configSUPPORT_STATIC_ALLOCATION == 1 */\r