]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/WIN32-MingW/main_full.c
84ae4074e3c7711e7400dc532527a1d3f7a82887
[freertos] / FreeRTOS / Demo / WIN32-MingW / main_full.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /*\r
29  *******************************************************************************\r
30  * NOTE 1: The Win32 port is a simulation (or is that emulation?) only!  Do not\r
31  * expect to get real time behaviour from the Win32 port or this demo\r
32  * application.  It is provided as a convenient development and demonstration\r
33  * test bed only.\r
34  *\r
35  * Windows will not be running the FreeRTOS simulator threads continuously, so\r
36  * the timing information in the FreeRTOS+Trace logs have no meaningful units.\r
37  * See the documentation page for the Windows simulator for an explanation of\r
38  * the slow timing:\r
39  * http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html\r
40  * - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT -\r
41  *\r
42  * NOTE 2:  This project provides two demo applications.  A simple blinky style\r
43  * project, and a more comprehensive test and demo application.  The\r
44  * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select\r
45  * between the two.  See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY\r
46  * in main.c.  This file implements the comprehensive test and demo version.\r
47  *\r
48  * NOTE 3:  This file only contains the source code that is specific to the\r
49  * full demo.  Generic functions, such FreeRTOS hook functions, are defined in\r
50  * main.c.\r
51  *******************************************************************************\r
52  *\r
53  * main() creates all the demo application tasks, then starts the scheduler.\r
54  * The web documentation provides more details of the standard demo application\r
55  * tasks, which provide no particular functionality but do provide a good\r
56  * example of how to use the FreeRTOS API.\r
57  *\r
58  * In addition to the standard demo tasks, the following tasks and tests are\r
59  * defined and/or created within this file:\r
60  *\r
61  * "Check" task - This only executes every five seconds but has a high priority\r
62  * to ensure it gets processor time.  Its main function is to check that all the\r
63  * standard demo tasks are still operational.  While no errors have been\r
64  * discovered the check task will print out "OK" and the current simulated tick\r
65  * time.  If an error is discovered in the execution of a task then the check\r
66  * task will print out an appropriate error message.\r
67  *\r
68  */\r
69 \r
70 \r
71 /* Standard includes. */\r
72 #include <stdio.h>\r
73 #include <stdlib.h>\r
74 \r
75 /* Kernel includes. */\r
76 #include <FreeRTOS.h>\r
77 #include <task.h>\r
78 #include <queue.h>\r
79 #include <timers.h>\r
80 #include <semphr.h>\r
81 \r
82 /* Standard demo includes. */\r
83 #include "BlockQ.h"\r
84 #include "integer.h"\r
85 #include "semtest.h"\r
86 #include "PollQ.h"\r
87 #include "GenQTest.h"\r
88 #include "QPeek.h"\r
89 #include "recmutex.h"\r
90 #include "flop.h"\r
91 #include "TimerDemo.h"\r
92 #include "countsem.h"\r
93 #include "death.h"\r
94 #include "dynamic.h"\r
95 #include "QueueSet.h"\r
96 #include "QueueOverwrite.h"\r
97 #include "EventGroupsDemo.h"\r
98 #include "IntSemTest.h"\r
99 #include "TaskNotify.h"\r
100 #include "QueueSetPolling.h"\r
101 #include "StaticAllocation.h"\r
102 #include "blocktim.h"\r
103 #include "AbortDelay.h"\r
104 #include "MessageBufferDemo.h"\r
105 #include "StreamBufferDemo.h"\r
106 #include "StreamBufferInterrupt.h"\r
107 #include "MessageBufferAMP.h"\r
108 \r
109 /* Priorities at which the tasks are created. */\r
110 #define mainCHECK_TASK_PRIORITY                 ( configMAX_PRIORITIES - 2 )\r
111 #define mainQUEUE_POLL_PRIORITY                 ( tskIDLE_PRIORITY + 1 )\r
112 #define mainSEM_TEST_PRIORITY                   ( tskIDLE_PRIORITY + 1 )\r
113 #define mainBLOCK_Q_PRIORITY                    ( tskIDLE_PRIORITY + 2 )\r
114 #define mainCREATOR_TASK_PRIORITY               ( tskIDLE_PRIORITY + 3 )\r
115 #define mainFLASH_TASK_PRIORITY                 ( tskIDLE_PRIORITY + 1 )\r
116 #define mainINTEGER_TASK_PRIORITY               ( tskIDLE_PRIORITY )\r
117 #define mainGEN_QUEUE_TASK_PRIORITY             ( tskIDLE_PRIORITY )\r
118 #define mainFLOP_TASK_PRIORITY                  ( tskIDLE_PRIORITY )\r
119 #define mainQUEUE_OVERWRITE_PRIORITY    ( tskIDLE_PRIORITY )\r
120 \r
121 #define mainTIMER_TEST_PERIOD                   ( 50 )\r
122 \r
123 /*\r
124  * Exercises code that is not otherwise covered by the standard demo/test\r
125  * tasks.\r
126  */\r
127 extern BaseType_t xRunCodeCoverageTestAdditions( void );\r
128 \r
129 /* Task function prototypes. */\r
130 static void prvCheckTask( void *pvParameters );\r
131 \r
132 /* A task that is created from the idle task to test the functionality of\r
133 eTaskStateGet(). */\r
134 static void prvTestTask( void *pvParameters );\r
135 \r
136 /*\r
137  * Called from the idle task hook function to demonstrate a few utility\r
138  * functions that are not demonstrated by any of the standard demo tasks.\r
139  */\r
140 static void prvDemonstrateTaskStateAndHandleGetFunctions( void );\r
141 \r
142 /*\r
143  * Called from the idle task hook function to demonstrate the use of\r
144  * xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by\r
145  * any of the standard demo tasks.\r
146  */\r
147 static void prvDemonstratePendingFunctionCall( void );\r
148 \r
149 /*\r
150  * The function that is pended by prvDemonstratePendingFunctionCall().\r
151  */\r
152 static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 );\r
153 \r
154 /*\r
155  * prvDemonstrateTimerQueryFunctions() is called from the idle task hook\r
156  * function to demonstrate the use of functions that query information about a\r
157  * software timer.  prvTestTimerCallback() is the callback function for the\r
158  * timer being queried.\r
159  */\r
160 static void prvDemonstrateTimerQueryFunctions( void );\r
161 static void prvTestTimerCallback( TimerHandle_t xTimer );\r
162 \r
163 /*\r
164  * A task to demonstrate the use of the xQueueSpacesAvailable() function.\r
165  */\r
166 static void prvDemoQueueSpaceFunctions( void *pvParameters );\r
167 \r
168 /*\r
169  * Tasks that ensure indefinite delays are truly indefinite.\r
170  */\r
171 static void prvPermanentlyBlockingSemaphoreTask( void *pvParameters );\r
172 static void prvPermanentlyBlockingNotificationTask( void *pvParameters );\r
173 \r
174 /*\r
175  * The test function and callback function used when exercising the timer AP\r
176  * function that changes the timer's autoreload mode.\r
177  */\r
178 static void prvDemonstrateChangingTimerReloadMode( void *pvParameters );\r
179 static void prvReloadModeTestTimerCallback( TimerHandle_t xTimer );\r
180 \r
181 /*-----------------------------------------------------------*/\r
182 \r
183 /* The variable into which error messages are latched. */\r
184 static char *pcStatusMessage = "No errors";\r
185 \r
186 /* This semaphore is created purely to test using the vSemaphoreDelete() and\r
187 semaphore tracing API functions.  It has no other purpose. */\r
188 static SemaphoreHandle_t xMutexToDelete = NULL;\r
189 \r
190 /*-----------------------------------------------------------*/\r
191 \r
192 int main_full( void )\r
193 {\r
194         /* Start the check task as described at the top of this file. */\r
195         xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
196 \r
197         /* Create the standard demo tasks. */\r
198         vStartTaskNotifyTask();\r
199         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
200         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
201         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
202         vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
203         vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
204         vStartQueuePeekTasks();\r
205         vStartMathTasks( mainFLOP_TASK_PRIORITY );\r
206         vStartRecursiveMutexTasks();\r
207         vStartCountingSemaphoreTasks();\r
208         vStartDynamicPriorityTasks();\r
209         vStartQueueSetTasks();\r
210         vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );\r
211         xTaskCreate( prvDemoQueueSpaceFunctions, NULL, configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); /* Name is null for code coverage. */\r
212         vStartEventGroupTasks();\r
213         vStartInterruptSemaphoreTasks();\r
214         vStartQueueSetPollingTask();\r
215         vCreateBlockTimeTasks();\r
216         vCreateAbortDelayTasks();\r
217         xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
218         xTaskCreate( prvPermanentlyBlockingSemaphoreTask, "BlockSem", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
219         xTaskCreate( prvPermanentlyBlockingNotificationTask, "BlockNoti", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
220         xTaskCreate( prvDemonstrateChangingTimerReloadMode, "TimerMode", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
221 \r
222         vStartMessageBufferTasks( configMINIMAL_STACK_SIZE );\r
223         vStartStreamBufferTasks();\r
224         vStartStreamBufferInterruptDemo();\r
225         vStartMessageBufferAMPTasks( configMINIMAL_STACK_SIZE );\r
226 \r
227         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
228         {\r
229                 vStartStaticallyAllocatedTasks();\r
230         }\r
231         #endif\r
232 \r
233         #if( configUSE_PREEMPTION != 0  )\r
234         {\r
235                 /* Don't expect these tasks to pass when preemption is not used. */\r
236                 vStartTimerDemoTask( mainTIMER_TEST_PERIOD );\r
237         }\r
238         #endif\r
239 \r
240         /* The suicide tasks must be created last as they need to know how many\r
241         tasks were running prior to their creation.  This then allows them to\r
242         ascertain whether or not the correct/expected number of tasks are running at\r
243         any given time. */\r
244         vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );\r
245 \r
246         /* Create the semaphore that will be deleted in the idle task hook.  This\r
247         is done purely to test the use of vSemaphoreDelete(). */\r
248         xMutexToDelete = xSemaphoreCreateMutex();\r
249 \r
250         /* Start the scheduler itself. */\r
251         vTaskStartScheduler();\r
252 \r
253         /* Should never get here unless there was not enough heap space to create\r
254         the idle and other system tasks. */\r
255         return 0;\r
256 }\r
257 /*-----------------------------------------------------------*/\r
258 \r
259 static void prvCheckTask( void *pvParameters )\r
260 {\r
261 TickType_t xNextWakeTime;\r
262 const TickType_t xCycleFrequency = pdMS_TO_TICKS( 2500UL );\r
263 HeapStats_t xHeapStats;\r
264 \r
265         /* Just to remove compiler warning. */\r
266         ( void ) pvParameters;\r
267 \r
268         /* Initialise xNextWakeTime - this only needs to be done once. */\r
269         xNextWakeTime = xTaskGetTickCount();\r
270 \r
271         for( ;; )\r
272         {\r
273                 /* Place this task in the blocked state until it is time to run again. */\r
274                 vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );\r
275 \r
276                 /* Check the standard demo tasks are running without error. */\r
277                 #if( configUSE_PREEMPTION != 0 )\r
278                 {\r
279                         /* These tasks are only created when preemption is used. */\r
280                         if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE )\r
281                         {\r
282                                 pcStatusMessage = "Error: TimerDemo";\r
283                         }\r
284                 }\r
285                 #endif\r
286 \r
287                 if( xAreStreamBufferTasksStillRunning() != pdTRUE )\r
288                 {\r
289                         pcStatusMessage = "Error:  StreamBuffer";\r
290                 }\r
291                 else if( xAreMessageBufferTasksStillRunning() != pdTRUE )\r
292                 {\r
293                         pcStatusMessage = "Error:  MessageBuffer";\r
294                 }\r
295                 else if( xAreTaskNotificationTasksStillRunning() != pdTRUE )\r
296                 {\r
297                         pcStatusMessage = "Error:  Notification";\r
298                 }\r
299                 else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )\r
300                 {\r
301                         pcStatusMessage = "Error: IntSem";\r
302                 }\r
303                 else if( xAreEventGroupTasksStillRunning() != pdTRUE )\r
304                 {\r
305                         pcStatusMessage = "Error: EventGroup";\r
306                 }\r
307                 else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
308                 {\r
309                         pcStatusMessage = "Error: IntMath";\r
310                 }\r
311                 else if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
312                 {\r
313                         pcStatusMessage = "Error: GenQueue";\r
314                 }\r
315                 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
316                 {\r
317                         pcStatusMessage = "Error: QueuePeek";\r
318                 }\r
319                 else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
320                 {\r
321                         pcStatusMessage = "Error: BlockQueue";\r
322                 }\r
323                 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
324                 {\r
325                         pcStatusMessage = "Error: SemTest";\r
326                 }\r
327                 else if( xArePollingQueuesStillRunning() != pdTRUE )\r
328                 {\r
329                         pcStatusMessage = "Error: PollQueue";\r
330                 }\r
331                 else if( xAreMathsTaskStillRunning() != pdPASS )\r
332                 {\r
333                         pcStatusMessage = "Error: Flop";\r
334                 }\r
335                 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
336                 {\r
337                         pcStatusMessage = "Error: RecMutex";\r
338                 }\r
339                 else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )\r
340                 {\r
341                         pcStatusMessage = "Error: CountSem";\r
342                 }\r
343                 else if( xIsCreateTaskStillRunning() != pdTRUE )\r
344                 {\r
345                         pcStatusMessage = "Error: Death";\r
346                 }\r
347                 else if( xAreDynamicPriorityTasksStillRunning() != pdPASS )\r
348                 {\r
349                         pcStatusMessage = "Error: Dynamic";\r
350                 }\r
351                 else if( xAreQueueSetTasksStillRunning() != pdPASS )\r
352                 {\r
353                         pcStatusMessage = "Error: Queue set";\r
354                 }\r
355                 else if( xIsQueueOverwriteTaskStillRunning() != pdPASS )\r
356                 {\r
357                         pcStatusMessage = "Error: Queue overwrite";\r
358                 }\r
359                 else if( xAreQueueSetPollTasksStillRunning() != pdPASS )\r
360                 {\r
361                         pcStatusMessage = "Error: Queue set polling";\r
362                 }\r
363                 else if( xAreBlockTimeTestTasksStillRunning() != pdPASS )\r
364                 {\r
365                         pcStatusMessage = "Error: Block time";\r
366                 }\r
367                 else if( xAreAbortDelayTestTasksStillRunning() != pdPASS )\r
368                 {\r
369                         pcStatusMessage = "Error: Abort delay";\r
370                 }\r
371                 else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS )\r
372                 {\r
373                         pcStatusMessage = "Error: Stream buffer interrupt";\r
374                 }\r
375                 else if( xAreMessageBufferAMPTasksStillRunning() != pdPASS )\r
376                 {\r
377                         pcStatusMessage = "Error: Message buffer AMP";\r
378                 }\r
379 \r
380                 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
381                         else if( xAreStaticAllocationTasksStillRunning() != pdPASS )\r
382                         {\r
383                                 pcStatusMessage = "Error: Static allocation";\r
384                         }\r
385                 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
386 \r
387                 /* This is the only task that uses stdout so its ok to call printf()\r
388                 directly. */\r
389                 vPortGetHeapStats( &xHeapStats );\r
390 \r
391                 configASSERT( xHeapStats.xAvailableHeapSpaceInBytes == xPortGetFreeHeapSize() );\r
392                 configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xPortGetMinimumEverFreeHeapSize() );\r
393 \r
394                 printf( "%s - tick count %u - free heap %u - min free heap %u - largest free block %u - number of free blocks %u\r\n",\r
395                                         pcStatusMessage,\r
396                                         xTaskGetTickCount(),\r
397                                         xHeapStats.xAvailableHeapSpaceInBytes,\r
398                                         xHeapStats.xMinimumEverFreeBytesRemaining,\r
399                                         xHeapStats.xSizeOfLargestFreeBlockInBytes,\r
400                                         xHeapStats.xNumberOfFreeBlocks );\r
401 \r
402                 fflush( stdout );\r
403         }\r
404 }\r
405 /*-----------------------------------------------------------*/\r
406 \r
407 static void prvTestTask( void *pvParameters )\r
408 {\r
409 const unsigned long ulMSToSleep = 5;\r
410 \r
411         /* Just to remove compiler warnings. */\r
412         ( void ) pvParameters;\r
413 \r
414         /* This task is just used to test the eTaskStateGet() function.  It\r
415         does not have anything to do. */\r
416         for( ;; )\r
417         {\r
418                 /* Sleep to reduce CPU load, but don't sleep indefinitely in case there are\r
419                 tasks waiting to be terminated by the idle task. */\r
420                 Sleep( ulMSToSleep );\r
421         }\r
422 }\r
423 /*-----------------------------------------------------------*/\r
424 \r
425 /* Called from vApplicationIdleHook(), which is defined in main.c. */\r
426 void vFullDemoIdleFunction( void )\r
427 {\r
428 const unsigned long ulMSToSleep = 15;\r
429 void *pvAllocated;\r
430 \r
431         /* Sleep to reduce CPU load, but don't sleep indefinitely in case there are\r
432         tasks waiting to be terminated by the idle task. */\r
433         Sleep( ulMSToSleep );\r
434 \r
435         /* Demonstrate a few utility functions that are not demonstrated by any of\r
436         the standard demo tasks. */\r
437         prvDemonstrateTaskStateAndHandleGetFunctions();\r
438 \r
439         /* Demonstrate the use of xTimerPendFunctionCall(), which is not\r
440         demonstrated by any of the standard demo tasks. */\r
441         prvDemonstratePendingFunctionCall();\r
442 \r
443         /* Demonstrate the use of functions that query information about a software\r
444         timer. */\r
445         prvDemonstrateTimerQueryFunctions();\r
446 \r
447         /* If xMutexToDelete has not already been deleted, then delete it now.\r
448         This is done purely to demonstrate the use of, and test, the\r
449         vSemaphoreDelete() macro.  Care must be taken not to delete a semaphore\r
450         that has tasks blocked on it. */\r
451         if( xMutexToDelete != NULL )\r
452         {\r
453                 /* For test purposes, add the mutex to the registry, then remove it\r
454                 again, before it is deleted - checking its name is as expected before\r
455                 and after the assertion into the registry and its removal from the\r
456                 registry. */\r
457                 configASSERT( pcQueueGetName( xMutexToDelete ) == NULL );\r
458                 vQueueAddToRegistry( xMutexToDelete, "Test_Mutex" );\r
459                 configASSERT( strcmp( pcQueueGetName( xMutexToDelete ), "Test_Mutex" ) == 0 );\r
460                 vQueueUnregisterQueue( xMutexToDelete );\r
461                 configASSERT( pcQueueGetName( xMutexToDelete ) == NULL );\r
462 \r
463                 vSemaphoreDelete( xMutexToDelete );\r
464                 xMutexToDelete = NULL;\r
465         }\r
466 \r
467         /* Exercise heap_5 a bit.  The malloc failed hook will trap failed\r
468         allocations so there is no need to test here. */\r
469         pvAllocated = pvPortMalloc( ( rand() % 500 ) + 1 );\r
470         vPortFree( pvAllocated );\r
471 \r
472         /* Exit after a fixed time so code coverage results are written to the\r
473         disk. */\r
474         #if( projCOVERAGE_TEST == 1 )\r
475         {\r
476                 const TickType_t xMaxRunTime = pdMS_TO_TICKS( 30000UL );\r
477 \r
478                 /* Exercise code not otherwise executed by standard demo/test tasks. */\r
479                 if( xRunCodeCoverageTestAdditions() != pdPASS )\r
480                 {\r
481                         pcStatusMessage = "Code coverage additions failed.\r\n";\r
482                 }\r
483 \r
484                 if( ( xTaskGetTickCount() - configINITIAL_TICK_COUNT ) >= xMaxRunTime )\r
485                 {\r
486                         vTaskEndScheduler();\r
487                 }\r
488         }\r
489         #endif\r
490 }\r
491 /*-----------------------------------------------------------*/\r
492 \r
493 /* Called by vApplicationTickHook(), which is defined in main.c. */\r
494 void vFullDemoTickHookFunction( void )\r
495 {\r
496 TaskHandle_t xTimerTask;\r
497 \r
498         /* Call the periodic timer test, which tests the timer API functions that\r
499         can be called from an ISR. */\r
500         #if( configUSE_PREEMPTION != 0 )\r
501         {\r
502                 /* Only created when preemption is used. */\r
503                 vTimerPeriodicISRTests();\r
504         }\r
505         #endif\r
506 \r
507         /* Call the periodic queue overwrite from ISR demo. */\r
508         vQueueOverwritePeriodicISRDemo();\r
509 \r
510         /* Write to a queue that is in use as part of the queue set demo to\r
511         demonstrate using queue sets from an ISR. */\r
512         vQueueSetAccessQueueSetFromISR();\r
513         vQueueSetPollingInterruptAccess();\r
514 \r
515         /* Exercise event groups from interrupts. */\r
516         vPeriodicEventGroupsProcessing();\r
517 \r
518         /* Exercise giving mutexes from an interrupt. */\r
519         vInterruptSemaphorePeriodicTest();\r
520 \r
521         /* Exercise using task notifications from an interrupt. */\r
522         xNotifyTaskFromISR();\r
523 \r
524         /* Writes to stream buffer byte by byte to test the stream buffer trigger\r
525         level functionality. */\r
526         vPeriodicStreamBufferProcessing();\r
527 \r
528         /* Writes a string to a string buffer four bytes at a time to demonstrate\r
529         a stream being sent from an interrupt to a task. */\r
530         vBasicStreamBufferSendFromISR();\r
531 \r
532         /* For code coverage purposes. */\r
533         xTimerTask = xTimerGetTimerDaemonTaskHandle();\r
534         configASSERT( uxTaskPriorityGetFromISR( xTimerTask ) == configTIMER_TASK_PRIORITY );\r
535         ( void ) xTimerTask; /* In case configASSERT() is not defined. */\r
536 }\r
537 /*-----------------------------------------------------------*/\r
538 \r
539 static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 )\r
540 {\r
541 static uint32_t ulLastParameter1 = 1000UL, ulLastParameter2 = 0UL;\r
542 uint32_t ulParameter1;\r
543 \r
544         ulParameter1 = ( uint32_t ) pvParameter1;\r
545 \r
546         /* Ensure the parameters are as expected. */\r
547         configASSERT( ulParameter1 == ( ulLastParameter1 + 1 ) );\r
548         configASSERT( ulParameter2 == ( ulLastParameter2 + 1 ) );\r
549 \r
550         /* Remember the parameters for the next time the function is called. */\r
551         ulLastParameter1 = ulParameter1;\r
552         ulLastParameter2 = ulParameter2;\r
553 \r
554         /* Remove compiler warnings in case configASSERT() is not defined. */\r
555         ( void ) ulLastParameter1;\r
556         ( void ) ulLastParameter2;\r
557 }\r
558 /*-----------------------------------------------------------*/\r
559 \r
560 static void prvTestTimerCallback( TimerHandle_t xTimer )\r
561 {\r
562         /* This is the callback function for the timer accessed by\r
563         prvDemonstrateTimerQueryFunctions().  The callback does not do anything. */\r
564         ( void ) xTimer;\r
565 }\r
566 /*-----------------------------------------------------------*/\r
567 \r
568 static void prvDemonstrateTimerQueryFunctions( void )\r
569 {\r
570 static TimerHandle_t xTimer = NULL;\r
571 const char *pcTimerName = "TestTimer";\r
572 volatile TickType_t xExpiryTime;\r
573 const TickType_t xDontBlock = 0;\r
574 \r
575         if( xTimer == NULL )\r
576         {\r
577                 xTimer = xTimerCreate( pcTimerName, portMAX_DELAY, pdTRUE, NULL, prvTestTimerCallback );\r
578 \r
579                 if( xTimer != NULL )\r
580                 {\r
581                         /* Called from the idle task so a block time must not be\r
582                         specified. */\r
583                         xTimerStart( xTimer, xDontBlock );\r
584                 }\r
585         }\r
586 \r
587         if( xTimer != NULL )\r
588         {\r
589                 /* Demonstrate querying a timer's name. */\r
590                 configASSERT( strcmp( pcTimerGetName( xTimer ), pcTimerName ) == 0 );\r
591 \r
592                 /* Demonstrate querying a timer's period. */\r
593                 configASSERT( xTimerGetPeriod( xTimer ) == portMAX_DELAY );\r
594 \r
595                 /* Demonstrate querying a timer's next expiry time, although nothing is\r
596                 done with the returned value.  Note if the expiry time is less than the\r
597                 maximum tick count then the expiry time has overflowed from the current\r
598                 time.  In this case the expiry time was set to portMAX_DELAY, so it is\r
599                 expected to be less than the current time until the current time has\r
600                 itself overflowed. */\r
601                 xExpiryTime = xTimerGetExpiryTime( xTimer );\r
602                 ( void ) xExpiryTime;\r
603         }\r
604 }\r
605 /*-----------------------------------------------------------*/\r
606 \r
607 static void prvDemonstratePendingFunctionCall( void )\r
608 {\r
609 static uint32_t ulParameter1 = 1000UL, ulParameter2 = 0UL;\r
610 const TickType_t xDontBlock = 0; /* This is called from the idle task so must *not* attempt to block. */\r
611 \r
612         /* prvPendedFunction() just expects the parameters to be incremented by one\r
613         each time it is called. */\r
614         ulParameter1++;\r
615         ulParameter2++;\r
616 \r
617         /* Pend the function call, sending the parameters. */\r
618         xTimerPendFunctionCall( prvPendedFunction, ( void * ) ulParameter1, ulParameter2, xDontBlock );\r
619 }\r
620 /*-----------------------------------------------------------*/\r
621 \r
622 static void prvDemonstrateTaskStateAndHandleGetFunctions( void )\r
623 {\r
624 TaskHandle_t xIdleTaskHandle, xTimerTaskHandle;\r
625 char *pcTaskName;\r
626 static portBASE_TYPE xPerformedOneShotTests = pdFALSE;\r
627 TaskHandle_t xTestTask;\r
628 TaskStatus_t xTaskInfo;\r
629 extern StackType_t uxTimerTaskStack[];\r
630 static TickType_t xLastIdleExecutionTime = 0;\r
631 TickType_t xIdleExecutionTime;\r
632 \r
633         /* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and\r
634         xTaskGetIdleTaskHandle() functions.  Also try using the function that sets\r
635         the task number. */\r
636         xIdleTaskHandle = xTaskGetIdleTaskHandle();\r
637         xTimerTaskHandle = xTimerGetTimerDaemonTaskHandle();\r
638 \r
639         /* This is the idle hook, so the current task handle should equal the\r
640         returned idle task handle. */\r
641         if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle )\r
642         {\r
643                 pcStatusMessage = "Error:  Returned idle task handle was incorrect";\r
644         }\r
645 \r
646         /* Check the same handle is obtained using the idle task's name.  First try\r
647         with the wrong name, then the right name. */\r
648         if( xTaskGetHandle( "Idle" ) == xIdleTaskHandle )\r
649         {\r
650                 pcStatusMessage = "Error:  Returned handle for name Idle was incorrect";\r
651         }\r
652 \r
653         if( xTaskGetHandle( "IDLE" ) != xIdleTaskHandle )\r
654         {\r
655                 pcStatusMessage = "Error:  Returned handle for name Idle was incorrect";\r
656         }\r
657 \r
658         /* Check the timer task handle was returned correctly. */\r
659         pcTaskName = pcTaskGetName( xTimerTaskHandle );\r
660         if( strcmp( pcTaskName, "Tmr Svc" ) != 0 )\r
661         {\r
662                 pcStatusMessage = "Error:  Returned timer task handle was incorrect";\r
663         }\r
664 \r
665         if( xTaskGetHandle( "Tmr Svc" ) != xTimerTaskHandle )\r
666         {\r
667                 pcStatusMessage = "Error:  Returned handle for name Tmr Svc was incorrect";\r
668         }\r
669 \r
670         /* This task is running, make sure it's state is returned as running. */\r
671         if( eTaskStateGet( xIdleTaskHandle ) != eRunning )\r
672         {\r
673                 pcStatusMessage = "Error:  Returned idle task state was incorrect";\r
674         }\r
675 \r
676         /* If this task is running, then the timer task must be blocked. */\r
677         if( eTaskStateGet( xTimerTaskHandle ) != eBlocked )\r
678         {\r
679                 pcStatusMessage = "Error:  Returned timer task state was incorrect";\r
680         }\r
681 \r
682         /* Also with the vTaskGetInfo() function. */\r
683         vTaskGetInfo( xTimerTaskHandle, /* The task being queried. */\r
684                                           &xTaskInfo,           /* The structure into which information on the task will be written. */\r
685                                           pdTRUE,                       /* Include the task's high watermark in the structure. */\r
686                                           eInvalid );           /* Include the task state in the structure. */\r
687 \r
688         /* Check the information returned by vTaskGetInfo() is as expected. */\r
689         if( ( xTaskInfo.eCurrentState != eBlocked )                                              ||\r
690                 ( strcmp( xTaskInfo.pcTaskName, "Tmr Svc" ) != 0 )                       ||\r
691                 ( xTaskInfo.uxCurrentPriority != configTIMER_TASK_PRIORITY ) ||\r
692                 ( xTaskInfo.pxStackBase != uxTimerTaskStack )                            ||\r
693                 ( xTaskInfo.xHandle != xTimerTaskHandle ) )\r
694         {\r
695                 pcStatusMessage = "Error:  vTaskGetInfo() returned incorrect information about the timer task";\r
696         }\r
697 \r
698         /* Other tests that should only be performed once follow.  The test task\r
699         is not created on each iteration because to do so would cause the death\r
700         task to report an error (too many tasks running). */\r
701         if( xPerformedOneShotTests == pdFALSE )\r
702         {\r
703                 /* Don't run this part of the test again. */\r
704                 xPerformedOneShotTests = pdTRUE;\r
705 \r
706                 /* Create a test task to use to test other eTaskStateGet() return values. */\r
707                 if( xTaskCreate( prvTestTask, "Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTestTask ) == pdPASS )\r
708                 {\r
709                         /* If this task is running, the test task must be in the ready state. */\r
710                         if( eTaskStateGet( xTestTask ) != eReady )\r
711                         {\r
712                                 pcStatusMessage = "Error: Returned test task state was incorrect 1";\r
713                         }\r
714 \r
715                         /* Now suspend the test task and check its state is reported correctly. */\r
716                         vTaskSuspend( xTestTask );\r
717                         if( eTaskStateGet( xTestTask ) != eSuspended )\r
718                         {\r
719                                 pcStatusMessage = "Error: Returned test task state was incorrect 2";\r
720                         }\r
721 \r
722                         /* Now delete the task and check its state is reported correctly. */\r
723                         vTaskDelete( xTestTask );\r
724                         if( eTaskStateGet( xTestTask ) != eDeleted )\r
725                         {\r
726                                 pcStatusMessage = "Error: Returned test task state was incorrect 3";\r
727                         }\r
728                 }\r
729         }\r
730 \r
731         xIdleExecutionTime = xTaskGetIdleRunTimeCounter();\r
732         if( xIdleExecutionTime == xLastIdleExecutionTime )\r
733         {\r
734                 pcStatusMessage = "Error: Total amount of Idle task execution time did not change";\r
735         }\r
736         xLastIdleExecutionTime = xIdleExecutionTime;\r
737 }\r
738 /*-----------------------------------------------------------*/\r
739 \r
740 static void prvDemoQueueSpaceFunctions( void *pvParameters )\r
741 {\r
742 QueueHandle_t xQueue = NULL;\r
743 const unsigned portBASE_TYPE uxQueueLength = 10;\r
744 unsigned portBASE_TYPE uxReturn, x;\r
745 \r
746         /* Remove compiler warnings. */\r
747         ( void ) pvParameters;\r
748 \r
749         /* Create the queue that will be used.  Nothing is actually going to be\r
750         sent or received so the queue item size is set to 0. */\r
751         xQueue = xQueueCreate( uxQueueLength, 0 );\r
752         configASSERT( xQueue );\r
753 \r
754         for( ;; )\r
755         {\r
756                 for( x = 0; x < uxQueueLength; x++ )\r
757                 {\r
758                         /* Ask how many messages are available... */\r
759                         uxReturn = uxQueueMessagesWaiting( xQueue );\r
760 \r
761                         /* Check the number of messages being reported as being available\r
762                         is as expected, and force an assert if not. */\r
763                         if( uxReturn != x )\r
764                         {\r
765                                 /* xQueue cannot be NULL so this is deliberately causing an\r
766                                 assert to be triggered as there is an error. */\r
767                                 configASSERT( xQueue == NULL );\r
768                         }\r
769 \r
770                         /* Ask how many spaces remain in the queue... */\r
771                         uxReturn = uxQueueSpacesAvailable( xQueue );\r
772 \r
773                         /* Check the number of spaces being reported as being available\r
774                         is as expected, and force an assert if not. */\r
775                         if( uxReturn != ( uxQueueLength - x ) )\r
776                         {\r
777                                 /* xQueue cannot be NULL so this is deliberately causing an\r
778                                 assert to be triggered as there is an error. */\r
779                                 configASSERT( xQueue == NULL );\r
780                         }\r
781 \r
782                         /* Fill one more space in the queue. */\r
783                         xQueueSendToBack( xQueue, NULL, 0 );\r
784                 }\r
785 \r
786                 /* Perform the same check while the queue is full. */\r
787                 uxReturn = uxQueueMessagesWaiting( xQueue );\r
788                 if( uxReturn != uxQueueLength )\r
789                 {\r
790                         configASSERT( xQueue == NULL );\r
791                 }\r
792 \r
793                 uxReturn = uxQueueSpacesAvailable( xQueue );\r
794 \r
795                 if( uxReturn != 0 )\r
796                 {\r
797                         configASSERT( xQueue == NULL );\r
798                 }\r
799 \r
800                 /* The queue is full, start again. */\r
801                 xQueueReset( xQueue );\r
802 \r
803                 #if( configUSE_PREEMPTION == 0 )\r
804                         taskYIELD();\r
805                 #endif\r
806         }\r
807 }\r
808 /*-----------------------------------------------------------*/\r
809 \r
810 static void prvPermanentlyBlockingSemaphoreTask( void *pvParameters )\r
811 {\r
812 SemaphoreHandle_t xSemaphore;\r
813 \r
814         /* Prevent compiler warning about unused parameter in the case that\r
815         configASSERT() is not defined. */\r
816         ( void ) pvParameters;\r
817 \r
818         /* This task should block on a semaphore, and never return. */\r
819         xSemaphore = xSemaphoreCreateBinary();\r
820         configASSERT( xSemaphore );\r
821 \r
822         xSemaphoreTake( xSemaphore, portMAX_DELAY );\r
823 \r
824         /* The above xSemaphoreTake() call should never return, force an assert if\r
825         it does. */\r
826         configASSERT( pvParameters != NULL );\r
827         vTaskDelete( NULL );\r
828 }\r
829 /*-----------------------------------------------------------*/\r
830 \r
831 static void prvPermanentlyBlockingNotificationTask( void *pvParameters )\r
832 {\r
833         /* Prevent compiler warning about unused parameter in the case that\r
834         configASSERT() is not defined. */\r
835         ( void ) pvParameters;\r
836 \r
837         /* This task should block on a task notification, and never return. */\r
838         ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
839 \r
840         /* The above ulTaskNotifyTake() call should never return, force an assert\r
841         if it does. */\r
842         configASSERT( pvParameters != NULL );\r
843         vTaskDelete( NULL );\r
844 }\r
845 /*-----------------------------------------------------------*/\r
846 \r
847 static void prvReloadModeTestTimerCallback( TimerHandle_t xTimer )\r
848 {\r
849 uint32_t ulTimerID;\r
850 \r
851         /* Increment the timer's ID to show the callback has executed. */\r
852         ulTimerID = ( uint32_t ) pvTimerGetTimerID( xTimer );\r
853         ulTimerID++;\r
854         vTimerSetTimerID( xTimer, ( void * ) ulTimerID );\r
855 }\r
856 /*-----------------------------------------------------------*/\r
857 \r
858 static void prvDemonstrateChangingTimerReloadMode( void *pvParameters )\r
859 {\r
860 TimerHandle_t xTimer;\r
861 const char * const pcTimerName = "TestTimer";\r
862 const TickType_t x100ms = pdMS_TO_TICKS( 100UL );\r
863 \r
864         /* Avoid compiler warnings about unused parameter. */\r
865         ( void ) pvParameters;\r
866 \r
867         xTimer = xTimerCreate(  pcTimerName,\r
868                                                         x100ms,\r
869                                                         pdFALSE, /* Created as a one shot timer. */\r
870                                                         0,\r
871                                                         prvReloadModeTestTimerCallback );\r
872         configASSERT( xTimer );\r
873         configASSERT( xTimerIsTimerActive( xTimer ) == pdFALSE );\r
874         configASSERT( xTimerGetTimerDaemonTaskHandle() != NULL );\r
875         configASSERT( strcmp( pcTimerName, pcTimerGetName( xTimer ) ) == 0 );\r
876         configASSERT( xTimerGetPeriod( xTimer ) == x100ms );\r
877 \r
878         /* Timer was created as a one shot timer.  Its callback just increments the\r
879         timer's ID - so set the ID to 0, let the timer run for a number of timeout\r
880         periods, then check the timer has only executed once. */\r
881         vTimerSetTimerID( xTimer, ( void * ) 0 );\r
882         xTimerStart( xTimer, portMAX_DELAY );\r
883         vTaskDelay( 3UL * x100ms );\r
884         configASSERT( ( ( uint32_t ) ( pvTimerGetTimerID( xTimer ) ) ) == 1UL );\r
885 \r
886         /* Now change the timer to be an autoreload timer and check it executes\r
887         the expected number of times. */\r
888         vTimerSetReloadMode( xTimer, pdTRUE );\r
889         vTimerSetTimerID( xTimer, ( void * ) 0 );\r
890         xTimerStart( xTimer, 0 );\r
891         vTaskDelay( ( 3UL * x100ms ) + ( x100ms / 2UL ) ); /* Three full periods. */\r
892         configASSERT( ( uint32_t ) ( pvTimerGetTimerID( xTimer ) ) == 3UL );\r
893         configASSERT( xTimerStop( xTimer, 0 ) != pdFAIL );\r
894 \r
895         /* Now change the timer back to be a one shot timer and check it only\r
896         executes once. */\r
897         vTimerSetReloadMode( xTimer, pdFALSE );\r
898         vTimerSetTimerID( xTimer, ( void * ) 0 );\r
899         xTimerStart( xTimer, 0 );\r
900         vTaskDelay( 3UL * x100ms );\r
901         configASSERT( xTimerStop( xTimer, 0 ) != pdFAIL );\r
902         configASSERT( ( uint32_t ) ( pvTimerGetTimerID( xTimer ) ) == 1UL );\r
903 \r
904         /* Clean up at the end. */\r
905         xTimerDelete( xTimer, portMAX_DELAY );\r
906         vTaskDelete( NULL );\r
907 }\r