2 * FreeRTOS Kernel V10.0.1
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\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
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\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
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
29 * main() creates all the demo application tasks, then starts the scheduler.
\r
30 * The web documentation provides more details of the standard demo application
\r
31 * tasks, which provide no particular functionality but do provide a good
\r
32 * example of how to use the FreeRTOS API.
\r
34 * In addition to the standard demo tasks, the following tasks and tests are
\r
35 * defined and/or created within this file:
\r
37 * "Check" task - This only executes every five seconds but has a high priority
\r
38 * to ensure it gets processor time. Its main function is to check that all the
\r
39 * standard demo tasks are still operational. While no errors have been
\r
40 * discovered the check task will print out "OK" and the current simulated tick
\r
41 * time. If an error is discovered in the execution of a task then the check
\r
42 * task will print out an appropriate error message.
\r
47 /* Standard includes. */
\r
51 /* Kernel includes. */
\r
52 #include <FreeRTOS.h>
\r
58 /* Standard demo includes. */
\r
60 #include "integer.h"
\r
61 #include "semtest.h"
\r
63 #include "GenQTest.h"
\r
65 #include "recmutex.h"
\r
67 #include "TimerDemo.h"
\r
68 #include "countsem.h"
\r
70 #include "QueueSet.h"
\r
71 #include "QueueOverwrite.h"
\r
72 #include "EventGroupsDemo.h"
\r
73 #include "IntSemTest.h"
\r
74 #include "TaskNotify.h"
\r
75 #include "QueueSetPolling.h"
\r
76 #include "StaticAllocation.h"
\r
77 #include "blocktim.h"
\r
78 #include "AbortDelay.h"
\r
79 #include "MessageBufferDemo.h"
\r
80 #include "StreamBufferDemo.h"
\r
81 #include "StreamBufferInterrupt.h"
\r
83 /* Priorities at which the tasks are created. */
\r
84 #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
\r
85 #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
86 #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
87 #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
\r
88 #define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
\r
89 #define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
90 #define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
91 #define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
92 #define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
93 #define mainQUEUE_OVERWRITE_PRIORITY ( tskIDLE_PRIORITY )
\r
95 #define mainTIMER_TEST_PERIOD ( 50 )
\r
97 /* Parameters that are passed into the register check tasks solely for the
\r
98 purpose of ensuring parameters are passed into tasks correctly. */
\r
99 #define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 )
\r
100 #define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 )
\r
102 /* Whether or not to enable interrupt queue tests. */
\r
103 #define mainENABLE_INT_QUEUE_TESTS ( 0 )
\r
105 /* The task that periodically checks that all the standard demo tasks are
\r
106 * still executing and error free.
\r
108 static void prvCheckTask( void *pvParameters );
\r
110 /* Tasks that implement register tests. */
\r
111 static void prvRegTest1Task( void *pvParameters );
\r
112 static void prvRegTest2Task( void *pvParameters );
\r
114 /* Functions implemented in assembly file regtest_xtensa.S. */
\r
115 extern void vRegTest1( void );
\r
116 extern void vRegTest2( void );
\r
117 /*-----------------------------------------------------------*/
\r
119 /* The variable into which error messages are latched. */
\r
120 static char *pcStatusMessage = "No errors";
\r
122 /* The following two variables are used to communicate the status of the
\r
123 register check tasks to the check task. If the variables keep incrementing,
\r
124 then the register check tasks have not discovered any errors. If a variable
\r
125 stops incrementing, then an error has been found. */
\r
126 volatile unsigned long ulRegTest1Counter = 0UL, ulRegTest2Counter = 0UL;
\r
128 /* The following variable is used to communicate whether the timers for the
\r
129 IntQueue tests have been Initialized. This is needed to ensure that the queues
\r
130 are accessed from the tick hook only after they have been created in the
\r
131 interrupt queue test. */
\r
132 volatile BaseType_t xTimerForQueueTestInitialized = pdFALSE;
\r
133 /*-----------------------------------------------------------*/
\r
135 int main_full( void )
\r
137 /* Start the check task as described at the top of this file. */
\r
138 xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
\r
140 #if( mainENABLE_INT_QUEUE_TESTS == 0 )
\r
142 /* Create the standard demo tasks. */
\r
143 vStartTaskNotifyTask();
\r
144 vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
\r
145 vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
\r
146 vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
\r
147 vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
\r
148 vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
\r
150 vStartQueuePeekTasks();
\r
151 vStartMathTasks( mainFLOP_TASK_PRIORITY );
\r
152 vStartRecursiveMutexTasks();
\r
153 vStartCountingSemaphoreTasks();
\r
154 vStartQueueSetTasks();
\r
156 vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );
\r
157 vStartEventGroupTasks();
\r
158 vStartInterruptSemaphoreTasks();
\r
159 vStartQueueSetPollingTask();
\r
160 vCreateBlockTimeTasks();
\r
162 #if( configUSE_PREEMPTION != 0 )
\r
164 /* Don't expect these tasks to pass when preemption is not used. */
\r
165 vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
\r
169 vCreateAbortDelayTasks();
\r
170 vStartMessageBufferTasks( configMINIMAL_STACK_SIZE );
\r
172 vStartStreamBufferTasks();
\r
173 vStartStreamBufferInterruptDemo();
\r
175 /* Create the register check tasks, as described at the top of this file */
\r
176 xTaskCreate( prvRegTest1Task, "Reg1", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_1_PARAMETER, tskIDLE_PRIORITY, NULL );
\r
177 xTaskCreate( prvRegTest2Task, "Reg2", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );
\r
179 /* The suicide tasks must be created last as they need to know how many
\r
180 tasks were running prior to their creation. This then allows them to
\r
181 ascertain whether or not the correct/expected number of tasks are running at
\r
183 vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
\r
185 #else /* mainENABLE_INT_QUEUE_TESTS */
\r
187 /* Start interrupt queue test tasks. */
\r
188 vStartInterruptQueueTasks();
\r
190 #endif /* mainENABLE_INT_QUEUE_TESTS */
\r
192 /* Start the scheduler itself. */
\r
193 vTaskStartScheduler();
\r
195 /* Should never get here unless there was not enough heap space to create
\r
196 the idle and other system tasks. */
\r
199 /*-----------------------------------------------------------*/
\r
201 static void prvCheckTask( void *pvParameters )
\r
203 TickType_t xNextWakeTime;
\r
204 const TickType_t xCycleFrequency = pdMS_TO_TICKS( 5000UL );
\r
205 static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;
\r
207 /* Just to remove compiler warning. */
\r
208 ( void ) pvParameters;
\r
210 /* Initialise xNextWakeTime - this only needs to be done once. */
\r
211 xNextWakeTime = xTaskGetTickCount();
\r
215 /* Place this task in the blocked state until it is time to run again. */
\r
216 vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );
\r
218 #if( mainENABLE_INT_QUEUE_TESTS == 0 )
\r
220 /* Check the standard demo tasks are running without error. */
\r
221 #if( configUSE_PREEMPTION != 0 )
\r
223 /* These tasks are only created when preemption is used. */
\r
224 if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE )
\r
226 pcStatusMessage = "Error: TimerDemo";
\r
231 if( xAreTaskNotificationTasksStillRunning() != pdTRUE )
\r
233 pcStatusMessage = "Error: Notification";
\r
235 else if( xAreBlockingQueuesStillRunning() != pdTRUE )
\r
237 pcStatusMessage = "Error: BlockQueue";
\r
239 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
\r
241 pcStatusMessage = "Error: SemTest";
\r
243 else if( xArePollingQueuesStillRunning() != pdTRUE )
\r
245 pcStatusMessage = "Error: PollQueue";
\r
247 else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
\r
249 pcStatusMessage = "Error: IntMath";
\r
251 else if( xAreGenericQueueTasksStillRunning() != pdTRUE )
\r
253 pcStatusMessage = "Error: GenQueue";
\r
255 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
\r
257 pcStatusMessage = "Error: QueuePeek";
\r
259 else if( xAreMathsTaskStillRunning() != pdPASS )
\r
261 pcStatusMessage = "Error: Flop";
\r
263 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
\r
265 pcStatusMessage = "Error: RecMutex";
\r
267 else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )
\r
269 pcStatusMessage = "Error: CountSem";
\r
271 else if( xAreQueueSetTasksStillRunning() != pdPASS )
\r
273 pcStatusMessage = "Error: Queue set";
\r
275 else if( xIsQueueOverwriteTaskStillRunning() != pdPASS )
\r
277 pcStatusMessage = "Error: Queue overwrite";
\r
279 else if( xAreEventGroupTasksStillRunning() != pdTRUE )
\r
281 pcStatusMessage = "Error: EventGroup";
\r
283 else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )
\r
285 pcStatusMessage = "Error: IntSem";
\r
287 else if( xAreQueueSetPollTasksStillRunning() != pdPASS )
\r
289 pcStatusMessage = "Error: Queue set polling";
\r
291 else if( xAreBlockTimeTestTasksStillRunning() != pdPASS )
\r
293 pcStatusMessage = "Error: Block time";
\r
295 else if( xAreAbortDelayTestTasksStillRunning() != pdPASS )
\r
297 pcStatusMessage = "Error: Abort delay";
\r
299 else if( xAreMessageBufferTasksStillRunning() != pdTRUE )
\r
301 pcStatusMessage = "Error: MessageBuffer";
\r
303 else if( xAreStreamBufferTasksStillRunning() != pdTRUE )
\r
305 pcStatusMessage = "Error: StreamBuffer";
\r
307 else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS )
\r
309 pcStatusMessage = "Error: Stream buffer interrupt";
\r
311 else if( xIsCreateTaskStillRunning() != pdTRUE )
\r
313 pcStatusMessage = "Error: Death";
\r
315 else if( ulLastRegTest1Value == ulRegTest1Counter )
\r
317 pcStatusMessage = "Error: Reg Test 1";
\r
319 else if( ulLastRegTest2Value == ulRegTest2Counter )
\r
321 pcStatusMessage = "Error: Reg Test 2";
\r
324 /* Update register test counters. */
\r
325 ulLastRegTest1Value = ulRegTest1Counter;
\r
326 ulLastRegTest2Value = ulRegTest2Counter;
\r
328 #else /* mainENABLE_INT_QUEUE_TESTS */
\r
330 if( xAreIntQueueTasksStillRunning() != pdTRUE )
\r
332 pcStatusMessage = "Error: IntQueue";
\r
335 #endif /* mainENABLE_INT_QUEUE_TESTS */
\r
337 /* This is the only task that uses stdout so its ok to call printf()
\r
339 printf( "%s - tick count %zu - free heap %zu - min free heap %zu\r\n", pcStatusMessage,
\r
340 xTaskGetTickCount(),
\r
341 xPortGetFreeHeapSize(),
\r
342 xPortGetMinimumEverFreeHeapSize() );
\r
345 /*-----------------------------------------------------------*/
\r
347 /* Called by vApplicationTickHook(), which is defined in main.c. */
\r
348 void vFullDemoTickHookFunction( void )
\r
350 TaskHandle_t xTimerTask;
\r
352 #if( mainENABLE_INT_QUEUE_TESTS == 0 )
\r
354 /* Exercise using task notifications from an interrupt. */
\r
355 xNotifyTaskFromISR();
\r
357 /* Write to a queue that is in use as part of the queue set demo to
\r
358 * demonstrate using queue sets from an ISR. */
\r
359 vQueueSetAccessQueueSetFromISR();
\r
361 /* Call the periodic queue overwrite from ISR demo. */
\r
362 vQueueOverwritePeriodicISRDemo();
\r
364 /* Exercise event groups from interrupts. */
\r
365 vPeriodicEventGroupsProcessing();
\r
367 /* Exercise giving mutexes from an interrupt. */
\r
368 vInterruptSemaphorePeriodicTest();
\r
370 /* Queue set access from interrupt. */
\r
371 vQueueSetPollingInterruptAccess();
\r
373 /* Call the periodic timer test, which tests the timer API functions that
\r
374 can be called from an ISR. */
\r
375 #if( configUSE_PREEMPTION != 0 )
\r
377 /* Only created when preemption is used. */
\r
378 vTimerPeriodicISRTests();
\r
382 /* Writes to stream buffer byte by byte to test the stream buffer trigger
\r
383 level functionality. */
\r
384 vPeriodicStreamBufferProcessing();
\r
386 /* Writes a string to a string buffer four bytes at a time to demonstrate
\r
387 a stream being sent from an interrupt to a task. */
\r
388 vBasicStreamBufferSendFromISR();
\r
390 #else /* mainENABLE_INT_QUEUE_TESTS */
\r
392 /* Access queues from interrupt. Make sure to access after the queues have
\r
394 if( xTimerForQueueTestInitialized == pdTRUE )
\r
396 portYIELD_FROM_ISR( xFirstTimerHandler() );
\r
399 #endif /* mainENABLE_INT_QUEUE_TESTS */
\r
401 /*-----------------------------------------------------------*/
\r
403 static void prvRegTest1Task( void *pvParameters )
\r
405 /* Although the regtest task is written in assembly, its entry point is
\r
406 written in C for convenience of checking the task parameter is being passed
\r
408 if( pvParameters == mainREG_TEST_TASK_1_PARAMETER )
\r
410 /* Start the part of the test that is written in assembly. */
\r
414 /* The following line will only execute if the task parameter is found to
\r
415 be incorrect. The check task will detect that the regtest loop counter is
\r
416 not being incremented and flag an error. */
\r
417 vTaskDelete( NULL );
\r
419 /*-----------------------------------------------------------*/
\r
421 static void prvRegTest2Task( void *pvParameters )
\r
423 /* Although the regtest task is written in assembly, its entry point is
\r
424 written in C for convenience of checking the task parameter is being passed
\r
426 if( pvParameters == mainREG_TEST_TASK_2_PARAMETER )
\r
428 /* Start the part of the test that is written in assembly. */
\r
432 /* The following line will only execute if the task parameter is found to
\r
433 be incorrect. The check task will detect that the regtest loop counter is
\r
434 not being incremented and flag an error. */
\r
435 vTaskDelete( NULL );
\r
437 /*-----------------------------------------------------------*/
\r