2 FreeRTOS V9.0.0rc1 - Copyright (C) 2016 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, and tests objects being
\r
74 * created and deleted with both statically allocated memory and dynamically
\r
78 /* Scheduler include files. */
\r
79 #include "FreeRTOS.h"
\r
83 #include "event_groups.h"
\r
86 /* Demo program include files. */
\r
87 #include "StaticAllocation.h"
\r
89 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */
\r
90 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
92 /* The priority at which the task that performs the tests is created. */
\r
93 #define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
\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
99 /* A block time of 0 simply means "don't block". */
\r
100 #define staticDONT_BLOCK ( ( TickType_t ) 0 )
\r
102 /* Binary semaphores have a maximum count of 1. */
\r
103 #define staticBINARY_SEMAPHORE_MAX_COUNT ( 1 )
\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
108 /* The number of times the software timer will execute before stopping itself. */
\r
109 #define staticMAX_TIMER_CALLBACK_EXECUTIONS ( 5 )
\r
112 /*-----------------------------------------------------------*/
\r
115 * The task that repeatedly creates and deletes statically allocated tasks, and
\r
116 * other RTOS objects.
\r
118 static void prvStaticallyAllocatedCreator( void *pvParameters );
\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
124 static void prvTimerCallback( TimerHandle_t xExpiredTimer );
\r
127 * A task that is created and deleted multiple times, using both statically and
\r
128 * dynamically allocated stack and TCB.
\r
130 static void prvStaticallyAllocatedTask( void *pvParameters );
\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
137 static void prvCreateAndDeleteStaticallyAllocatedTasks( void );
\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
144 static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void );
\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
151 static void prvCreateAndDeleteStaticallyAllocatedQueues( void );
\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
158 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );
\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
165 static void prvCreateAndDeleteStaticallyAllocatedTimers( void );
\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
172 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void );
\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
179 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void );
\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
187 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );
\r
190 * Utility function to create pseudo random numbers.
\r
192 static UBaseType_t prvRand( void );
\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
200 static TickType_t prvGetNextDelayTime( void );
\r
203 * Checks the basic operation of a queue after it has been created.
\r
205 static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue );
\r
208 * Checks the basic operation of a recursive mutex after it has been created.
\r
210 static void prvSanityCheckCreatedRecursiveMutex( SemaphoreHandle_t xSemaphore );
\r
213 * Checks the basic operation of a binary semaphore after it has been created.
\r
215 static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount );
\r
218 * Checks the basic operation of an event group after it has been created.
\r
220 static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup );
\r
222 /*-----------------------------------------------------------*/
\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
232 static StaticTask_t xCreatorTaskTCBBuffer;
\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
239 /* Used by the pseudo random number generating function. */
\r
240 static uint32_t ulNextRand = 0;
\r
242 /* Used so a check task can ensure this test is still executing, and not
\r
244 static volatile UBaseType_t uxCycleCounter = 0;
\r
246 /* A variable that gets set to pdTRUE if an error is detected. */
\r
247 static volatile BaseType_t xErrorOccurred = pdFALSE;
\r
249 /*-----------------------------------------------------------*/
\r
251 void vStartStaticallyAllocatedTasks( void )
\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
265 /* Pseudo seed the random number generator. */
\r
266 ulNextRand = ( uint32_t ) prvRand;
\r
268 /*-----------------------------------------------------------*/
\r
270 static void prvStaticallyAllocatedCreator( void *pvParameters )
\r
272 /* Avoid compiler warnings. */
\r
273 ( void ) pvParameters;
\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
280 prvCreateAndDeleteStaticallyAllocatedTasks();
\r
281 prvCreateAndDeleteStaticallyAllocatedQueues();
\r
283 /* Ensure lower priority tasks get CPU time. */
\r
284 vTaskDelay( prvGetNextDelayTime() );
\r
286 /* Just to show the check task that this task is still executing. */
\r
289 prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();
\r
290 prvCreateAndDeleteStaticallyAllocatedCountingSemaphores();
\r
292 vTaskDelay( prvGetNextDelayTime() );
\r
295 prvCreateAndDeleteStaticallyAllocatedMutexes();
\r
296 prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes();
\r
298 vTaskDelay( prvGetNextDelayTime() );
\r
301 prvCreateAndDeleteStaticallyAllocatedEventGroups();
\r
302 prvCreateAndDeleteStaticallyAllocatedTimers();
\r
305 /*-----------------------------------------------------------*/
\r
307 static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup )
\r
309 EventBits_t xEventBits;
\r
310 const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( EventBits_t ) 0x55;
\r
312 /* The event group should not have any bits set yet. */
\r
313 xEventBits = xEventGroupGetBits( xEventGroup );
\r
315 if( xEventBits != ( EventBits_t ) 0 )
\r
317 xErrorOccurred = pdTRUE;
\r
320 /* Some some bits, then read them back to check they are as expected. */
\r
321 xEventGroupSetBits( xEventGroup, xFirstTestBits );
\r
323 xEventBits = xEventGroupGetBits( xEventGroup );
\r
325 if( xEventBits != xFirstTestBits )
\r
327 xErrorOccurred = pdTRUE;
\r
330 xEventGroupSetBits( xEventGroup, xSecondTestBits );
\r
332 xEventBits = xEventGroupGetBits( xEventGroup );
\r
334 if( xEventBits != ( xFirstTestBits | xSecondTestBits ) )
\r
336 xErrorOccurred = pdTRUE;
\r
339 /* Finally try clearing some bits too and check that operation proceeds as
\r
341 xEventGroupClearBits( xEventGroup, xFirstTestBits );
\r
343 xEventBits = xEventGroupGetBits( xEventGroup );
\r
345 if( xEventBits != xSecondTestBits )
\r
347 xErrorOccurred = pdTRUE;
\r
350 /*-----------------------------------------------------------*/
\r
352 static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )
\r
354 BaseType_t xReturned;
\r
356 const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );
\r
357 TickType_t xTickCount;
\r
359 /* The binary semaphore should start 'empty', so a call to xSemaphoreTake()
\r
361 xTickCount = xTaskGetTickCount();
\r
362 xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
\r
364 if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )
\r
366 /* Did not block on the semaphore as long as expected. */
\r
367 xErrorOccurred = pdTRUE;
\r
370 if( xReturned != pdFAIL )
\r
372 xErrorOccurred = pdTRUE;
\r
375 /* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount
\r
377 for( x = 0; x < uxMaxCount; x++ )
\r
379 xReturned = xSemaphoreGive( xSemaphore );
\r
381 if( xReturned == pdFAIL )
\r
383 xErrorOccurred = pdTRUE;
\r
387 /* Giving the semaphore again should fail, as it is 'full'. */
\r
388 xReturned = xSemaphoreGive( xSemaphore );
\r
390 if( xReturned != pdFAIL )
\r
392 xErrorOccurred = pdTRUE;
\r
395 configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );
\r
397 /* Should now be possible to 'take' the semaphore up to a maximum of
\r
398 uxMaxCount times without blocking. */
\r
399 for( x = 0; x < uxMaxCount; x++ )
\r
401 xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
\r
403 if( xReturned == pdFAIL )
\r
405 xErrorOccurred = pdTRUE;
\r
409 /* Back to the starting condition, where the semaphore should not be
\r
411 xTickCount = xTaskGetTickCount();
\r
412 xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
\r
414 if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )
\r
416 /* Did not block on the semaphore as long as expected. */
\r
417 xErrorOccurred = pdTRUE;
\r
420 if( xReturned != pdFAIL )
\r
422 xErrorOccurred = pdTRUE;
\r
425 configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );
\r
427 /*-----------------------------------------------------------*/
\r
429 static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue )
\r
431 uint64_t ull, ullRead;
\r
432 BaseType_t xReturned, xLoop;
\r
434 /* This test is done twice to ensure the queue storage area wraps. */
\r
435 for( xLoop = 0; xLoop < 2; xLoop++ )
\r
437 /* A very basic test that the queue can be written to and read from as
\r
438 expected. First the queue should be empty. */
\r
439 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
\r
440 if( xReturned != errQUEUE_EMPTY )
\r
442 xErrorOccurred = pdTRUE;
\r
445 /* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS
\r
447 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
\r
449 xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
\r
450 if( xReturned != pdPASS )
\r
452 xErrorOccurred = pdTRUE;
\r
456 /* Should not now be possible to write to the queue again. */
\r
457 xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
\r
458 if( xReturned != errQUEUE_FULL )
\r
460 xErrorOccurred = pdTRUE;
\r
463 /* Now read back from the queue to ensure the data read back matches that
\r
465 for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
\r
467 xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );
\r
469 if( xReturned != pdPASS )
\r
471 xErrorOccurred = pdTRUE;
\r
474 if( ullRead != ull )
\r
476 xErrorOccurred = pdTRUE;
\r
480 /* The queue should be empty again. */
\r
481 xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
\r
482 if( xReturned != errQUEUE_EMPTY )
\r
484 xErrorOccurred = pdTRUE;
\r
488 /*-----------------------------------------------------------*/
\r
490 static void prvSanityCheckCreatedRecursiveMutex( SemaphoreHandle_t xSemaphore )
\r
492 const BaseType_t xLoops = 5;
\r
493 BaseType_t x, xReturned;
\r
495 /* A very basic test that the recursive semaphore behaved like a recursive
\r
496 semaphore. First the semaphore should not be able to be given, as it has not
\r
498 xReturned = xSemaphoreGiveRecursive( xSemaphore );
\r
500 if( xReturned != pdFAIL )
\r
502 xErrorOccurred = pdTRUE;
\r
505 /* Now it should be possible to take the mutex a number of times. */
\r
506 for( x = 0; x < xLoops; x++ )
\r
508 xReturned = xSemaphoreTakeRecursive( xSemaphore, staticDONT_BLOCK );
\r
510 if( xReturned != pdPASS )
\r
512 xErrorOccurred = pdTRUE;
\r
516 /* Should be possible to give the semaphore the same number of times as it
\r
517 was given in the loop above. */
\r
518 for( x = 0; x < xLoops; x++ )
\r
520 xReturned = xSemaphoreGiveRecursive( xSemaphore );
\r
522 if( xReturned != pdPASS )
\r
524 xErrorOccurred = pdTRUE;
\r
528 /* No more gives should be possible though. */
\r
529 xReturned = xSemaphoreGiveRecursive( xSemaphore );
\r
531 if( xReturned != pdFAIL )
\r
533 xErrorOccurred = pdTRUE;
\r
536 /*-----------------------------------------------------------*/
\r
538 static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void )
\r
540 SemaphoreHandle_t xSemaphore;
\r
541 const UBaseType_t uxMaxCount = ( UBaseType_t ) 10;
\r
543 /* StaticSemaphore_t is a publicly accessible structure that has the same size
\r
544 and alignment requirements as the real semaphore structure. It is provided as a
\r
545 mechanism for applications to know the size of the semaphore (which is dependent
\r
546 on the architecture and configuration file settings) without breaking the strict
\r
547 data hiding policy by exposing the real semaphore internals. This
\r
548 StaticSemaphore_t variable is passed into the xSemaphoreCreateCountingStatic()
\r
549 function calls within this function. NOTE: In most usage scenarios now it is
\r
550 faster and more memory efficient to use a direct to task notification instead of
\r
551 a counting semaphore. http://www.freertos.org/RTOS-task-notifications.html */
\r
552 StaticSemaphore_t xSemaphoreBuffer;
\r
554 /* Create the semaphore. xSemaphoreCreateCountingStatic() has one more
\r
555 parameter than the usual xSemaphoreCreateCounting() function. The paraemter
\r
556 is a pointer to the pre-allocated StaticSemaphore_t structure, which will
\r
557 hold information on the semaphore in an anonymous way. If the pointer is
\r
558 passed as NULL then the structure will be allocated dynamically, just as
\r
559 when xSemaphoreCreateCounting() is called. */
\r
560 xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, &xSemaphoreBuffer );
\r
562 /* The semaphore handle should equal the static semaphore structure passed
\r
563 into the xSemaphoreCreateBinaryStatic() function. */
\r
564 configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
\r
566 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
567 prvSanityCheckCreatedSemaphore( xSemaphore, uxMaxCount );
\r
569 /* Delete the semaphore again so the buffers can be reused. */
\r
570 vSemaphoreDelete( xSemaphore );
\r
572 /*-----------------------------------------------------------*/
\r
574 static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void )
\r
576 SemaphoreHandle_t xSemaphore;
\r
578 /* StaticSemaphore_t is a publicly accessible structure that has the same size
\r
579 and alignment requirements as the real semaphore structure. It is provided as a
\r
580 mechanism for applications to know the size of the semaphore (which is dependent
\r
581 on the architecture and configuration file settings) without breaking the strict
\r
582 data hiding policy by exposing the real semaphore internals. This
\r
583 StaticSemaphore_t variable is passed into the
\r
584 xSemaphoreCreateRecursiveMutexStatic() function calls within this function. */
\r
585 StaticSemaphore_t xSemaphoreBuffer;
\r
587 /* Create the semaphore. xSemaphoreCreateRecursiveMutexStatic() has one
\r
588 more parameter than the usual xSemaphoreCreateRecursiveMutex() function.
\r
589 The parameter is a pointer to the pre-allocated StaticSemaphore_t structure,
\r
590 which will hold information on the semaphore in an anonymous way. If the
\r
591 pointer is passed as NULL then the structure will be allocated dynamically,
\r
592 just as when xSemaphoreCreateRecursiveMutex() is called. */
\r
593 xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );
\r
595 /* The semaphore handle should equal the static semaphore structure passed
\r
596 into the xSemaphoreCreateBinaryStatic() function. */
\r
597 configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
\r
599 /* Ensure the semaphore passes a few sanity checks as a valid
\r
600 recursive semaphore. */
\r
601 prvSanityCheckCreatedRecursiveMutex( xSemaphore );
\r
603 /* Delete the semaphore again so the buffers can be reused. */
\r
604 vSemaphoreDelete( xSemaphore );
\r
606 /*-----------------------------------------------------------*/
\r
608 static void prvCreateAndDeleteStaticallyAllocatedQueues( void )
\r
610 QueueHandle_t xQueue;
\r
612 /* StaticQueue_t is a publicly accessible structure that has the same size and
\r
613 alignment requirements as the real queue structure. It is provided as a
\r
614 mechanism for applications to know the size of the queue (which is dependent on
\r
615 the architecture and configuration file settings) without breaking the strict
\r
616 data hiding policy by exposing the real queue internals. This StaticQueue_t
\r
617 variable is passed into the xQueueCreateStatic() function calls within this
\r
619 static StaticQueue_t xStaticQueue;
\r
621 /* The queue storage area must be large enough to hold the maximum number of
\r
622 items it is possible for the queue to hold at any one time, which equals the
\r
623 queue length (in items, not bytes) multiplied by the size of each item. In this
\r
624 case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items. See
\r
625 http://www.freertos.org/Embedded-RTOS-Queues.html */
\r
626 static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ];
\r
628 /* Create the queue. xQueueCreateStatic() has two more parameters than the
\r
629 usual xQueueCreate() function. The first new parameter is a pointer to the
\r
630 pre-allocated queue storage area. The second new parameter is a pointer to
\r
631 the StaticQueue_t structure that will hold the queue state information in
\r
632 an anonymous way. If the two pointers are passed as NULL then the data
\r
633 will be allocated dynamically as if xQueueCreate() had been called. */
\r
634 xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */
\r
635 sizeof( uint64_t ), /* The size of each item. */
\r
636 ucQueueStorageArea, /* The buffer used to hold items within the queue. */
\r
637 &xStaticQueue ); /* The static queue structure that will hold the state of the queue. */
\r
639 /* The queue handle should equal the static queue structure passed into the
\r
640 xQueueCreateStatic() function. */
\r
641 configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );
\r
643 /* Ensure the queue passes a few sanity checks as a valid queue. */
\r
644 prvSanityCheckCreatedQueue( xQueue );
\r
646 /* Delete the queue again so the buffers can be reused. */
\r
647 vQueueDelete( xQueue );
\r
649 /*-----------------------------------------------------------*/
\r
651 static void prvCreateAndDeleteStaticallyAllocatedMutexes( void )
\r
653 SemaphoreHandle_t xSemaphore;
\r
654 BaseType_t xReturned;
\r
656 /* StaticSemaphore_t is a publicly accessible structure that has the same size
\r
657 and alignment requirements as the real semaphore structure. It is provided as a
\r
658 mechanism for applications to know the size of the semaphore (which is dependent
\r
659 on the architecture and configuration file settings) without breaking the strict
\r
660 data hiding policy by exposing the real semaphore internals. This
\r
661 StaticSemaphore_t variable is passed into the xSemaphoreCreateMutexStatic()
\r
662 function calls within this function. */
\r
663 StaticSemaphore_t xSemaphoreBuffer;
\r
665 /* Create the semaphore. xSemaphoreCreateMutexStatic() has one more
\r
666 parameter than the usual xSemaphoreCreateMutex() function. The paraemter
\r
667 is a pointer to the pre-allocated StaticSemaphore_t structure, which will
\r
668 hold information on the semaphore in an anonymous way. If the pointer is
\r
669 passed as NULL then the structure will be allocated dynamically, just as
\r
670 when xSemaphoreCreateMutex() is called. */
\r
671 xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );
\r
673 /* The semaphore handle should equal the static semaphore structure passed
\r
674 into the xSemaphoreCreateMutexStatic() function. */
\r
675 configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
\r
677 /* Take the mutex so the mutex is in the state expected by the
\r
678 prvSanityCheckCreatedSemaphore() function. */
\r
679 xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
\r
681 if( xReturned != pdPASS )
\r
683 xErrorOccurred = pdTRUE;
\r
686 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
687 prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
689 /* Delete the semaphore again so the buffers can be reused. */
\r
690 vSemaphoreDelete( xSemaphore );
\r
692 /*-----------------------------------------------------------*/
\r
694 static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )
\r
696 SemaphoreHandle_t xSemaphore;
\r
698 /* StaticSemaphore_t is a publicly accessible structure that has the same size
\r
699 and alignment requirements as the real semaphore structure. It is provided as a
\r
700 mechanism for applications to know the size of the semaphore (which is dependent
\r
701 on the architecture and configuration file settings) without breaking the strict
\r
702 data hiding policy by exposing the real semaphore internals. This
\r
703 StaticSemaphore_t variable is passed into the xSemaphoreCreateBinaryStatic()
\r
704 function calls within this function. NOTE: In most usage scenarios now it is
\r
705 faster and more memory efficient to use a direct to task notification instead of
\r
706 a binary semaphore. http://www.freertos.org/RTOS-task-notifications.html */
\r
707 StaticSemaphore_t xSemaphoreBuffer;
\r
709 /* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more
\r
710 parameter than the usual xSemaphoreCreateBinary() function. The paraemter
\r
711 is a pointer to the pre-allocated StaticSemaphore_t structure, which will
\r
712 hold information on the semaphore in an anonymous way. If the pointer is
\r
713 passed as NULL then the structure will be allocated dynamically, just as
\r
714 when xSemaphoreCreateBinary() is called. */
\r
715 xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
\r
717 /* The semaphore handle should equal the static semaphore structure passed
\r
718 into the xSemaphoreCreateBinaryStatic() function. */
\r
719 configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
\r
721 /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
\r
722 prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
724 /* Delete the semaphore again so the buffers can be reused. */
\r
725 vSemaphoreDelete( xSemaphore );
\r
728 /* There isn't a static version of the old and deprecated
\r
729 vSemaphoreCreateBinary() macro (because its deprecated!), but check it is
\r
730 still functioning correctly when configSUPPORT_STATIC_ALLOCATION is set to
\r
732 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
734 vSemaphoreCreateBinary( xSemaphore );
\r
736 /* The macro starts with the binary semaphore available, but the test
\r
737 function expects it to be unavailable. */
\r
738 if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL )
\r
740 xErrorOccurred = pdTRUE;
\r
743 prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
\r
744 vSemaphoreDelete( xSemaphore );
\r
748 /*-----------------------------------------------------------*/
\r
750 static void prvTimerCallback( TimerHandle_t xExpiredTimer )
\r
752 UBaseType_t *puxVariableToIncrement;
\r
753 BaseType_t xReturned;
\r
755 /* Obtain the address of the variable to increment from the timer ID. */
\r
756 puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );
\r
758 /* Increment the variable to show the timer callback has executed. */
\r
759 ( *puxVariableToIncrement )++;
\r
761 /* If this callback has executed the required number of times, stop the
\r
763 if( *puxVariableToIncrement == staticMAX_TIMER_CALLBACK_EXECUTIONS )
\r
765 /* This is called from a timer callback so must not block. */
\r
766 xReturned = xTimerStop( xExpiredTimer, staticDONT_BLOCK );
\r
768 if( xReturned != pdPASS )
\r
770 xErrorOccurred = pdTRUE;
\r
774 /*-----------------------------------------------------------*/
\r
776 static void prvCreateAndDeleteStaticallyAllocatedTimers( void )
\r
778 TimerHandle_t xTimer;
\r
779 UBaseType_t uxVariableToIncrement;
\r
780 const TickType_t xTimerPeriod = pdMS_TO_TICKS( 20 );
\r
781 BaseType_t xReturned;
\r
783 /* StaticTimer_t is a publicly accessible structure that has the same size
\r
784 and alignment requirements as the real timer structure. It is provided as a
\r
785 mechanism for applications to know the size of the timer structure (which is
\r
786 dependent on the architecture and configuration file settings) without breaking
\r
787 the strict data hiding policy by exposing the real timer internals. This
\r
788 StaticTimer_t variable is passed into the xTimerCreateStatic() function calls
\r
789 within this function. */
\r
790 StaticTimer_t xTimerBuffer;
\r
792 /* Create the software time. xTimerCreateStatic() has an extra parameter
\r
793 than the normal xTimerCreate() API function. The parameter is a pointer to
\r
794 the StaticTimer_t structure that will hold the software timer structure. If
\r
795 the parameter is passed as NULL then the structure will be allocated
\r
796 dynamically, just as if xTimerCreate() had been called. */
\r
797 xTimer = xTimerCreateStatic( "T1", /* Text name for the task. Helps debugging only. Not used by FreeRTOS. */
\r
798 xTimerPeriod, /* The period of the timer in ticks. */
\r
799 pdTRUE, /* This is an auto-reload timer. */
\r
800 ( void * ) &uxVariableToIncrement, /* The variable incremented by the test is passed into the timer callback using the timer ID. */
\r
801 prvTimerCallback, /* The function to execute when the timer expires. */
\r
802 &xTimerBuffer ); /* The buffer that will hold the software timer structure. */
\r
804 /* The timer handle should equal the static timer structure passed into the
\r
805 xTimerCreateStatic() function. */
\r
806 configASSERT( xTimer == ( TimerHandle_t ) &xTimerBuffer );
\r
808 /* Set the variable to 0, wait for a few timer periods to expire, then check
\r
809 the timer callback has incremented the variable to the expected value. */
\r
810 uxVariableToIncrement = 0;
\r
812 /* This is a low priority so a block time should not be needed. */
\r
813 xReturned = xTimerStart( xTimer, staticDONT_BLOCK );
\r
815 if( xReturned != pdPASS )
\r
817 xErrorOccurred = pdTRUE;
\r
820 vTaskDelay( xTimerPeriod * staticMAX_TIMER_CALLBACK_EXECUTIONS );
\r
822 /* By now the timer should have expired staticMAX_TIMER_CALLBACK_EXECUTIONS
\r
823 times, and then stopped itself. */
\r
824 if( uxVariableToIncrement != staticMAX_TIMER_CALLBACK_EXECUTIONS )
\r
826 xErrorOccurred = pdTRUE;
\r
829 /* Finished with the timer, delete it. */
\r
830 xReturned = xTimerDelete( xTimer, staticDONT_BLOCK );
\r
832 /* Again, as this is a low priority task it is expected that the timer
\r
833 command will have been sent even without a block time being used. */
\r
834 if( xReturned != pdPASS )
\r
836 xErrorOccurred = pdTRUE;
\r
839 /* Just to show the check task that this task is still executing. */
\r
842 /*-----------------------------------------------------------*/
\r
844 static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void )
\r
846 EventGroupHandle_t xEventGroup;
\r
848 /* StaticEventGroup_t is a publicly accessible structure that has the same size
\r
849 and alignment requirements as the real event group structure. It is provided as
\r
850 a mechanism for applications to know the size of the event group (which is
\r
851 dependent on the architecture and configuration file settings) without breaking
\r
852 the strict data hiding policy by exposing the real event group internals. This
\r
853 StaticEventGroup_t variable is passed into the xSemaphoreCreateEventGroupStatic()
\r
854 function calls within this function. */
\r
855 StaticEventGroup_t xEventGroupBuffer;
\r
857 /* Create the event group. xEventGroupCreateStatic() has an extra parameter
\r
858 than the normal xEventGroupCreate() API function. The parameter is a
\r
859 pointer to the StaticEventGroup_t structure that will hold the event group
\r
860 structure. If the parameter is passed as NULL then the structure will be
\r
861 allocated dynamically, just as if xEventGroupCreate() had been called. */
\r
862 xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
\r
864 /* The event group handle should equal the static event group structure
\r
865 passed into the xEventGroupCreateStatic() function. */
\r
866 configASSERT( xEventGroup == ( EventGroupHandle_t ) &xEventGroupBuffer );
\r
868 /* Ensure the event group passes a few sanity checks as a valid event
\r
870 prvSanityCheckCreatedEventGroup( xEventGroup );
\r
872 /* Delete the event group again so the buffers can be reused. */
\r
873 vEventGroupDelete( xEventGroup );
\r
875 /*-----------------------------------------------------------*/
\r
877 static void prvCreateAndDeleteStaticallyAllocatedTasks( void )
\r
879 TaskHandle_t xCreatedTask;
\r
880 BaseType_t xReturned;
\r
882 /* The variable that will hold the TCB of tasks created by this function. See
\r
883 the comments above the declaration of the xCreatorTaskTCBBuffer variable for
\r
884 more information. */
\r
885 StaticTask_t xTCBBuffer;
\r
887 /* This buffer that will be used as the stack of tasks created by this function.
\r
888 See the comments above the declaration of the uxCreatorTaskStackBuffer[] array
\r
889 above for more information. */
\r
890 static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
\r
892 /* Create the task. xTaskCreateStatic() has two more parameters than
\r
893 the usual xTaskCreate() function. The first new parameter is a pointer to
\r
894 the pre-allocated stack. The second new parameter is a pointer to the
\r
895 StaticTask_t structure that will hold the task's TCB. If both pointers are
\r
896 passed as NULL then the respective object will be allocated dynamically as
\r
897 if xTaskCreate() had been called. */
\r
898 xReturned = xTaskCreateStatic(
\r
899 prvStaticallyAllocatedTask, /* Function that implements the task. */
\r
900 "Static", /* Human readable name for the task. */
\r
901 configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */
\r
902 NULL, /* Parameter to pass into the task. */
\r
903 tskIDLE_PRIORITY, /* The priority of the task. */
\r
904 &xCreatedTask, /* Handle of the task being created. */
\r
905 &( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */
\r
906 &xTCBBuffer ); /* The variable that will hold that task's TCB. */
\r
908 /* Check the task was created correctly, then delete the task. */
\r
909 configASSERT( xReturned == pdPASS );
\r
910 if( xReturned != pdPASS )
\r
912 xErrorOccurred = pdTRUE;
\r
914 vTaskDelete( xCreatedTask );
\r
916 /*-----------------------------------------------------------*/
\r
918 static void prvStaticallyAllocatedTask( void *pvParameters )
\r
920 ( void ) pvParameters;
\r
922 /* The created task doesn't do anything - just waits to get deleted. */
\r
923 vTaskSuspend( NULL );
\r
925 /*-----------------------------------------------------------*/
\r
927 static UBaseType_t prvRand( void )
\r
929 const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
\r
931 /* Utility function to generate a pseudo random number. */
\r
932 ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
\r
933 return( ( ulNextRand >> 16UL ) & 0x7fffUL );
\r
935 /*-----------------------------------------------------------*/
\r
937 static TickType_t prvGetNextDelayTime( void )
\r
939 TickType_t xNextDelay;
\r
940 const TickType_t xMaxDelay = pdMS_TO_TICKS( ( TickType_t ) 150 );
\r
941 const TickType_t xMinDelay = pdMS_TO_TICKS( ( TickType_t ) 75 );
\r
942 const TickType_t xTinyDelay = pdMS_TO_TICKS( ( TickType_t ) 2 );
\r
944 /* Generate the next delay time. This is kept within a narrow band so as
\r
945 not to disturb the timing of other tests - but does add in some pseudo
\r
946 randomisation into the tests. */
\r
949 xNextDelay = prvRand() % xMaxDelay;
\r
951 /* Just in case this loop is executed lots of times. */
\r
952 vTaskDelay( xTinyDelay );
\r
954 } while ( xNextDelay < xMinDelay );
\r
958 /*-----------------------------------------------------------*/
\r
960 BaseType_t xAreStaticAllocationTasksStillRunning( void )
\r
962 static UBaseType_t uxLastCycleCounter = 0;
\r
963 BaseType_t xReturn;
\r
965 if( uxCycleCounter == uxLastCycleCounter )
\r
967 xErrorOccurred = pdTRUE;
\r
971 uxLastCycleCounter = uxCycleCounter;
\r
974 if( xErrorOccurred != pdFALSE )
\r
985 /*-----------------------------------------------------------*/
\r
987 /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */
\r
988 #endif /* configSUPPORT_STATIC_ALLOCATION == 1 */
\r