2 FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 This file is part of the FreeRTOS distribution.
\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
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
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
25 ***************************************************************************
\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
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
37 ***************************************************************************
\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
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
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
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
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
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
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
72 * Demonstrates how to create FreeRTOS objects using pre-allocated memory,
\r
73 * rather than the normal dynamically allocated memory.
\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
82 /* Scheduler include files. */
\r
83 #include "FreeRTOS.h"
\r
88 /* Demo program include files. */
\r
89 #include "StaticAllocation.h"
\r
91 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */
\r
92 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
94 /* The priority at which the task that performs the tests is created. */
\r
95 #define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
\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
101 /* A block time of 0 simply means "don't block". */
\r
102 #define staticDONT_BLOCK ( ( TickType_t ) 0 )
\r
104 /* Binary semaphores have a maximum count of 1. */
\r
105 #define staticBINARY_SEMAPHORE_MAX_COUNT ( 1 )
\r
108 /*-----------------------------------------------------------*/
\r
111 * A task that is created and deleted multiple times, using both statically and
\r
112 * dynamically allocated stack and TCB.
\r
114 static void prvStaticallyAllocatedTask( void *pvParameters );
\r
117 * The task that repeatedly creates and deletes statically allocated tasks, and
\r
118 * other RTOS objects.
\r
120 static void prvStaticallyAllocatedCreator( void *pvParameters );
\r
123 * Utility function to create pseudo random numbers.
\r
125 static UBaseType_t prvRand( void );
\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
132 static void prvCreateAndDeleteStaticallyAllocatedTasks( void );
\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
139 static void prvCreateAndDeleteStaticallyAllocatedQueues( void );
\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
146 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );
\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
153 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void );
\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
160 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void );
\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
168 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );
\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
176 static TickType_t prvGetNextDelayTime( void );
\r
179 * Checks the basic operation of a queue after it has been created.
\r
181 static void prvCheckQueueFunction( QueueHandle_t xQueue );
\r
184 * Checks the basic operation of a recursive mutex after it has been created.
\r
186 static void prvCheckRecursiveSemaphoreFunction( SemaphoreHandle_t xSemaphore );
\r
189 * Checks the basic operation of a binary semaphore after it has been created.
\r
191 static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount );
\r
193 /*-----------------------------------------------------------*/
\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
203 static StaticTCB_t xCreatorTaskTCBBuffer;
\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
210 /* Used by the pseudo random number generating function. */
\r
211 static uint32_t ulNextRand = 0;
\r
213 /* Used so a check task can ensure this test is still executing, and not
\r
215 static volatile UBaseType_t uxCycleCounter = 0;
\r
217 /* A variable that gets set to pdTRUE if an error is detected. */
\r
218 static BaseType_t xErrorOccurred = pdFALSE;
\r
220 /*-----------------------------------------------------------*/
\r
222 void vStartStaticallyAllocatedTasks( void )
\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
236 /* Pseudo seed the random number generator. */
\r
237 ulNextRand = ( uint32_t ) prvRand;
\r
239 /*-----------------------------------------------------------*/
\r
241 static void prvStaticallyAllocatedCreator( void *pvParameters )
\r
243 /* Avoid compiler warnings. */
\r
244 ( void ) pvParameters;
\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
251 prvCreateAndDeleteStaticallyAllocatedTasks();
\r
252 prvCreateAndDeleteStaticallyAllocatedQueues();
\r
253 prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();
\r
254 prvCreateAndDeleteStaticallyAllocatedCountingSemaphores();
\r
255 prvCreateAndDeleteStaticallyAllocatedMutexes();
\r
256 prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes();
\r
259 /*-----------------------------------------------------------*/
\r
261 static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )
\r
263 BaseType_t xReturned;
\r
265 const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );
\r
266 TickType_t xTickCount;
\r
268 /* The binary semaphore should start 'empty', so a call to xSemaphoreTake()
\r
270 xTickCount = xTaskGetTickCount();
\r
271 xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
\r
273 if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )
\r
275 /* Did not block on the semaphore as long as expected. */
\r
276 xErrorOccurred = pdTRUE;
\r
279 if( xReturned != pdFAIL )
\r
281 xErrorOccurred = pdTRUE;
\r
284 /* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount
\r
286 for( x = 0; x < uxMaxCount; x++ )
\r
288 xReturned = xSemaphoreGive( xSemaphore );
\r
290 if( xReturned == pdFAIL )
\r
292 xErrorOccurred = pdTRUE;
\r
296 /* Giving the semaphore again should fail, as it is 'full'. */
\r
297 xReturned = xSemaphoreGive( xSemaphore );
\r
299 if( xReturned != pdFAIL )
\r
301 xErrorOccurred = pdTRUE;
\r
304 configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );
\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
310 xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
\r
312 if( xReturned == pdFAIL )
\r
314 xErrorOccurred = pdTRUE;
\r
318 /* Back to the starting condition, where the semaphore should not be
\r
320 xTickCount = xTaskGetTickCount();
\r
321 xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
\r
323 if( ( xTaskGetTickCount() - xTickCount) < xShortBlockTime )
\r
325 /* Did not block on the semaphore as long as expected. */
\r
326 xErrorOccurred = pdTRUE;
\r
329 if( xReturned != pdFAIL )
\r
331 xErrorOccurred = pdTRUE;
\r
334 configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );
\r
336 /*-----------------------------------------------------------*/
\r
338 static void prvCheckQueueFunction( QueueHandle_t xQueue )
\r
340 uint64_t ull, ullRead;
\r
341 BaseType_t xReturned, xLoop;
\r
343 /* This test is done twice to ensure the queue storage area wraps. */
\r
344 for( xLoop = 0; xLoop < 2; xLoop++ )
\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
351 xErrorOccurred = pdTRUE;
\r
354 /* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS
\r
356 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
\r
358 xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
\r
359 if( xReturned != pdPASS )
\r
361 xErrorOccurred = pdTRUE;
\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
369 xErrorOccurred = pdTRUE;
\r
372 /* Now read back from the queue to ensure the data read back matches that
\r
374 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
\r
376 xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );
\r
378 if( xReturned != pdPASS )
\r
380 xErrorOccurred = pdTRUE;
\r
383 if( ullRead != ull )
\r
385 xErrorOccurred = pdTRUE;
\r
389 /* The queue should be empty again. */
\r
390 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
\r
391 if( xReturned != errQUEUE_EMPTY )
\r
393 xErrorOccurred = pdTRUE;
\r
397 /*-----------------------------------------------------------*/
\r
399 static void prvCheckRecursiveSemaphoreFunction( SemaphoreHandle_t xSemaphore )
\r
401 const BaseType_t xLoops = 5;
\r
402 BaseType_t x, xReturned;
\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
407 xReturned = xSemaphoreGiveRecursive( xSemaphore );
\r
409 if( xReturned != pdFAIL )
\r
411 xErrorOccurred = pdTRUE;
\r
414 /* Now it should be possible to take the mutex a number of times. */
\r
415 for( x = 0; x < xLoops; x++ )
\r
417 xReturned = xSemaphoreTakeRecursive( xSemaphore, staticDONT_BLOCK );
\r
419 if( xReturned != pdPASS )
\r
421 xErrorOccurred = pdTRUE;
\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
429 xReturned = xSemaphoreGiveRecursive( xSemaphore );
\r
431 if( xReturned != pdPASS )
\r
433 xErrorOccurred = pdTRUE;
\r
437 /* No more gives should be possible though. */
\r
438 xReturned = xSemaphoreGiveRecursive( xSemaphore );
\r
440 if( xReturned != pdFAIL )
\r
442 xErrorOccurred = pdTRUE;
\r
445 /*-----------------------------------------------------------*/
\r
447 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void )
\r
449 SemaphoreHandle_t xSemaphore;
\r
450 const UBaseType_t uxMaxCount = ( UBaseType_t ) 10;
\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
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
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
475 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
476 prvCheckSemaphoreFunction( xSemaphore, uxMaxCount );
\r
478 /* Delete the semaphore again so the buffers can be reused. */
\r
479 vSemaphoreDelete( xSemaphore );
\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
488 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
489 prvCheckSemaphoreFunction( xSemaphore, uxMaxCount );
\r
491 /* Delete the semaphore again so the buffers can be reused. */
\r
492 vSemaphoreDelete( xSemaphore );
\r
494 /* Ensure lower priority tasks get CPU time. */
\r
495 vTaskDelay( prvGetNextDelayTime() );
\r
497 /* Just to show the check task that this task is still executing. */
\r
500 /*-----------------------------------------------------------*/
\r
502 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void )
\r
504 SemaphoreHandle_t xSemaphore;
\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
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
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
527 /* Ensure the semaphore passes a few sanity checks as a valid
\r
528 recursive semaphore. */
\r
529 prvCheckRecursiveSemaphoreFunction( xSemaphore );
\r
531 /* Delete the semaphore again so the buffers can be reused. */
\r
532 vSemaphoreDelete( xSemaphore );
\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
541 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
542 prvCheckRecursiveSemaphoreFunction( xSemaphore );
\r
544 /* Delete the semaphore again so the buffers can be reused. */
\r
545 vSemaphoreDelete( xSemaphore );
\r
547 /* Ensure lower priority tasks get CPU time. */
\r
548 vTaskDelay( prvGetNextDelayTime() );
\r
550 /* Just to show the check task that this task is still executing. */
\r
553 /*-----------------------------------------------------------*/
\r
555 static void prvCreateAndDeleteStaticallyAllocatedQueues( void )
\r
557 QueueHandle_t xQueue;
\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
566 static StaticQueue_t xStaticQueue;
\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
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
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
590 /* Ensure the queue passes a few sanity checks as a valid queue. */
\r
591 prvCheckQueueFunction( xQueue );
\r
593 /* Delete the queue again so the buffers can be reused. */
\r
594 vQueueDelete( xQueue );
\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
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
606 configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );
\r
607 prvCheckQueueFunction( xQueue );
\r
608 vQueueDelete( xQueue );
\r
610 /* Ensure lower priority tasks get CPU time. */
\r
611 vTaskDelay( prvGetNextDelayTime() );
\r
613 /* Just to show the check task that this task is still executing. */
\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
621 prvCheckQueueFunction( xQueue );
\r
622 vQueueDelete( xQueue );
\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
629 prvCheckQueueFunction( xQueue );
\r
630 vQueueDelete( xQueue );
\r
632 /* Ensure lower priority tasks get CPU time. */
\r
633 vTaskDelay( prvGetNextDelayTime() );
\r
635 /* Just to show the check task that this task is still executing. */
\r
638 /*-----------------------------------------------------------*/
\r
640 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void )
\r
642 SemaphoreHandle_t xSemaphore;
\r
643 BaseType_t xReturned;
\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
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
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
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
670 if( xReturned != pdPASS )
\r
672 xErrorOccurred = pdTRUE;
\r
675 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
676 prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
678 /* Delete the semaphore again so the buffers can be reused. */
\r
679 vSemaphoreDelete( xSemaphore );
\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
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
691 if( xReturned != pdPASS )
\r
693 xErrorOccurred = pdTRUE;
\r
696 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
697 prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
699 /* Delete the semaphore again so the buffers can be reused. */
\r
700 vSemaphoreDelete( xSemaphore );
\r
702 /* Ensure lower priority tasks get CPU time. */
\r
703 vTaskDelay( prvGetNextDelayTime() );
\r
705 /* Just to show the check task that this task is still executing. */
\r
708 /*-----------------------------------------------------------*/
\r
710 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )
\r
712 SemaphoreHandle_t xSemaphore;
\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
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
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
737 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
738 prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
740 /* Delete the semaphore again so the buffers can be reused. */
\r
741 vSemaphoreDelete( xSemaphore );
\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
749 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
750 prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
752 /* Delete the semaphore again so the buffers can be reused. */
\r
753 vSemaphoreDelete( xSemaphore );
\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
761 vSemaphoreCreateBinary( xSemaphore );
\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
767 xErrorOccurred = pdTRUE;
\r
770 prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
771 vSemaphoreDelete( xSemaphore );
\r
773 /* Ensure lower priority tasks get CPU time. */
\r
774 vTaskDelay( prvGetNextDelayTime() );
\r
776 /* Just to show the check task that this task is still executing. */
\r
779 /*-----------------------------------------------------------*/
\r
781 static void prvCreateAndDeleteStaticallyAllocatedTasks( void )
\r
783 TaskHandle_t xCreatedTask;
\r
784 BaseType_t xReturned;
\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
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
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
812 /* Check the task was created correctly, then delete the task. */
\r
813 configASSERT( xReturned == pdPASS );
\r
814 if( xReturned != pdPASS )
\r
816 xErrorOccurred = pdTRUE;
\r
818 vTaskDelete( xCreatedTask );
\r
820 /* Ensure lower priority tasks get CPU time. */
\r
821 vTaskDelay( prvGetNextDelayTime() );
\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
835 configASSERT( xReturned == pdPASS );
\r
836 if( xReturned != pdPASS )
\r
838 xErrorOccurred = pdTRUE;
\r
840 vTaskDelete( xCreatedTask );
\r
842 /* Just to show the check task that this task is still executing. */
\r
845 /* Ensure lower priority tasks get CPU time. */
\r
846 vTaskDelay( prvGetNextDelayTime() );
\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
858 configASSERT( xReturned == pdPASS );
\r
859 if( xReturned != pdPASS )
\r
861 xErrorOccurred = pdTRUE;
\r
863 vTaskDelete( xCreatedTask );
\r
865 /* Ensure lower priority tasks get CPU time. */
\r
866 vTaskDelay( prvGetNextDelayTime() );
\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
878 configASSERT( xReturned == pdPASS );
\r
879 if( xReturned != pdPASS )
\r
881 xErrorOccurred = pdTRUE;
\r
883 vTaskDelete( xCreatedTask );
\r
885 /* Ensure lower priority tasks get CPU time. */
\r
886 vTaskDelay( prvGetNextDelayTime() );
\r
888 /* Just to show the check task that this task is still executing. */
\r
891 /*-----------------------------------------------------------*/
\r
893 static void prvStaticallyAllocatedTask( void *pvParameters )
\r
895 ( void ) pvParameters;
\r
897 /* The created task doesn't do anything - just waits to get deleted. */
\r
898 vTaskSuspend( NULL );
\r
900 /*-----------------------------------------------------------*/
\r
902 static UBaseType_t prvRand( void )
\r
904 const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
\r
906 /* Utility function to generate a pseudo random number. */
\r
907 ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
\r
908 return( ( ulNextRand >> 16UL ) & 0x7fffUL );
\r
910 /*-----------------------------------------------------------*/
\r
912 static TickType_t prvGetNextDelayTime( void )
\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
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
924 xNextDelay = prvRand() % xMaxDelay;
\r
926 /* Just in case this loop is executed lots of times. */
\r
927 vTaskDelay( xTinyDelay );
\r
929 } while ( xNextDelay < xMinDelay );
\r
933 /*-----------------------------------------------------------*/
\r
935 BaseType_t xAreStaticAllocationTasksStillRunning( void )
\r
937 static UBaseType_t uxLastCycleCounter = 0;
\r
938 BaseType_t xReturn;
\r
940 if( uxCycleCounter == uxLastCycleCounter )
\r
942 xErrorOccurred = pdTRUE;
\r
946 uxLastCycleCounter = uxCycleCounter;
\r
949 if( xErrorOccurred != pdFALSE )
\r
960 /*-----------------------------------------------------------*/
\r
962 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */
\r
963 #endif /* configSUPPORT_STATIC_ALLOCATION == 1 */
\r