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