]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/StaticAllocation.c
71d4d00b77dc879ca1bd2f7e953a8d278e436e32
[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, and tests objects being\r
74  * created and deleted with both statically allocated memory and dynamically\r
75  * allocated memory.\r
76  */\r
77 \r
78 /* Scheduler include files. */\r
79 #include "FreeRTOS.h"\r
80 #include "task.h"\r
81 #include "queue.h"\r
82 #include "semphr.h"\r
83 #include "event_groups.h"\r
84 #include "timers.h"\r
85 \r
86 /* Demo program include files. */\r
87 #include "StaticAllocation.h"\r
88 \r
89 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */\r
90 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
91 \r
92 /* The priority at which the task that performs the tests is created. */\r
93 #define staticTASK_PRIORITY                                     ( tskIDLE_PRIORITY + 2 )\r
94 \r
95 /* The length of the queue, in items, not bytes, used in the queue static\r
96 allocation tests. */\r
97 #define staticQUEUE_LENGTH_IN_ITEMS                     ( 5 )\r
98 \r
99 /* A block time of 0 simply means "don't block". */\r
100 #define staticDONT_BLOCK                                        ( ( TickType_t ) 0 )\r
101 \r
102 /* Binary semaphores have a maximum count of 1. */\r
103 #define staticBINARY_SEMAPHORE_MAX_COUNT        ( 1 )\r
104 \r
105 /* The size of the stack used by the task that runs the tests. */\r
106 #define staticCREATOR_TASK_STACK_SIZE           ( configMINIMAL_STACK_SIZE * 2 )\r
107 \r
108 /* The number of times the software timer will execute before stopping itself. */\r
109 #define staticMAX_TIMER_CALLBACK_EXECUTIONS     ( 5 )\r
110 \r
111 \r
112 /*-----------------------------------------------------------*/\r
113 \r
114 /*\r
115  * The task that repeatedly creates and deletes statically allocated tasks, and\r
116  * other RTOS objects.\r
117  */\r
118 static void prvStaticallyAllocatedCreator( void *pvParameters );\r
119 \r
120 /*\r
121  * The callback function used by the software timer that is repeatedly created\r
122  * and deleted using both static and dynamically allocated memory.\r
123  */\r
124 static void prvTimerCallback( TimerHandle_t xExpiredTimer );\r
125 \r
126 /*\r
127  * A task that is created and deleted multiple times, using both statically and\r
128  * dynamically allocated stack and TCB.\r
129  */\r
130 static void prvStaticallyAllocatedTask( void *pvParameters );\r
131 \r
132 /*\r
133  * A function that demonstrates and tests the xTaskCreateStatic() API function\r
134  * by creating and then deleting tasks with both dynamically and statically\r
135  * allocated TCBs and stacks.\r
136  */\r
137 static void prvCreateAndDeleteStaticallyAllocatedTasks( void );\r
138 \r
139 /*\r
140  * A function that demonstrates and tests the xEventGroupCreateStatic() API\r
141  * function by creating and then deleting event groups using both dynamically\r
142  * and statically allocated event group structures.\r
143  */\r
144 static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void );\r
145 \r
146 /*\r
147  * A function that demonstrates and tests the xQueueCreateStatic() API function\r
148  * by creating and then deleting queues with both dynamically and statically\r
149  * allocated queue structures and queue storage areas.\r
150  */\r
151 static void prvCreateAndDeleteStaticallyAllocatedQueues( void );\r
152 \r
153 /*\r
154  * A function that demonstrates and tests the xSemaphoreCreateBinaryStatic() API\r
155  * macro by creating and then deleting binary semaphores with both dynamically\r
156  * and statically allocated semaphore structures.\r
157  */\r
158 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );\r
159 \r
160 /*\r
161  * A function that demonstrates and tests the xTimerCreateStatic() API macro by\r
162  * creating and then deleting software timers with both dynamically and\r
163  * statically allocated timer structures.\r
164  */\r
165 static void prvCreateAndDeleteStaticallyAllocatedTimers( void );\r
166 \r
167 /*\r
168  * A function that demonstrates and tests the xSemaphoreCreateMutexStatic() API\r
169  * macro by creating and then deleting mutexes with both dynamically and\r
170  * statically allocated semaphore structures.\r
171  */\r
172 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void );\r
173 \r
174 /*\r
175  * A function that demonstrates and tests the xSemaphoreCreateCountingStatic()\r
176  * API macro by creating and then deleting counting semaphores with both\r
177  * dynamically and statically allocated semaphore structures.\r
178  */\r
179 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void );\r
180 \r
181 /*\r
182  * A function that demonstrates and tests the\r
183  * xSemaphoreCreateRecursiveMutexStatic() API macro by creating and then\r
184  * deleting recursive mutexes with both dynamically and statically allocated\r
185  * semaphore structures.\r
186  */\r
187 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );\r
188 \r
189 /*\r
190  * Utility function to create pseudo random numbers.\r
191  */\r
192 static UBaseType_t prvRand( void );\r
193 \r
194 /*\r
195  * The task that creates and deletes other tasks has to delay occasionally to\r
196  * ensure lower priority tasks are not starved of processing time.  A pseudo\r
197  * random delay time is used just to add a little bit of randomisation into the\r
198  * execution pattern.  prvGetNextDelayTime() generates the pseudo random delay.\r
199  */\r
200 static TickType_t prvGetNextDelayTime( void );\r
201 \r
202 /*\r
203  * Checks the basic operation of a queue after it has been created.\r
204  */\r
205 static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue );\r
206 \r
207 /*\r
208  * Checks the basic operation of a recursive mutex after it has been created.\r
209  */\r
210 static void prvSanityCheckCreatedRecursiveMutex( SemaphoreHandle_t xSemaphore );\r
211 \r
212 /*\r
213  * Checks the basic operation of a binary semaphore after it has been created.\r
214  */\r
215 static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount );\r
216 \r
217 /*\r
218  * Checks the basic operation of an event group after it has been created.\r
219  */\r
220 static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup );\r
221 \r
222 /*-----------------------------------------------------------*/\r
223 \r
224 /* StaticTask_t is a publicly accessible structure that has the same size and\r
225 alignment requirements as the real TCB structure.  It is provided as a mechanism\r
226 for applications to know the size of the TCB (which is dependent on the\r
227 architecture and configuration file settings) without breaking the strict data\r
228 hiding policy by exposing the real TCB.  This StaticTask_t variable is passed\r
229 into the xTaskCreateStatic() function that creates the\r
230 prvStaticallyAllocatedCreator() task, and will hold the TCB of the created\r
231 tasks. */\r
232 static StaticTask_t xCreatorTaskTCBBuffer;\r
233 \r
234 /* This is the stack that will be used by the prvStaticallyAllocatedCreator()\r
235 task, which is itself created using statically allocated buffers (so without any\r
236 dynamic memory allocation). */\r
237 static StackType_t uxCreatorTaskStackBuffer[ staticCREATOR_TASK_STACK_SIZE ];\r
238 \r
239 /* Used by the pseudo random number generating function. */\r
240 static uint32_t ulNextRand = 0;\r
241 \r
242 /* Used so a check task can ensure this test is still executing, and not\r
243 stalled. */\r
244 static volatile UBaseType_t uxCycleCounter = 0;\r
245 \r
246 /* A variable that gets set to pdTRUE if an error is detected. */\r
247 static BaseType_t xErrorOccurred = pdFALSE;\r
248 \r
249 /*-----------------------------------------------------------*/\r
250 \r
251 void vStartStaticallyAllocatedTasks( void  )\r
252 {\r
253         /* Create a single task, which then repeatedly creates and deletes the\r
254         task implemented by prvStaticallyAllocatedTask() at various different\r
255         priorities, and both with and without statically allocated TCB and stack. */\r
256         xTaskCreateStatic( prvStaticallyAllocatedCreator,               /* The function that implements the task being created. */\r
257                                            "StatCreate",                                                /* Text name for the task - not used by the RTOS, its just to assist debugging. */\r
258                                            staticCREATOR_TASK_STACK_SIZE,               /* Size of the buffer passed in as the stack - in words, not bytes! */\r
259                                            NULL,                                                                /* Parameter passed into the task - not used in this case. */\r
260                                            staticTASK_PRIORITY,                                 /* Priority of the task. */\r
261                                            NULL,                                                                /* Handle of the task being created, not used in this case. */\r
262                                            &( uxCreatorTaskStackBuffer[ 0 ] ),  /* The buffer to use as the task's stack. */\r
263                                            &xCreatorTaskTCBBuffer );                    /* The variable that will hold the task's TCB. */\r
264 \r
265         /* Pseudo seed the random number generator. */\r
266         ulNextRand = ( uint32_t ) prvRand;\r
267 }\r
268 /*-----------------------------------------------------------*/\r
269 \r
270 static void prvStaticallyAllocatedCreator( void *pvParameters )\r
271 {\r
272         /* Avoid compiler warnings. */\r
273         ( void ) pvParameters;\r
274 \r
275         for( ;; )\r
276         {\r
277                 /* Loop, running functions that create and delete the various objects\r
278                 that can be optionally created using either static or dynamic memory\r
279                 allocation. */\r
280                 prvCreateAndDeleteStaticallyAllocatedTasks();\r
281                 prvCreateAndDeleteStaticallyAllocatedQueues();\r
282                 prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();\r
283                 prvCreateAndDeleteStaticallyAllocatedCountingSemaphores();\r
284                 prvCreateAndDeleteStaticallyAllocatedMutexes();\r
285                 prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes();\r
286                 prvCreateAndDeleteStaticallyAllocatedEventGroups();\r
287                 prvCreateAndDeleteStaticallyAllocatedTimers();\r
288         }\r
289 }\r
290 /*-----------------------------------------------------------*/\r
291 \r
292 static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup )\r
293 {\r
294 EventBits_t xEventBits;\r
295 const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( EventBits_t ) 0x55;\r
296 \r
297         /* The event group should not have any bits set yet. */\r
298         xEventBits = xEventGroupGetBits( xEventGroup );\r
299 \r
300         if( xEventBits != ( EventBits_t ) 0 )\r
301         {\r
302                 xErrorOccurred = pdTRUE;\r
303         }\r
304 \r
305         /* Some some bits, then read them back to check they are as expected. */\r
306         xEventGroupSetBits( xEventGroup, xFirstTestBits );\r
307 \r
308         xEventBits = xEventGroupGetBits( xEventGroup );\r
309 \r
310         if( xEventBits != xFirstTestBits )\r
311         {\r
312                 xErrorOccurred = pdTRUE;\r
313         }\r
314 \r
315         xEventGroupSetBits( xEventGroup, xSecondTestBits );\r
316 \r
317         xEventBits = xEventGroupGetBits( xEventGroup );\r
318 \r
319         if( xEventBits != ( xFirstTestBits | xSecondTestBits ) )\r
320         {\r
321                 xErrorOccurred = pdTRUE;\r
322         }\r
323 \r
324         /* Finally try clearing some bits too and check that operation proceeds as\r
325         expected. */\r
326         xEventGroupClearBits( xEventGroup, xFirstTestBits );\r
327 \r
328         xEventBits = xEventGroupGetBits( xEventGroup );\r
329 \r
330         if( xEventBits != xSecondTestBits )\r
331         {\r
332                 xErrorOccurred = pdTRUE;\r
333         }\r
334 }\r
335 /*-----------------------------------------------------------*/\r
336 \r
337 static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )\r
338 {\r
339 BaseType_t xReturned;\r
340 UBaseType_t x;\r
341 const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );\r
342 TickType_t xTickCount;\r
343 \r
344         /* The binary semaphore should start 'empty', so a call to xSemaphoreTake()\r
345         should fail. */\r
346         xTickCount = xTaskGetTickCount();\r
347         xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
348 \r
349         if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )\r
350         {\r
351                 /* Did not block on the semaphore as long as expected. */\r
352                 xErrorOccurred = pdTRUE;\r
353         }\r
354 \r
355         if( xReturned != pdFAIL )\r
356         {\r
357                 xErrorOccurred = pdTRUE;\r
358         }\r
359 \r
360         /* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount\r
361         times. */\r
362         for( x = 0; x < uxMaxCount; x++ )\r
363         {\r
364                 xReturned = xSemaphoreGive( xSemaphore );\r
365 \r
366                 if( xReturned == pdFAIL )\r
367                 {\r
368                         xErrorOccurred = pdTRUE;\r
369                 }\r
370         }\r
371 \r
372         /* Giving the semaphore again should fail, as it is 'full'. */\r
373         xReturned = xSemaphoreGive( xSemaphore );\r
374 \r
375         if( xReturned != pdFAIL )\r
376         {\r
377                 xErrorOccurred = pdTRUE;\r
378         }\r
379 \r
380         configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );\r
381 \r
382         /* Should now be possible to 'take' the semaphore up to a maximum of\r
383         uxMaxCount times without blocking. */\r
384         for( x = 0; x < uxMaxCount; x++ )\r
385         {\r
386                 xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
387 \r
388                 if( xReturned == pdFAIL )\r
389                 {\r
390                         xErrorOccurred = pdTRUE;\r
391                 }\r
392         }\r
393 \r
394         /* Back to the starting condition, where the semaphore should not be\r
395         available. */\r
396         xTickCount = xTaskGetTickCount();\r
397         xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );\r
398 \r
399         if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )\r
400         {\r
401                 /* Did not block on the semaphore as long as expected. */\r
402                 xErrorOccurred = pdTRUE;\r
403         }\r
404 \r
405         if( xReturned != pdFAIL )\r
406         {\r
407                 xErrorOccurred = pdTRUE;\r
408         }\r
409 \r
410         configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );\r
411 }\r
412 /*-----------------------------------------------------------*/\r
413 \r
414 static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue )\r
415 {\r
416 uint64_t ull, ullRead;\r
417 BaseType_t xReturned, xLoop;\r
418 \r
419         /* This test is done twice to ensure the queue storage area wraps. */\r
420         for( xLoop = 0; xLoop < 2; xLoop++ )\r
421         {\r
422                 /* A very basic test that the queue can be written to and read from as\r
423                 expected.  First the queue should be empty. */\r
424                 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
425                 if( xReturned != errQUEUE_EMPTY )\r
426                 {\r
427                         xErrorOccurred = pdTRUE;\r
428                 }\r
429 \r
430                 /* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS\r
431                 times. */\r
432                 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
433                 {\r
434                         xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
435                         if( xReturned != pdPASS )\r
436                         {\r
437                                 xErrorOccurred = pdTRUE;\r
438                         }\r
439                 }\r
440 \r
441                 /* Should not now be possible to write to the queue again. */\r
442                 xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );\r
443                 if( xReturned != errQUEUE_FULL )\r
444                 {\r
445                         xErrorOccurred = pdTRUE;\r
446                 }\r
447 \r
448                 /* Now read back from the queue to ensure the data read back matches that\r
449                 written. */\r
450                 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )\r
451                 {\r
452                         xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );\r
453 \r
454                         if( xReturned != pdPASS )\r
455                         {\r
456                                 xErrorOccurred = pdTRUE;\r
457                         }\r
458 \r
459                         if( ullRead != ull )\r
460                         {\r
461                                 xErrorOccurred = pdTRUE;\r
462                         }\r
463                 }\r
464 \r
465                 /* The queue should be empty again. */\r
466                 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );\r
467                 if( xReturned != errQUEUE_EMPTY )\r
468                 {\r
469                         xErrorOccurred = pdTRUE;\r
470                 }\r
471         }\r
472 }\r
473 /*-----------------------------------------------------------*/\r
474 \r
475 static void prvSanityCheckCreatedRecursiveMutex( SemaphoreHandle_t xSemaphore )\r
476 {\r
477 const BaseType_t xLoops = 5;\r
478 BaseType_t x, xReturned;\r
479 \r
480         /* A very basic test that the recursive semaphore behaved like a recursive\r
481         semaphore. First the semaphore should not be able to be given, as it has not\r
482         yet been taken. */\r
483         xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
484 \r
485         if( xReturned != pdFAIL )\r
486         {\r
487                 xErrorOccurred = pdTRUE;\r
488         }\r
489 \r
490         /* Now it should be possible to take the mutex a number of times. */\r
491         for( x = 0; x < xLoops; x++ )\r
492         {\r
493                 xReturned = xSemaphoreTakeRecursive( xSemaphore, staticDONT_BLOCK );\r
494 \r
495                 if( xReturned != pdPASS )\r
496                 {\r
497                         xErrorOccurred = pdTRUE;\r
498                 }\r
499         }\r
500 \r
501         /* Should be possible to give the semaphore the same number of times as it\r
502         was given in the loop above. */\r
503         for( x = 0; x < xLoops; x++ )\r
504         {\r
505                 xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
506 \r
507                 if( xReturned != pdPASS )\r
508                 {\r
509                         xErrorOccurred = pdTRUE;\r
510                 }\r
511         }\r
512 \r
513         /* No more gives should be possible though. */\r
514         xReturned = xSemaphoreGiveRecursive( xSemaphore );\r
515 \r
516         if( xReturned != pdFAIL )\r
517         {\r
518                 xErrorOccurred = pdTRUE;\r
519         }\r
520 }\r
521 /*-----------------------------------------------------------*/\r
522 \r
523 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void )\r
524 {\r
525 SemaphoreHandle_t xSemaphore;\r
526 const UBaseType_t uxMaxCount = ( UBaseType_t ) 10;\r
527 \r
528 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
529 and alignment requirements as the real semaphore structure.  It is provided as a\r
530 mechanism for applications to know the size of the semaphore (which is dependent\r
531 on the architecture and configuration file settings) without breaking the strict\r
532 data hiding policy by exposing the real semaphore internals.  This\r
533 StaticSemaphore_t variable is passed into the xSemaphoreCreateCountingStatic()\r
534 function calls within this function.  NOTE: In most usage scenarios now it is\r
535 faster and more memory efficient to use a direct to task notification instead of\r
536 a counting semaphore.  http://www.freertos.org/RTOS-task-notifications.html */\r
537 StaticSemaphore_t xSemaphoreBuffer;\r
538 \r
539         /* Create the semaphore.  xSemaphoreCreateCountingStatic() has one more\r
540         parameter than the usual xSemaphoreCreateCounting() function.  The paraemter\r
541         is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
542         hold information on the semaphore in an anonymous way.  If the pointer is\r
543         passed as NULL then the structure will be allocated dynamically, just as\r
544         when xSemaphoreCreateCounting() is called. */\r
545         xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, &xSemaphoreBuffer );\r
546 \r
547         /* The semaphore handle should equal the static semaphore structure passed\r
548         into the xSemaphoreCreateBinaryStatic() function. */\r
549         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
550 \r
551         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
552         prvSanityCheckCreatedSemaphore( xSemaphore, uxMaxCount );\r
553 \r
554         /* Delete the semaphore again so the buffers can be reused. */\r
555         vSemaphoreDelete( xSemaphore );\r
556 \r
557 \r
558         /* The semaphore created above had a statically allocated semaphore\r
559         structure.  Repeat the above using NULL as the third\r
560         xSemaphoreCreateCountingStatic() parameter so the semaphore structure is\r
561         instead allocated dynamically. */\r
562         xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, NULL );\r
563 \r
564         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
565         prvSanityCheckCreatedSemaphore( xSemaphore, uxMaxCount );\r
566 \r
567         /* Delete the semaphore again so the buffers can be reused. */\r
568         vSemaphoreDelete( xSemaphore );\r
569 \r
570         /* Ensure lower priority tasks get CPU time. */\r
571         vTaskDelay( prvGetNextDelayTime() );\r
572 \r
573         /* Just to show the check task that this task is still executing. */\r
574         uxCycleCounter++;\r
575 }\r
576 /*-----------------------------------------------------------*/\r
577 \r
578 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void )\r
579 {\r
580 SemaphoreHandle_t xSemaphore;\r
581 \r
582 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
583 and alignment requirements as the real semaphore structure.  It is provided as a\r
584 mechanism for applications to know the size of the semaphore (which is dependent\r
585 on the architecture and configuration file settings) without breaking the strict\r
586 data hiding policy by exposing the real semaphore internals.  This\r
587 StaticSemaphore_t variable is passed into the\r
588 xSemaphoreCreateRecursiveMutexStatic() function calls within this function. */\r
589 StaticSemaphore_t xSemaphoreBuffer;\r
590 \r
591         /* Create the semaphore.  xSemaphoreCreateRecursiveMutexStatic() has one\r
592         more parameter than the usual xSemaphoreCreateRecursiveMutex() function.\r
593         The parameter is a pointer to the pre-allocated StaticSemaphore_t structure,\r
594         which will hold information on the semaphore in an anonymous way.  If the\r
595         pointer is passed as NULL then the structure will be allocated dynamically,\r
596         just as when xSemaphoreCreateRecursiveMutex() is called. */\r
597         xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );\r
598 \r
599         /* The semaphore handle should equal the static semaphore structure passed\r
600         into the xSemaphoreCreateBinaryStatic() function. */\r
601         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
602 \r
603         /* Ensure the semaphore passes a few sanity checks as a valid\r
604         recursive semaphore. */\r
605         prvSanityCheckCreatedRecursiveMutex( xSemaphore );\r
606 \r
607         /* Delete the semaphore again so the buffers can be reused. */\r
608         vSemaphoreDelete( xSemaphore );\r
609 \r
610 \r
611         /* The semaphore created above had a statically allocated semaphore\r
612         structure.  Repeat the above using NULL as the\r
613         xSemaphoreCreateRecursiveMutexStatic() parameter so the semaphore structure\r
614         is instead allocated dynamically. */\r
615         xSemaphore = xSemaphoreCreateRecursiveMutexStatic( NULL );\r
616 \r
617         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
618         prvSanityCheckCreatedRecursiveMutex( xSemaphore );\r
619 \r
620         /* Delete the semaphore again so the buffers can be reused. */\r
621         vSemaphoreDelete( xSemaphore );\r
622 \r
623         /* Ensure lower priority tasks get CPU time. */\r
624         vTaskDelay( prvGetNextDelayTime() );\r
625 \r
626         /* Just to show the check task that this task is still executing. */\r
627         uxCycleCounter++;\r
628 }\r
629 /*-----------------------------------------------------------*/\r
630 \r
631 static void prvCreateAndDeleteStaticallyAllocatedQueues( void )\r
632 {\r
633 QueueHandle_t xQueue;\r
634 \r
635 /* StaticQueue_t is a publicly accessible structure that has the same size and\r
636 alignment requirements as the real queue structure.  It is provided as a\r
637 mechanism for applications to know the size of the queue (which is dependent on\r
638 the architecture and configuration file settings) without breaking the strict\r
639 data hiding policy by exposing the real queue internals.  This StaticQueue_t\r
640 variable is passed into the xQueueCreateStatic() function calls within this\r
641 function. */\r
642 static StaticQueue_t xStaticQueue;\r
643 \r
644 /* The queue storage area must be large enough to hold the maximum number of\r
645 items it is possible for the queue to hold at any one time, which equals the\r
646 queue length (in items, not bytes) multiplied by the size of each item.  In this\r
647 case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items.  See\r
648 http://www.freertos.org/Embedded-RTOS-Queues.html */\r
649 static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ];\r
650 \r
651         /* Create the queue.  xQueueCreateStatic() has two more parameters than the\r
652         usual xQueueCreate() function.  The first new paraemter is a pointer to the\r
653         pre-allocated queue storage area.  The second new parameter is a pointer to\r
654         the StaticQueue_t structure that will hold the queue state information in\r
655         an anonymous way.  If either pointer is passed as NULL then the respective\r
656         data will be allocated dynamically as if xQueueCreate() had been called. */\r
657         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
658                                                                  sizeof( uint64_t ), /* The size of each item. */\r
659                                                                  ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
660                                                                  &xStaticQueue );        /* The static queue structure that will hold the state of the queue. */\r
661 \r
662         /* The queue handle should equal the static queue structure passed into the\r
663         xQueueCreateStatic() function. */\r
664         configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
665 \r
666         /* Ensure the queue passes a few sanity checks as a valid queue. */\r
667         prvSanityCheckCreatedQueue( xQueue );\r
668 \r
669         /* Delete the queue again so the buffers can be reused. */\r
670         vQueueDelete( xQueue );\r
671 \r
672 \r
673         /* The queue created above had a statically allocated queue storage area and\r
674         queue structure.  Repeat the above with three more times - with different\r
675         combinations of static and dynamic allocation. */\r
676 \r
677         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
678                                                                  sizeof( uint64_t ), /* The size of each item. */\r
679                                                                  NULL,                           /* Allocate the buffer used to hold items within the queue dynamically. */\r
680                                                                  &xStaticQueue );        /* The static queue structure that will hold the state of the queue. */\r
681 \r
682         configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );\r
683         prvSanityCheckCreatedQueue( xQueue );\r
684         vQueueDelete( xQueue );\r
685 \r
686         /* Ensure lower priority tasks get CPU time. */\r
687         vTaskDelay( prvGetNextDelayTime() );\r
688 \r
689         /* Just to show the check task that this task is still executing. */\r
690         uxCycleCounter++;\r
691 \r
692         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
693                                                                  sizeof( uint64_t ), /* The size of each item. */\r
694                                                                  ucQueueStorageArea, /* The buffer used to hold items within the queue. */\r
695                                                                  NULL );                         /* The queue structure is allocated dynamically. */\r
696 \r
697         prvSanityCheckCreatedQueue( xQueue );\r
698         vQueueDelete( xQueue );\r
699 \r
700         xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */\r
701                                                                  sizeof( uint64_t ), /* The size of each item. */\r
702                                                                  NULL,                           /* Allocate the buffer used to hold items within the queue dynamically. */\r
703                                                                  NULL );                         /* The queue structure is allocated dynamically. */\r
704 \r
705         prvSanityCheckCreatedQueue( xQueue );\r
706         vQueueDelete( xQueue );\r
707 \r
708         /* Ensure lower priority tasks get CPU time. */\r
709         vTaskDelay( prvGetNextDelayTime() );\r
710 \r
711         /* Just to show the check task that this task is still executing. */\r
712         uxCycleCounter++;\r
713 }\r
714 /*-----------------------------------------------------------*/\r
715 \r
716 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void )\r
717 {\r
718 SemaphoreHandle_t xSemaphore;\r
719 BaseType_t xReturned;\r
720 \r
721 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
722 and alignment requirements as the real semaphore structure.  It is provided as a\r
723 mechanism for applications to know the size of the semaphore (which is dependent\r
724 on the architecture and configuration file settings) without breaking the strict\r
725 data hiding policy by exposing the real semaphore internals.  This\r
726 StaticSemaphore_t variable is passed into the xSemaphoreCreateMutexStatic()\r
727 function calls within this function. */\r
728 StaticSemaphore_t xSemaphoreBuffer;\r
729 \r
730         /* Create the semaphore.  xSemaphoreCreateMutexStatic() has one more\r
731         parameter than the usual xSemaphoreCreateMutex() function.  The paraemter\r
732         is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
733         hold information on the semaphore in an anonymous way.  If the pointer is\r
734         passed as NULL then the structure will be allocated dynamically, just as\r
735         when xSemaphoreCreateMutex() is called. */\r
736         xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );\r
737 \r
738         /* The semaphore handle should equal the static semaphore structure passed\r
739         into the xSemaphoreCreateMutexStatic() function. */\r
740         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
741 \r
742         /* Take the mutex so the mutex is in the state expected by the\r
743         prvSanityCheckCreatedSemaphore() function. */\r
744         xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
745 \r
746         if( xReturned != pdPASS )\r
747         {\r
748                 xErrorOccurred = pdTRUE;\r
749         }\r
750 \r
751         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
752         prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
753 \r
754         /* Delete the semaphore again so the buffers can be reused. */\r
755         vSemaphoreDelete( xSemaphore );\r
756 \r
757 \r
758         /* The semaphore created above had a statically allocated semaphore\r
759         structure.  Repeat the above using NULL as the xSemaphoreCreateMutexStatic()\r
760         parameter so the semaphore structure is instead allocated dynamically. */\r
761         xSemaphore = xSemaphoreCreateMutexStatic( NULL );\r
762 \r
763         /* Take the mutex so the mutex is in the state expected by the\r
764         prvSanityCheckCreatedSemaphore() function. */\r
765         xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );\r
766 \r
767         if( xReturned != pdPASS )\r
768         {\r
769                 xErrorOccurred = pdTRUE;\r
770         }\r
771 \r
772         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
773         prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
774 \r
775         /* Delete the semaphore again so the buffers can be reused. */\r
776         vSemaphoreDelete( xSemaphore );\r
777 \r
778         /* Ensure lower priority tasks get CPU time. */\r
779         vTaskDelay( prvGetNextDelayTime() );\r
780 \r
781         /* Just to show the check task that this task is still executing. */\r
782         uxCycleCounter++;\r
783 }\r
784 /*-----------------------------------------------------------*/\r
785 \r
786 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )\r
787 {\r
788 SemaphoreHandle_t xSemaphore;\r
789 \r
790 /* StaticSemaphore_t is a publicly accessible structure that has the same size\r
791 and alignment requirements as the real semaphore structure.  It is provided as a\r
792 mechanism for applications to know the size of the semaphore (which is dependent\r
793 on the architecture and configuration file settings) without breaking the strict\r
794 data hiding policy by exposing the real semaphore internals.  This\r
795 StaticSemaphore_t variable is passed into the xSemaphoreCreateBinaryStatic()\r
796 function calls within this function.  NOTE: In most usage scenarios now it is\r
797 faster and more memory efficient to use a direct to task notification instead of\r
798 a binary semaphore.  http://www.freertos.org/RTOS-task-notifications.html */\r
799 StaticSemaphore_t xSemaphoreBuffer;\r
800 \r
801         /* Create the semaphore.  xSemaphoreCreateBinaryStatic() has one more\r
802         parameter than the usual xSemaphoreCreateBinary() function.  The paraemter\r
803         is a pointer to the pre-allocated StaticSemaphore_t structure, which will\r
804         hold information on the semaphore in an anonymous way.  If the pointer is\r
805         passed as NULL then the structure will be allocated dynamically, just as\r
806         when xSemaphoreCreateBinary() is called. */\r
807         xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );\r
808 \r
809         /* The semaphore handle should equal the static semaphore structure passed\r
810         into the xSemaphoreCreateBinaryStatic() function. */\r
811         configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );\r
812 \r
813         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
814         prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
815 \r
816         /* Delete the semaphore again so the buffers can be reused. */\r
817         vSemaphoreDelete( xSemaphore );\r
818 \r
819 \r
820         /* The semaphore created above had a statically allocated semaphore\r
821         structure.  Repeat the above using NULL as the xSemaphoreCreateBinaryStatic()\r
822         parameter so the semaphore structure is instead allocated dynamically. */\r
823         xSemaphore = xSemaphoreCreateBinaryStatic( NULL );\r
824 \r
825         /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */\r
826         prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
827 \r
828         /* Delete the semaphore again so the buffers can be reused. */\r
829         vSemaphoreDelete( xSemaphore );\r
830 \r
831 \r
832 \r
833         /* There isn't a static version of the old and deprecated\r
834         vSemaphoreCreateBinary() macro (because its deprecated!), but check it is\r
835         still functioning correctly when configSUPPORT_STATIC_ALLOCATION is set to\r
836         1. */\r
837         vSemaphoreCreateBinary( xSemaphore );\r
838 \r
839         /* The macro starts with the binary semaphore available, but the test\r
840         function expects it to be unavailable. */\r
841         if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL )\r
842         {\r
843                 xErrorOccurred = pdTRUE;\r
844         }\r
845 \r
846         prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );\r
847         vSemaphoreDelete( xSemaphore );\r
848 \r
849         /* Ensure lower priority tasks get CPU time. */\r
850         vTaskDelay( prvGetNextDelayTime() );\r
851 \r
852         /* Just to show the check task that this task is still executing. */\r
853         uxCycleCounter++;\r
854 }\r
855 /*-----------------------------------------------------------*/\r
856 \r
857 static void prvTimerCallback( TimerHandle_t xExpiredTimer )\r
858 {\r
859 UBaseType_t *puxVariableToIncrement;\r
860 BaseType_t xReturned;\r
861 \r
862         /* Obtain the address of the variable to increment from the timer ID. */\r
863         puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );\r
864 \r
865         /* Increment the variable to show the timer callback has executed. */\r
866         ( *puxVariableToIncrement )++;\r
867 \r
868         /* If this callback has executed the required number of times, stop the\r
869         timer. */\r
870         if( *puxVariableToIncrement == staticMAX_TIMER_CALLBACK_EXECUTIONS )\r
871         {\r
872                 /* This is called from a timer callback so must not block. */\r
873                 xReturned = xTimerStop( xExpiredTimer, staticDONT_BLOCK );\r
874 \r
875                 if( xReturned != pdPASS )\r
876                 {\r
877                         xErrorOccurred = pdTRUE;\r
878                 }\r
879         }\r
880 }\r
881 /*-----------------------------------------------------------*/\r
882 \r
883 static void prvCreateAndDeleteStaticallyAllocatedTimers( void )\r
884 {\r
885 TimerHandle_t xTimer;\r
886 UBaseType_t uxVariableToIncrement;\r
887 const TickType_t xTimerPeriod = pdMS_TO_TICKS( 20 );\r
888 BaseType_t xReturned;\r
889 \r
890 /* StaticTimer_t is a publicly accessible structure that has the same size\r
891 and alignment requirements as the real timer structure.  It is provided as a\r
892 mechanism for applications to know the size of the timer structure (which is\r
893 dependent on the architecture and configuration file settings) without breaking\r
894 the strict data hiding policy by exposing the real timer internals.  This\r
895 StaticTimer_t variable is passed into the xTimerCreateStatic() function calls\r
896 within this function. */\r
897 StaticTimer_t xTimerBuffer;\r
898 \r
899         /* Create the software time.  xTimerCreateStatic() has an extra parameter\r
900         than the normal xTimerCreate() API function.  The parameter is a pointer to\r
901         the StaticTimer_t structure that will hold the software timer structure.  If\r
902         the parameter is passed as NULL then the structure will be allocated\r
903         dynamically, just as if xTimerCreate() had been called. */\r
904         xTimer = xTimerCreateStatic( "T1",                                      /* Text name for the task.  Helps debugging only.  Not used by FreeRTOS. */\r
905                                                                  xTimerPeriod,                  /* The period of the timer in ticks. */\r
906                                                                  pdTRUE,                                /* This is an auto-reload timer. */\r
907                                                                  ( void * ) &uxVariableToIncrement,     /* The variable incremented by the test is passed into the timer callback using the timer ID. */\r
908                                                                  prvTimerCallback,              /* The function to execute when the timer expires. */\r
909                                                                  &xTimerBuffer );               /* The buffer that will hold the software timer structure. */\r
910 \r
911         /* The timer handle should equal the static timer structure passed into the\r
912         xTimerCreateStatic() function. */\r
913         configASSERT( xTimer == ( TimerHandle_t ) &xTimerBuffer );\r
914 \r
915         /* Set the variable to 0, wait for a few timer periods to expire, then check\r
916         the timer callback has incremented the variable to the expected value. */\r
917         uxVariableToIncrement = 0;\r
918 \r
919         /* This is a low priority so a block time should not be needed. */\r
920         xReturned = xTimerStart( xTimer, staticDONT_BLOCK );\r
921 \r
922         if( xReturned != pdPASS )\r
923         {\r
924                 xErrorOccurred = pdTRUE;\r
925         }\r
926 \r
927         vTaskDelay( xTimerPeriod * staticMAX_TIMER_CALLBACK_EXECUTIONS );\r
928 \r
929         /* By now the timer should have expired staticMAX_TIMER_CALLBACK_EXECUTIONS\r
930         times, and then stopped itself. */\r
931         if( uxVariableToIncrement != staticMAX_TIMER_CALLBACK_EXECUTIONS )\r
932         {\r
933                 xErrorOccurred = pdTRUE;\r
934         }\r
935 \r
936         /* Finished with the timer, delete it. */\r
937         xReturned = xTimerDelete( xTimer, staticDONT_BLOCK );\r
938 \r
939         /* Again, as this is a low priority task it is expected that the timer\r
940         command will have been sent even without a block time being used. */\r
941         if( xReturned != pdPASS )\r
942         {\r
943                 xErrorOccurred = pdTRUE;\r
944         }\r
945 \r
946         /* Just to show the check task that this task is still executing. */\r
947         uxCycleCounter++;\r
948 \r
949         /* The software timer created above had a statically allocated timer\r
950         structure.  Repeat the above using NULL as the xTimerCreateStatic()\r
951         parameter so the timer structure is instead allocated dynamically. */\r
952         xTimer = xTimerCreateStatic( "T1",                                      /* Text name for the task.  Helps debugging only.  Not used by FreeRTOS. */\r
953                                                                  xTimerPeriod,                  /* The period of the timer in ticks. */\r
954                                                                  pdTRUE,                                /* This is an auto-reload timer. */\r
955                                                                  ( void * ) &uxVariableToIncrement,     /* The variable incremented by the test is passed into the timer callback using the timer ID. */\r
956                                                                  prvTimerCallback,              /* The function to execute when the timer expires. */\r
957                                                                  NULL );                                /* A buffer is not passed this time, so the timer should be allocated dynamically. */\r
958         uxVariableToIncrement = 0;\r
959         xReturned = xTimerStart( xTimer, staticDONT_BLOCK );\r
960 \r
961         if( xReturned != pdPASS )\r
962         {\r
963                 xErrorOccurred = pdTRUE;\r
964         }\r
965 \r
966         vTaskDelay( xTimerPeriod * staticMAX_TIMER_CALLBACK_EXECUTIONS );\r
967 \r
968         /* Just to show the check task that this task is still executing. */\r
969         uxCycleCounter++;\r
970 \r
971         if( uxVariableToIncrement != staticMAX_TIMER_CALLBACK_EXECUTIONS )\r
972         {\r
973                 xErrorOccurred = pdTRUE;\r
974         }\r
975 \r
976         xReturned = xTimerDelete( xTimer, staticDONT_BLOCK );\r
977 \r
978         if( xReturned != pdPASS )\r
979         {\r
980                 xErrorOccurred = pdTRUE;\r
981         }\r
982 \r
983         /* Just to show the check task that this task is still executing. */\r
984         uxCycleCounter++;\r
985 }\r
986 /*-----------------------------------------------------------*/\r
987 \r
988 static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void )\r
989 {\r
990 EventGroupHandle_t xEventGroup;\r
991 \r
992 /* StaticEventGroup_t is a publicly accessible structure that has the same size\r
993 and alignment requirements as the real event group structure.  It is provided as\r
994 a mechanism for applications to know the size of the event group (which is\r
995 dependent on the architecture and configuration file settings) without breaking\r
996 the strict data hiding policy by exposing the real event group internals.  This\r
997 StaticEventGroup_t variable is passed into the xSemaphoreCreateEventGroupStatic()\r
998 function calls within this function. */\r
999 StaticEventGroup_t xEventGroupBuffer;\r
1000 \r
1001         /* Create the event group.  xEventGroupCreateStatic() has an extra parameter\r
1002         than the normal xEventGroupCreate() API function.  The parameter is a\r
1003         pointer to the StaticEventGroup_t structure that will hold the event group\r
1004         structure.  If the parameter is passed as NULL then the structure will be\r
1005         allocated dynamically, just as if xEventGroupCreate() had been called. */\r
1006         xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );\r
1007 \r
1008         /* The event group handle should equal the static event group structure\r
1009         passed into the xEventGroupCreateStatic() function. */\r
1010         configASSERT( xEventGroup == ( EventGroupHandle_t ) &xEventGroupBuffer );\r
1011 \r
1012         /* Ensure the event group passes a few sanity checks as a valid event\r
1013         group. */\r
1014         prvSanityCheckCreatedEventGroup( xEventGroup );\r
1015 \r
1016         /* Delete the event group again so the buffers can be reused. */\r
1017         vEventGroupDelete( xEventGroup );\r
1018 \r
1019 \r
1020         /* The event group created above had a statically allocated event group\r
1021         structure.  Repeat the above using NULL as the xEventGroupCreateStatic()\r
1022         parameter so the event group structure is instead allocated dynamically. */\r
1023         xEventGroup = xEventGroupCreateStatic( NULL );\r
1024 \r
1025         /* Ensure the event group passes a few sanity checks as a valid event\r
1026         group. */\r
1027         prvSanityCheckCreatedEventGroup( xEventGroup );\r
1028 \r
1029         /* Delete the event group again so the buffers can be reused. */\r
1030         vEventGroupDelete( xEventGroup );\r
1031 \r
1032         /* Ensure lower priority tasks get CPU time. */\r
1033         vTaskDelay( prvGetNextDelayTime() );\r
1034 \r
1035         /* Just to show the check task that this task is still executing. */\r
1036         uxCycleCounter++;\r
1037 }\r
1038 /*-----------------------------------------------------------*/\r
1039 \r
1040 static void prvCreateAndDeleteStaticallyAllocatedTasks( void )\r
1041 {\r
1042 TaskHandle_t xCreatedTask;\r
1043 BaseType_t xReturned;\r
1044 \r
1045 /* The variable that will hold the TCB of tasks created by this function.  See\r
1046 the comments above the declaration of the xCreatorTaskTCBBuffer variable for\r
1047 more information. */\r
1048 StaticTask_t xTCBBuffer;\r
1049 \r
1050 /* This buffer that will be used as the stack of tasks created by this function.\r
1051 See the comments above the declaration of the uxCreatorTaskStackBuffer[] array\r
1052 above for more information. */\r
1053 static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];\r
1054 \r
1055         /* Create the task.  xTaskCreateStatic() has two more parameters than\r
1056         the usual xTaskCreate() function.  The first new parameter is a pointer to\r
1057         the pre-allocated stack.  The second new parameter is a pointer to the\r
1058         StaticTask_t structure that will hold the task's TCB.  If either pointer is\r
1059         passed as NULL then the respective object will be allocated dynamically as\r
1060         if xTaskCreate() had been called. */\r
1061         xReturned = xTaskCreateStatic(\r
1062                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
1063                                                 "Static",                                       /* Human readable name for the task. */\r
1064                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
1065                                                 NULL,                                           /* Parameter to pass into the task. */\r
1066                                                 tskIDLE_PRIORITY,                       /* The priority of the task. */\r
1067                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
1068                                                 &( uxStackBuffer[ 0 ] ),        /* The buffer to use as the task's stack. */\r
1069                                                 &xTCBBuffer );                          /* The variable that will hold that task's TCB. */\r
1070 \r
1071         /* Check the task was created correctly, then delete the task. */\r
1072         configASSERT( xReturned == pdPASS );\r
1073         if( xReturned != pdPASS )\r
1074         {\r
1075                 xErrorOccurred = pdTRUE;\r
1076         }\r
1077         vTaskDelete( xCreatedTask );\r
1078 \r
1079         /* Ensure lower priority tasks get CPU time. */\r
1080         vTaskDelay( prvGetNextDelayTime() );\r
1081 \r
1082         /* Create and delete the task a few times again - testing both static and\r
1083         dynamic allocation for the stack and TCB. */\r
1084         xReturned = xTaskCreateStatic(\r
1085                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
1086                                                 "Static",                                       /* Human readable name for the task. */\r
1087                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
1088                                                 NULL,                                           /* Parameter to pass into the task. */\r
1089                                                 staticTASK_PRIORITY + 1,        /* The priority of the task. */\r
1090                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
1091                                                 NULL,                                           /* This time, dynamically allocate the stack. */\r
1092                                                 &xTCBBuffer );                          /* The variable that will hold that task's TCB. */\r
1093 \r
1094         configASSERT( xReturned == pdPASS );\r
1095         if( xReturned != pdPASS )\r
1096         {\r
1097                 xErrorOccurred = pdTRUE;\r
1098         }\r
1099         vTaskDelete( xCreatedTask );\r
1100 \r
1101         /* Just to show the check task that this task is still executing. */\r
1102         uxCycleCounter++;\r
1103 \r
1104         /* Ensure lower priority tasks get CPU time. */\r
1105         vTaskDelay( prvGetNextDelayTime() );\r
1106 \r
1107         xReturned = xTaskCreateStatic(\r
1108                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
1109                                                 "Static",                                       /* Human readable name for the task. */\r
1110                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
1111                                                 NULL,                                           /* Parameter to pass into the task. */\r
1112                                                 staticTASK_PRIORITY - 1,        /* The priority of the task. */\r
1113                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
1114                                                 &( uxStackBuffer[ 0 ] ),        /* The buffer to use as the task's stack. */\r
1115                                                 NULL );                                         /* This time dynamically allocate the TCB. */\r
1116 \r
1117         configASSERT( xReturned == pdPASS );\r
1118         if( xReturned != pdPASS )\r
1119         {\r
1120                 xErrorOccurred = pdTRUE;\r
1121         }\r
1122         vTaskDelete( xCreatedTask );\r
1123 \r
1124         /* Ensure lower priority tasks get CPU time. */\r
1125         vTaskDelay( prvGetNextDelayTime() );\r
1126 \r
1127         xReturned = xTaskCreateStatic(\r
1128                                                 prvStaticallyAllocatedTask, /* Function that implements the task. */\r
1129                                                 "Static",                                       /* Human readable name for the task. */\r
1130                                                 configMINIMAL_STACK_SIZE,       /* Task's stack size, in words (not bytes!). */\r
1131                                                 NULL,                                           /* Parameter to pass into the task. */\r
1132                                                 staticTASK_PRIORITY,            /* The priority of the task. */\r
1133                                                 &xCreatedTask,                          /* Handle of the task being created. */\r
1134                                                 NULL,                                           /* This time dynamically allocate the stack and TCB. */\r
1135                                                 NULL );                                         /* This time dynamically allocate the stack and TCB. */\r
1136 \r
1137         configASSERT( xReturned == pdPASS );\r
1138         if( xReturned != pdPASS )\r
1139         {\r
1140                 xErrorOccurred = pdTRUE;\r
1141         }\r
1142         vTaskDelete( xCreatedTask );\r
1143 \r
1144         /* Ensure lower priority tasks get CPU time. */\r
1145         vTaskDelay( prvGetNextDelayTime() );\r
1146 \r
1147         /* Just to show the check task that this task is still executing. */\r
1148         uxCycleCounter++;\r
1149 }\r
1150 /*-----------------------------------------------------------*/\r
1151 \r
1152 static void prvStaticallyAllocatedTask( void *pvParameters )\r
1153 {\r
1154         ( void ) pvParameters;\r
1155 \r
1156         /* The created task doesn't do anything - just waits to get deleted. */\r
1157         vTaskSuspend( NULL );\r
1158 }\r
1159 /*-----------------------------------------------------------*/\r
1160 \r
1161 static UBaseType_t prvRand( void )\r
1162 {\r
1163 const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;\r
1164 \r
1165         /* Utility function to generate a pseudo random number. */\r
1166         ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;\r
1167         return( ( ulNextRand >> 16UL ) & 0x7fffUL );\r
1168 }\r
1169 /*-----------------------------------------------------------*/\r
1170 \r
1171 static TickType_t prvGetNextDelayTime( void )\r
1172 {\r
1173 TickType_t xNextDelay;\r
1174 const TickType_t xMaxDelay = pdMS_TO_TICKS( ( TickType_t ) 150 );\r
1175 const TickType_t xMinDelay = pdMS_TO_TICKS( ( TickType_t ) 75 );\r
1176 const TickType_t xTinyDelay = pdMS_TO_TICKS( ( TickType_t ) 2 );\r
1177 \r
1178         /* Generate the next delay time.  This is kept within a narrow band so as\r
1179         not to disturb the timing of other tests - but does add in some pseudo\r
1180         randomisation into the tests. */\r
1181         do\r
1182         {\r
1183                 xNextDelay = prvRand() % xMaxDelay;\r
1184 \r
1185                 /* Just in case this loop is executed lots of times. */\r
1186                 vTaskDelay( xTinyDelay );\r
1187 \r
1188         } while ( xNextDelay < xMinDelay );\r
1189 \r
1190         return xNextDelay;\r
1191 }\r
1192 /*-----------------------------------------------------------*/\r
1193 \r
1194 BaseType_t xAreStaticAllocationTasksStillRunning( void )\r
1195 {\r
1196 static UBaseType_t uxLastCycleCounter = 0;\r
1197 BaseType_t xReturn;\r
1198 \r
1199         if( uxCycleCounter == uxLastCycleCounter )\r
1200         {\r
1201                 xErrorOccurred = pdTRUE;\r
1202         }\r
1203         else\r
1204         {\r
1205                 uxLastCycleCounter = uxCycleCounter;\r
1206         }\r
1207 \r
1208         if( xErrorOccurred != pdFALSE )\r
1209         {\r
1210                 xReturn = pdFAIL;\r
1211         }\r
1212         else\r
1213         {\r
1214                 xReturn = pdPASS;\r
1215         }\r
1216 \r
1217         return xReturn;\r
1218 }\r
1219 /*-----------------------------------------------------------*/\r
1220 \r
1221 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */\r
1222 #endif /* configSUPPORT_STATIC_ALLOCATION == 1 */\r