]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/WIN32-MingW/main_full.c
Fix buffer clean up in \FreeRTOS_Plus_TCP_Minimal_Windows_Simulator\demo_logging.c.
[freertos] / FreeRTOS / Demo / WIN32-MingW / main_full.c
1 /*\r
2  * FreeRTOS Kernel V10.0.1\r
3  * Copyright (C) 2017 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  * basic 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 "blocktim.h"\r
102 #include "AbortDelay.h"\r
103 #include "MessageBufferDemo.h"\r
104 #include "StreamBufferDemo.h"\r
105 #include "StreamBufferInterrupt.h"\r
106 #include "MessageBufferAMP.h"\r
107 \r
108 /* Priorities at which the tasks are created. */\r
109 #define mainCHECK_TASK_PRIORITY                 ( configMAX_PRIORITIES - 2 )\r
110 #define mainQUEUE_POLL_PRIORITY                 ( tskIDLE_PRIORITY + 1 )\r
111 #define mainSEM_TEST_PRIORITY                   ( tskIDLE_PRIORITY + 1 )\r
112 #define mainBLOCK_Q_PRIORITY                    ( tskIDLE_PRIORITY + 2 )\r
113 #define mainCREATOR_TASK_PRIORITY               ( tskIDLE_PRIORITY + 3 )\r
114 #define mainFLASH_TASK_PRIORITY                 ( tskIDLE_PRIORITY + 1 )\r
115 #define mainINTEGER_TASK_PRIORITY               ( tskIDLE_PRIORITY )\r
116 #define mainGEN_QUEUE_TASK_PRIORITY             ( tskIDLE_PRIORITY )\r
117 #define mainFLOP_TASK_PRIORITY                  ( tskIDLE_PRIORITY )\r
118 #define mainQUEUE_OVERWRITE_PRIORITY    ( tskIDLE_PRIORITY )\r
119 \r
120 #define mainTIMER_TEST_PERIOD                   ( 50 )\r
121 \r
122 /* Task function prototypes. */\r
123 static void prvCheckTask( void *pvParameters );\r
124 \r
125 /* A task that is created from the idle task to test the functionality of\r
126 eTaskStateGet(). */\r
127 static void prvTestTask( void *pvParameters );\r
128 \r
129 /*\r
130  * Called from the idle task hook function to demonstrate a few utility\r
131  * functions that are not demonstrated by any of the standard demo tasks.\r
132  */\r
133 static void prvDemonstrateTaskStateAndHandleGetFunctions( void );\r
134 \r
135 /*\r
136  * Called from the idle task hook function to demonstrate the use of\r
137  * xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by\r
138  * any of the standard demo tasks.\r
139  */\r
140 static void prvDemonstratePendingFunctionCall( void );\r
141 \r
142 /*\r
143  * The function that is pended by prvDemonstratePendingFunctionCall().\r
144  */\r
145 static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 );\r
146 \r
147 /*\r
148  * prvDemonstrateTimerQueryFunctions() is called from the idle task hook\r
149  * function to demonstrate the use of functions that query information about a\r
150  * software timer.  prvTestTimerCallback() is the callback function for the\r
151  * timer being queried.\r
152  */\r
153 static void prvDemonstrateTimerQueryFunctions( void );\r
154 static void prvTestTimerCallback( TimerHandle_t xTimer );\r
155 \r
156 /*\r
157  * A task to demonstrate the use of the xQueueSpacesAvailable() function.\r
158  */\r
159 static void prvDemoQueueSpaceFunctions( void *pvParameters );\r
160 \r
161 /*\r
162  * Tasks that ensure indefinite delays are truly indefinite.\r
163  */\r
164 static void prvPermanentlyBlockingSemaphoreTask( void *pvParameters );\r
165 static void prvPermanentlyBlockingNotificationTask( void *pvParameters );\r
166 \r
167 /*-----------------------------------------------------------*/\r
168 \r
169 /* The variable into which error messages are latched. */\r
170 static char *pcStatusMessage = "No errors";\r
171 \r
172 /* This semaphore is created purely to test using the vSemaphoreDelete() and\r
173 semaphore tracing API functions.  It has no other purpose. */\r
174 static SemaphoreHandle_t xMutexToDelete = NULL;\r
175 \r
176 /*-----------------------------------------------------------*/\r
177 \r
178 int main_full( void )\r
179 {\r
180         /* Start the check task as described at the top of this file. */\r
181         xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
182 \r
183         /* Create the standard demo tasks. */\r
184         vStartTaskNotifyTask();\r
185         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
186         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
187         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
188         vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
189         vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
190         vStartQueuePeekTasks();\r
191         vStartMathTasks( mainFLOP_TASK_PRIORITY );\r
192         vStartRecursiveMutexTasks();\r
193         vStartCountingSemaphoreTasks();\r
194         vStartDynamicPriorityTasks();\r
195         vStartQueueSetTasks();\r
196         vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );\r
197         xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
198         vStartEventGroupTasks();\r
199         vStartInterruptSemaphoreTasks();\r
200         vStartQueueSetPollingTask();\r
201         vCreateBlockTimeTasks();\r
202         vCreateAbortDelayTasks();\r
203         xTaskCreate( prvDemoQueueSpaceFunctions, "QSpace", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
204         xTaskCreate( prvPermanentlyBlockingSemaphoreTask, "BlockSem", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
205         xTaskCreate( prvPermanentlyBlockingNotificationTask, "BlockNoti", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
206 \r
207         vStartMessageBufferTasks();\r
208         vStartStreamBufferTasks();\r
209         vStartStreamBufferInterruptDemo();\r
210         vStartMessageBufferAMPTasks();\r
211 \r
212         #if( configUSE_PREEMPTION != 0  )\r
213         {\r
214                 /* Don't expect these tasks to pass when preemption is not used. */\r
215                 vStartTimerDemoTask( mainTIMER_TEST_PERIOD );\r
216         }\r
217         #endif\r
218 \r
219         /* The suicide tasks must be created last as they need to know how many\r
220         tasks were running prior to their creation.  This then allows them to\r
221         ascertain whether or not the correct/expected number of tasks are running at\r
222         any given time. */\r
223         vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );\r
224 \r
225         /* Create the semaphore that will be deleted in the idle task hook.  This\r
226         is done purely to test the use of vSemaphoreDelete(). */\r
227         xMutexToDelete = xSemaphoreCreateMutex();\r
228 \r
229         /* Start the scheduler itself. */\r
230         vTaskStartScheduler();\r
231 \r
232         /* Should never get here unless there was not enough heap space to create\r
233         the idle and other system tasks. */\r
234         return 0;\r
235 }\r
236 /*-----------------------------------------------------------*/\r
237 \r
238 static void prvCheckTask( void *pvParameters )\r
239 {\r
240 TickType_t xNextWakeTime;\r
241 const TickType_t xCycleFrequency = pdMS_TO_TICKS( 2500UL );\r
242 \r
243         /* Just to remove compiler warning. */\r
244         ( void ) pvParameters;\r
245 \r
246         /* Initialise xNextWakeTime - this only needs to be done once. */\r
247         xNextWakeTime = xTaskGetTickCount();\r
248 \r
249         for( ;; )\r
250         {\r
251                 /* Place this task in the blocked state until it is time to run again. */\r
252                 vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );\r
253 \r
254                 /* Check the standard demo tasks are running without error. */\r
255                 #if( configUSE_PREEMPTION != 0 )\r
256                 {\r
257                         /* These tasks are only created when preemption is used. */\r
258                         if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE )\r
259                         {\r
260                                 pcStatusMessage = "Error: TimerDemo";\r
261                         }\r
262                 }\r
263                 #endif\r
264 \r
265                 if( xAreStreamBufferTasksStillRunning() != pdTRUE )\r
266                 {\r
267                         pcStatusMessage = "Error:  StreamBuffer";\r
268                 }\r
269                 else if( xAreMessageBufferTasksStillRunning() != pdTRUE )\r
270                 {\r
271                         pcStatusMessage = "Error:  MessageBuffer";\r
272                 }\r
273                 else if( xAreTaskNotificationTasksStillRunning() != pdTRUE )\r
274                 {\r
275                         pcStatusMessage = "Error:  Notification";\r
276                 }\r
277                 else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )\r
278                 {\r
279                         pcStatusMessage = "Error: IntSem";\r
280                 }\r
281                 else if( xAreEventGroupTasksStillRunning() != pdTRUE )\r
282                 {\r
283                         pcStatusMessage = "Error: EventGroup";\r
284                 }\r
285                 else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
286                 {\r
287                         pcStatusMessage = "Error: IntMath";\r
288                 }\r
289                 else if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
290                 {\r
291                         pcStatusMessage = "Error: GenQueue";\r
292                 }\r
293                 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
294                 {\r
295                         pcStatusMessage = "Error: QueuePeek";\r
296                 }\r
297                 else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
298                 {\r
299                         pcStatusMessage = "Error: BlockQueue";\r
300                 }\r
301                 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
302                 {\r
303                         pcStatusMessage = "Error: SemTest";\r
304                 }\r
305                 else if( xArePollingQueuesStillRunning() != pdTRUE )\r
306                 {\r
307                         pcStatusMessage = "Error: PollQueue";\r
308                 }\r
309                 else if( xAreMathsTaskStillRunning() != pdPASS )\r
310                 {\r
311                         pcStatusMessage = "Error: Flop";\r
312                 }\r
313                 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
314                 {\r
315                         pcStatusMessage = "Error: RecMutex";\r
316                 }\r
317                 else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )\r
318                 {\r
319                         pcStatusMessage = "Error: CountSem";\r
320                 }\r
321                 else if( xIsCreateTaskStillRunning() != pdTRUE )\r
322                 {\r
323                         pcStatusMessage = "Error: Death";\r
324                 }\r
325                 else if( xAreDynamicPriorityTasksStillRunning() != pdPASS )\r
326                 {\r
327                         pcStatusMessage = "Error: Dynamic";\r
328                 }\r
329                 else if( xAreQueueSetTasksStillRunning() != pdPASS )\r
330                 {\r
331                         pcStatusMessage = "Error: Queue set";\r
332                 }\r
333                 else if( xIsQueueOverwriteTaskStillRunning() != pdPASS )\r
334                 {\r
335                         pcStatusMessage = "Error: Queue overwrite";\r
336                 }\r
337                 else if( xAreQueueSetPollTasksStillRunning() != pdPASS )\r
338                 {\r
339                         pcStatusMessage = "Error: Queue set polling";\r
340                 }\r
341                 else if( xAreBlockTimeTestTasksStillRunning() != pdPASS )\r
342                 {\r
343                         pcStatusMessage = "Error: Block time";\r
344                 }\r
345                 else if( xAreAbortDelayTestTasksStillRunning() != pdPASS )\r
346                 {\r
347                         pcStatusMessage = "Error: Abort delay";\r
348                 }\r
349                 else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS )\r
350                 {\r
351                         pcStatusMessage = "Error: Stream buffer interrupt";\r
352                 }\r
353                 else if( xAreMessageBufferAMPTasksStillRunning() != pdPASS )\r
354                 {\r
355                         pcStatusMessage = "Error: Message buffer AMP";\r
356                 }\r
357 \r
358                 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
359                         else if( xAreStaticAllocationTasksStillRunning() != pdPASS )\r
360                         {\r
361                                 pcStatusMessage = "Error: Static allocation";\r
362                         }\r
363                 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
364 \r
365                 /* This is the only task that uses stdout so its ok to call printf()\r
366                 directly. */\r
367                 printf( "%s - tick count %u - free heap %u - min free heap %u\r\n", pcStatusMessage,\r
368                                                                                                                                                            xTaskGetTickCount(),\r
369                                                                                                                                                            xPortGetFreeHeapSize(),\r
370                                                                                                                                                            xPortGetMinimumEverFreeHeapSize() );\r
371                 fflush( stdout );\r
372         }\r
373 }\r
374 /*-----------------------------------------------------------*/\r
375 \r
376 static void prvTestTask( void *pvParameters )\r
377 {\r
378 const unsigned long ulMSToSleep = 5;\r
379 \r
380         /* Just to remove compiler warnings. */\r
381         ( void ) pvParameters;\r
382 \r
383         /* This task is just used to test the eTaskStateGet() function.  It\r
384         does not have anything to do. */\r
385         for( ;; )\r
386         {\r
387                 /* Sleep to reduce CPU load, but don't sleep indefinitely in case there are\r
388                 tasks waiting to be terminated by the idle task. */\r
389                 Sleep( ulMSToSleep );\r
390         }\r
391 }\r
392 /*-----------------------------------------------------------*/\r
393 \r
394 /* Called from vApplicationIdleHook(), which is defined in main.c. */\r
395 void vFullDemoIdleFunction( void )\r
396 {\r
397 const unsigned long ulMSToSleep = 15;\r
398 void *pvAllocated;\r
399 \r
400         /* Sleep to reduce CPU load, but don't sleep indefinitely in case there are\r
401         tasks waiting to be terminated by the idle task. */\r
402         Sleep( ulMSToSleep );\r
403 \r
404         /* Demonstrate a few utility functions that are not demonstrated by any of\r
405         the standard demo tasks. */\r
406         prvDemonstrateTaskStateAndHandleGetFunctions();\r
407 \r
408         /* Demonstrate the use of xTimerPendFunctionCall(), which is not\r
409         demonstrated by any of the standard demo tasks. */\r
410         prvDemonstratePendingFunctionCall();\r
411 \r
412         /* Demonstrate the use of functions that query information about a software\r
413         timer. */\r
414         prvDemonstrateTimerQueryFunctions();\r
415 \r
416 \r
417         /* If xMutexToDelete has not already been deleted, then delete it now.\r
418         This is done purely to demonstrate the use of, and test, the\r
419         vSemaphoreDelete() macro.  Care must be taken not to delete a semaphore\r
420         that has tasks blocked on it. */\r
421         if( xMutexToDelete != NULL )\r
422         {\r
423                 /* For test purposes, add the mutex to the registry, then remove it\r
424                 again, before it is deleted - checking its name is as expected before\r
425                 and after the assertion into the registry and its removal from the\r
426                 registry. */\r
427                 configASSERT( pcQueueGetName( xMutexToDelete ) == NULL );\r
428                 vQueueAddToRegistry( xMutexToDelete, "Test_Mutex" );\r
429                 configASSERT( strcmp( pcQueueGetName( xMutexToDelete ), "Test_Mutex" ) == 0 );\r
430                 vQueueUnregisterQueue( xMutexToDelete );\r
431                 configASSERT( pcQueueGetName( xMutexToDelete ) == NULL );\r
432 \r
433                 vSemaphoreDelete( xMutexToDelete );\r
434                 xMutexToDelete = NULL;\r
435         }\r
436 \r
437         /* Exercise heap_5 a bit.  The malloc failed hook will trap failed\r
438         allocations so there is no need to test here. */\r
439         pvAllocated = pvPortMalloc( ( rand() % 500 ) + 1 );\r
440         vPortFree( pvAllocated );\r
441 }\r
442 /*-----------------------------------------------------------*/\r
443 \r
444 /* Called by vApplicationTickHook(), which is defined in main.c. */\r
445 void vFullDemoTickHookFunction( void )\r
446 {\r
447 TaskHandle_t xTimerTask;\r
448 \r
449         /* Call the periodic timer test, which tests the timer API functions that\r
450         can be called from an ISR. */\r
451         #if( configUSE_PREEMPTION != 0 )\r
452         {\r
453                 /* Only created when preemption is used. */\r
454                 vTimerPeriodicISRTests();\r
455         }\r
456         #endif\r
457 \r
458         /* Call the periodic queue overwrite from ISR demo. */\r
459         vQueueOverwritePeriodicISRDemo();\r
460 \r
461         /* Write to a queue that is in use as part of the queue set demo to\r
462         demonstrate using queue sets from an ISR. */\r
463         vQueueSetAccessQueueSetFromISR();\r
464         vQueueSetPollingInterruptAccess();\r
465 \r
466         /* Exercise event groups from interrupts. */\r
467         vPeriodicEventGroupsProcessing();\r
468 \r
469         /* Exercise giving mutexes from an interrupt. */\r
470         vInterruptSemaphorePeriodicTest();\r
471 \r
472         /* Exercise using task notifications from an interrupt. */\r
473         xNotifyTaskFromISR();\r
474 \r
475         /* Writes to stream buffer byte by byte to test the stream buffer trigger\r
476         level functionality. */\r
477         vPeriodicStreamBufferProcessing();\r
478 \r
479         /* Writes a string to a string buffer four bytes at a time to demonstrate\r
480         a stream being sent from an interrupt to a task. */\r
481         vBasicStreamBufferSendFromISR();\r
482 \r
483         /* For code coverage purposes. */\r
484         xTimerTask = xTimerGetTimerDaemonTaskHandle();\r
485         configASSERT( uxTaskPriorityGetFromISR( xTimerTask ) == configTIMER_TASK_PRIORITY );\r
486         ( void ) xTimerTask; /* In case configASSERT() is not defined. */\r
487 }\r
488 /*-----------------------------------------------------------*/\r
489 \r
490 static void prvPendedFunction( void *pvParameter1, uint32_t ulParameter2 )\r
491 {\r
492 static uint32_t ulLastParameter1 = 1000UL, ulLastParameter2 = 0UL;\r
493 uint32_t ulParameter1;\r
494 \r
495         ulParameter1 = ( uint32_t ) pvParameter1;\r
496 \r
497         /* Ensure the parameters are as expected. */\r
498         configASSERT( ulParameter1 == ( ulLastParameter1 + 1 ) );\r
499         configASSERT( ulParameter2 == ( ulLastParameter2 + 1 ) );\r
500 \r
501         /* Remember the parameters for the next time the function is called. */\r
502         ulLastParameter1 = ulParameter1;\r
503         ulLastParameter2 = ulParameter2;\r
504 \r
505         /* Remove compiler warnings in case configASSERT() is not defined. */\r
506         ( void ) ulLastParameter1;\r
507         ( void ) ulLastParameter2;\r
508 }\r
509 /*-----------------------------------------------------------*/\r
510 \r
511 static void prvTestTimerCallback( TimerHandle_t xTimer )\r
512 {\r
513         /* This is the callback function for the timer accessed by\r
514         prvDemonstrateTimerQueryFunctions().  The callback does not do anything. */\r
515         ( void ) xTimer;\r
516 }\r
517 /*-----------------------------------------------------------*/\r
518 \r
519 static void prvDemonstrateTimerQueryFunctions( void )\r
520 {\r
521 static TimerHandle_t xTimer = NULL;\r
522 const char *pcTimerName = "TestTimer";\r
523 volatile TickType_t xExpiryTime;\r
524 const TickType_t xDontBlock = 0;\r
525 \r
526         if( xTimer == NULL )\r
527         {\r
528                 xTimer = xTimerCreate( pcTimerName, portMAX_DELAY, pdTRUE, NULL, prvTestTimerCallback );\r
529 \r
530                 if( xTimer != NULL )\r
531                 {\r
532                         /* Called from the idle task so a block time must not be\r
533                         specified. */\r
534                         xTimerStart( xTimer, xDontBlock );\r
535                 }\r
536         }\r
537 \r
538         if( xTimer != NULL )\r
539         {\r
540                 /* Demonstrate querying a timer's name. */\r
541                 configASSERT( strcmp( pcTimerGetName( xTimer ), pcTimerName ) == 0 );\r
542 \r
543                 /* Demonstrate querying a timer's period. */\r
544                 configASSERT( xTimerGetPeriod( xTimer ) == portMAX_DELAY );\r
545 \r
546                 /* Demonstrate querying a timer's next expiry time, although nothing is\r
547                 done with the returned value.  Note if the expiry time is less than the\r
548                 maximum tick count then the expiry time has overflowed from the current\r
549                 time.  In this case the expiry time was set to portMAX_DELAY, so it is\r
550                 expected to be less than the current time until the current time has\r
551                 itself overflowed. */\r
552                 xExpiryTime = xTimerGetExpiryTime( xTimer );\r
553                 ( void ) xExpiryTime;\r
554         }\r
555 }\r
556 /*-----------------------------------------------------------*/\r
557 \r
558 static void prvDemonstratePendingFunctionCall( void )\r
559 {\r
560 static uint32_t ulParameter1 = 1000UL, ulParameter2 = 0UL;\r
561 const TickType_t xDontBlock = 0; /* This is called from the idle task so must *not* attempt to block. */\r
562 \r
563         /* prvPendedFunction() just expects the parameters to be incremented by one\r
564         each time it is called. */\r
565         ulParameter1++;\r
566         ulParameter2++;\r
567 \r
568         /* Pend the function call, sending the parameters. */\r
569         xTimerPendFunctionCall( prvPendedFunction, ( void * ) ulParameter1, ulParameter2, xDontBlock );\r
570 }\r
571 /*-----------------------------------------------------------*/\r
572 \r
573 static void prvDemonstrateTaskStateAndHandleGetFunctions( void )\r
574 {\r
575 TaskHandle_t xIdleTaskHandle, xTimerTaskHandle;\r
576 char *pcTaskName;\r
577 static portBASE_TYPE xPerformedOneShotTests = pdFALSE;\r
578 TaskHandle_t xTestTask;\r
579 TaskStatus_t xTaskInfo;\r
580 \r
581         /* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and\r
582         xTaskGetIdleTaskHandle() functions.  Also try using the function that sets\r
583         the task number. */\r
584         xIdleTaskHandle = xTaskGetIdleTaskHandle();\r
585         xTimerTaskHandle = xTimerGetTimerDaemonTaskHandle();\r
586 \r
587         /* This is the idle hook, so the current task handle should equal the\r
588         returned idle task handle. */\r
589         if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle )\r
590         {\r
591                 pcStatusMessage = "Error:  Returned idle task handle was incorrect";\r
592         }\r
593 \r
594         /* Check the same handle is obtained using the idle task's name.  First try\r
595         with the wrong name, then the right name. */\r
596         if( xTaskGetHandle( "Idle" ) == xIdleTaskHandle )\r
597         {\r
598                 pcStatusMessage = "Error:  Returned handle for name Idle was incorrect";\r
599         }\r
600 \r
601         if( xTaskGetHandle( "IDLE" ) != xIdleTaskHandle )\r
602         {\r
603                 pcStatusMessage = "Error:  Returned handle for name Idle was incorrect";\r
604         }\r
605 \r
606         /* Check the timer task handle was returned correctly. */\r
607         pcTaskName = pcTaskGetName( xTimerTaskHandle );\r
608         if( strcmp( pcTaskName, "Tmr Svc" ) != 0 )\r
609         {\r
610                 pcStatusMessage = "Error:  Returned timer task handle was incorrect";\r
611         }\r
612 \r
613         if( xTaskGetHandle( "Tmr Svc" ) != xTimerTaskHandle )\r
614         {\r
615                 pcStatusMessage = "Error:  Returned handle for name Tmr Svc was incorrect";\r
616         }\r
617 \r
618         /* This task is running, make sure it's state is returned as running. */\r
619         if( eTaskStateGet( xIdleTaskHandle ) != eRunning )\r
620         {\r
621                 pcStatusMessage = "Error:  Returned idle task state was incorrect";\r
622         }\r
623 \r
624         /* If this task is running, then the timer task must be blocked. */\r
625         if( eTaskStateGet( xTimerTaskHandle ) != eBlocked )\r
626         {\r
627                 pcStatusMessage = "Error:  Returned timer task state was incorrect";\r
628         }\r
629 \r
630         /* Also with the vTaskGetInfo() function. */\r
631         vTaskGetInfo( xTimerTaskHandle, /* The task being queried. */\r
632                                           &xTaskInfo,           /* The structure into which information on the task will be written. */\r
633                                           pdTRUE,                       /* Include the task's high watermark in the structure. */\r
634                                           eInvalid );           /* Include the task state in the structure. */\r
635 \r
636         /* Check the information returned by vTaskGetInfo() is as expected. */\r
637         if( ( xTaskInfo.eCurrentState != eBlocked )                                              ||\r
638                 ( strcmp( xTaskInfo.pcTaskName, "Tmr Svc" ) != 0 )                       ||\r
639                 ( xTaskInfo.uxCurrentPriority != configTIMER_TASK_PRIORITY ) ||\r
640                 ( xTaskInfo.xHandle != xTimerTaskHandle ) )\r
641         {\r
642                 pcStatusMessage = "Error:  vTaskGetInfo() returned incorrect information about the timer task";\r
643         }\r
644 \r
645         /* Other tests that should only be performed once follow.  The test task\r
646         is not created on each iteration because to do so would cause the death\r
647         task to report an error (too many tasks running). */\r
648         if( xPerformedOneShotTests == pdFALSE )\r
649         {\r
650                 /* Don't run this part of the test again. */\r
651                 xPerformedOneShotTests = pdTRUE;\r
652 \r
653                 /* Create a test task to use to test other eTaskStateGet() return values. */\r
654                 if( xTaskCreate( prvTestTask, "Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTestTask ) == pdPASS )\r
655                 {\r
656                         /* If this task is running, the test task must be in the ready state. */\r
657                         if( eTaskStateGet( xTestTask ) != eReady )\r
658                         {\r
659                                 pcStatusMessage = "Error: Returned test task state was incorrect 1";\r
660                         }\r
661 \r
662                         /* Now suspend the test task and check its state is reported correctly. */\r
663                         vTaskSuspend( xTestTask );\r
664                         if( eTaskStateGet( xTestTask ) != eSuspended )\r
665                         {\r
666                                 pcStatusMessage = "Error: Returned test task state was incorrect 2";\r
667                         }\r
668 \r
669                         /* Now delete the task and check its state is reported correctly. */\r
670                         vTaskDelete( xTestTask );\r
671                         if( eTaskStateGet( xTestTask ) != eDeleted )\r
672                         {\r
673                                 pcStatusMessage = "Error: Returned test task state was incorrect 3";\r
674                         }\r
675                 }\r
676         }\r
677 }\r
678 /*-----------------------------------------------------------*/\r
679 \r
680 static void prvDemoQueueSpaceFunctions( void *pvParameters )\r
681 {\r
682 QueueHandle_t xQueue = NULL;\r
683 const unsigned portBASE_TYPE uxQueueLength = 10;\r
684 unsigned portBASE_TYPE uxReturn, x;\r
685 \r
686         /* Remove compiler warnings. */\r
687         ( void ) pvParameters;\r
688 \r
689         /* Create the queue that will be used.  Nothing is actually going to be\r
690         sent or received so the queue item size is set to 0. */\r
691         xQueue = xQueueCreate( uxQueueLength, 0 );\r
692         configASSERT( xQueue );\r
693 \r
694         for( ;; )\r
695         {\r
696                 for( x = 0; x < uxQueueLength; x++ )\r
697                 {\r
698                         /* Ask how many messages are available... */\r
699                         uxReturn = uxQueueMessagesWaiting( xQueue );\r
700 \r
701                         /* Check the number of messages being reported as being available\r
702                         is as expected, and force an assert if not. */\r
703                         if( uxReturn != x )\r
704                         {\r
705                                 /* xQueue cannot be NULL so this is deliberately causing an\r
706                                 assert to be triggered as there is an error. */\r
707                                 configASSERT( xQueue == NULL );\r
708                         }\r
709 \r
710                         /* Ask how many spaces remain in the queue... */\r
711                         uxReturn = uxQueueSpacesAvailable( xQueue );\r
712 \r
713                         /* Check the number of spaces being reported as being available\r
714                         is as expected, and force an assert if not. */\r
715                         if( uxReturn != ( uxQueueLength - x ) )\r
716                         {\r
717                                 /* xQueue cannot be NULL so this is deliberately causing an\r
718                                 assert to be triggered as there is an error. */\r
719                                 configASSERT( xQueue == NULL );\r
720                         }\r
721 \r
722                         /* Fill one more space in the queue. */\r
723                         xQueueSendToBack( xQueue, NULL, 0 );\r
724                 }\r
725 \r
726                 /* Perform the same check while the queue is full. */\r
727                 uxReturn = uxQueueMessagesWaiting( xQueue );\r
728                 if( uxReturn != uxQueueLength )\r
729                 {\r
730                         configASSERT( xQueue == NULL );\r
731                 }\r
732 \r
733                 uxReturn = uxQueueSpacesAvailable( xQueue );\r
734 \r
735                 if( uxReturn != 0 )\r
736                 {\r
737                         configASSERT( xQueue == NULL );\r
738                 }\r
739 \r
740                 /* The queue is full, start again. */\r
741                 xQueueReset( xQueue );\r
742 \r
743                 #if( configUSE_PREEMPTION == 0 )\r
744                         taskYIELD();\r
745                 #endif\r
746         }\r
747 }\r
748 /*-----------------------------------------------------------*/\r
749 \r
750 static void prvPermanentlyBlockingSemaphoreTask( void *pvParameters )\r
751 {\r
752 SemaphoreHandle_t xSemaphore;\r
753 \r
754         /* Prevent compiler warning about unused parameter in the case that\r
755         configASSERT() is not defined. */\r
756         ( void ) pvParameters;\r
757 \r
758         /* This task should block on a semaphore, and never return. */\r
759         xSemaphore = xSemaphoreCreateBinary();\r
760         configASSERT( xSemaphore );\r
761 \r
762         xSemaphoreTake( xSemaphore, portMAX_DELAY );\r
763 \r
764         /* The above xSemaphoreTake() call should never return, force an assert if\r
765         it does. */\r
766         configASSERT( pvParameters != NULL );\r
767         vTaskDelete( NULL );\r
768 }\r
769 /*-----------------------------------------------------------*/\r
770 \r
771 static void prvPermanentlyBlockingNotificationTask( void *pvParameters )\r
772 {\r
773         /* Prevent compiler warning about unused parameter in the case that\r
774         configASSERT() is not defined. */\r
775         ( void ) pvParameters;\r
776 \r
777         /* This task should block on a task notification, and never return. */\r
778         ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
779 \r
780         /* The above ulTaskNotifyTake() call should never return, force an assert\r
781         if it does. */\r
782         configASSERT( pvParameters != NULL );\r
783         vTaskDelete( NULL );\r
784 }\r
785 \r
786 \r