3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * http://www.FreeRTOS.org
23 * http://aws.amazon.com/freertos
29 * Creates all the demo application tasks, then starts the scheduler.
30 * In addition to the standard demo tasks, the following tasks and tests are
31 * defined and/or created within this file:
33 * "Check" task - This only executes every five seconds but has the highest
34 * priority so is guaranteed to get processor time. Its main function is to
35 * check that all the standard demo tasks are still operational. The check
36 * task will write an error message to the console should an error be detected
37 * within any of the demo tasks. The check task also toggles the LED defined
38 * by mainCHECK_LED every 5 seconds while the system is error free, with the
39 * toggle rate increasing to every 500ms should an error occur.
41 * "Reg test" tasks - These fill the registers with known values, then check
42 * that each register still contains its expected value. Each task uses
43 * different values. The tasks run with very low priority so get preempted very
44 * frequently. A register containing an unexpected value is indicative of an
45 * error in the context switching mechanism.
47 * See the online documentation for this demo for more information on interrupt
51 /* Standard includes. */
56 /* Scheduler includes. */
61 /* Demo application includes. */
78 /*-----------------------------------------------------------*/
80 #error The batch file Demo\NiosII_CycloneIII_DBC3C40_GCC\CreateProjectDirectoryStructure.bat must be executed before the project is imported into the workspace. Failure to do this will result in the include paths stored in the project being deleted. Remove this line after CreateProjectDirectoryStructure.bat has been executed.
82 /*-----------------------------------------------------------*/
84 /* The rate at which the LED controlled by the 'check' task will toggle when no
85 errors have been detected. */
86 #define mainNO_ERROR_PERIOD ( 5000 )
88 /* The rate at which the LED controlled by the 'check' task will toggle when an
89 error has been detected. */
90 #define mainERROR_PERIOD ( 500 )
92 /* The LED toggled by the Check task. */
93 #define mainCHECK_LED ( 7 )
95 /* The first LED used by the ComTest tasks. One LED toggles each time a
96 character is transmitted, and one each time a character is received and
97 verified as being the expected character. */
98 #define mainCOMTEST_LED ( 4 )
100 /* Priority definitions for the tasks in the demo application. */
101 #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
102 #define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
103 #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 4 )
104 #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
105 #define mainQUEUE_BLOCK_PRIORITY ( tskIDLE_PRIORITY + 3 )
106 #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
107 #define mainSEMAPHORE_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
108 #define mainGENERIC_QUEUE_PRIORITY ( tskIDLE_PRIORITY )
109 #define mainREG_TEST_PRIORITY ( tskIDLE_PRIORITY )
112 #define mainDONT_WAIT ( 0 )
114 /* The parameters passed to the reg test tasks. This is just done to check
115 the parameter passing mechanism is working correctly. */
116 #define mainREG_TEST_1_PARAMETER ( ( void * ) 0x12345678 )
117 #define mainREG_TEST_2_PARAMETER ( ( void * ) 0x87654321 )
119 /*-----------------------------------------------------------*/
122 * Setup the processor ready for the demo.
124 static void prvSetupHardware( void );
127 * Execute all of the check functions to ensure the tests haven't failed.
129 static void prvCheckTask( void *pvParameters );
132 * The register test (or RegTest) tasks as described at the top of this file.
134 static void prvFirstRegTestTask( void *pvParameters );
135 static void prvSecondRegTestTask( void *pvParameters );
137 /*-----------------------------------------------------------*/
139 /* Counters that are incremented on each iteration of the RegTest tasks
140 so long as no errors have been detected. */
141 volatile unsigned long ulRegTest1Counter = 0UL, ulRegTest2Counter = 0UL;
143 /*-----------------------------------------------------------*/
146 * Create the demo tasks then start the scheduler.
150 /* Configure any hardware required for this demo. */
153 /* Create all the other standard demo tasks. These serve no purpose other
154 than to test the port and demonstrate the use of the FreeRTOS API. */
155 vStartLEDFlashTasks( tskIDLE_PRIORITY );
156 vStartIntegerMathTasks( mainGENERIC_QUEUE_PRIORITY );
157 vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
158 vStartBlockingQueueTasks( mainQUEUE_BLOCK_PRIORITY );
159 vCreateBlockTimeTasks();
160 vStartSemaphoreTasks( mainSEMAPHORE_TASK_PRIORITY );
161 vStartDynamicPriorityTasks();
162 vStartQueuePeekTasks();
163 vStartGenericQueueTasks( mainGENERIC_QUEUE_PRIORITY );
164 vStartCountingSemaphoreTasks();
165 vStartRecursiveMutexTasks();
166 vAltStartComTestTasks( mainCOM_TEST_PRIORITY, 0, mainCOMTEST_LED );
168 /* prvCheckTask uses sprintf so requires more stack. */
169 xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
171 /* The RegTest tasks as described at the top of this file. */
172 xTaskCreate( prvFirstRegTestTask, "Rreg1", configMINIMAL_STACK_SIZE, mainREG_TEST_1_PARAMETER, mainREG_TEST_PRIORITY, NULL );
173 xTaskCreate( prvSecondRegTestTask, "Rreg2", configMINIMAL_STACK_SIZE, mainREG_TEST_2_PARAMETER, mainREG_TEST_PRIORITY, NULL );
175 /* This task has to be created last as it keeps account of the number of tasks
176 it expects to see running. */
177 vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
179 /* Finally start the scheduler. */
180 vTaskStartScheduler();
182 /* Will only reach here if there is insufficient heap available to start
186 /*-----------------------------------------------------------*/
188 static void prvSetupHardware( void )
190 /* Setup the digital IO for the LED's. */
191 vParTestInitialise();
193 /*-----------------------------------------------------------*/
195 void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
200 /* Look at pxCurrentTCB to see which task overflowed its stack. */
206 /*-----------------------------------------------------------*/
208 void _general_exception_handler( unsigned long ulCause, unsigned long ulStatus )
210 /* This overrides the definition provided by the kernel. Other exceptions
211 should be handled here. */
217 /*-----------------------------------------------------------*/
219 static void prvCheckTask( void *pvParameters )
221 TickType_t xLastExecutionTime, ulTicksToWait = mainNO_ERROR_PERIOD;
222 unsigned long ulLastRegTest1 = 0UL, ulLastRegTest2 = 0UL;
223 const char * pcMessage;
225 /* Initialise the variable used to control our iteration rate prior to
227 xLastExecutionTime = xTaskGetTickCount();
231 /* Wait until it is time to run the tests again. */
232 vTaskDelayUntil( &xLastExecutionTime, ulTicksToWait );
234 /* Have any of the standard demo tasks detected an error in their
236 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
238 ulTicksToWait = mainERROR_PERIOD;
239 pcMessage = "Error: Integer Maths.\n";
241 else if( xAreGenericQueueTasksStillRunning() != pdTRUE )
243 ulTicksToWait = mainERROR_PERIOD;
244 pcMessage = "Error: GenQ.\n";
246 else if( xAreBlockingQueuesStillRunning() != pdTRUE )
248 ulTicksToWait = mainERROR_PERIOD;
249 pcMessage = "Error: BlockQ.\n";
251 else if( xArePollingQueuesStillRunning() != pdTRUE )
253 ulTicksToWait = mainERROR_PERIOD;
254 pcMessage = "Error: PollQ.\n";
256 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
258 ulTicksToWait = mainERROR_PERIOD;
259 pcMessage = "Error: PeekQ.\n";
261 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
263 ulTicksToWait = mainERROR_PERIOD;
264 pcMessage = "Error: Block Time.\n";
266 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
268 ulTicksToWait = mainERROR_PERIOD;
269 pcMessage = "Error: Semaphore Test.\n";
271 else if( xAreComTestTasksStillRunning() != pdTRUE )
273 ulTicksToWait = mainERROR_PERIOD;
274 pcMessage = "Error: Comm Test.\n";
276 else if( xIsCreateTaskStillRunning() != pdTRUE )
278 ulTicksToWait = mainERROR_PERIOD;
279 pcMessage = "Error: Suicidal Tasks.\n";
281 else if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
283 ulTicksToWait = mainERROR_PERIOD;
284 pcMessage = "Error: Dynamic Priority.\n";
286 else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )
288 ulTicksToWait = mainERROR_PERIOD;
289 pcMessage = "Error: Count Semaphore.\n";
291 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
293 ulTicksToWait = mainERROR_PERIOD;
294 pcMessage = "Error: Recursive Mutex.\n";
296 else if( ulLastRegTest1 == ulRegTest1Counter )
298 /* ulRegTest1Counter is no longer being incremented, indicating
299 that an error has been discovered in prvFirstRegTestTask(). */
300 ulTicksToWait = mainERROR_PERIOD;
301 pcMessage = "Error: Reg Test1.\n";
303 else if( ulLastRegTest2 == ulRegTest2Counter )
305 /* ulRegTest2Counter is no longer being incremented, indicating
306 that an error has been discovered in prvSecondRegTestTask(). */
307 ulTicksToWait = mainERROR_PERIOD;
308 pcMessage = "Error: Reg Test2.\n";
315 /* Remember the counter values this time around so a counter failing
316 to be incremented correctly can be spotted. */
317 ulLastRegTest1 = ulRegTest1Counter;
318 ulLastRegTest2 = ulRegTest2Counter;
320 /* Print out an error message if there is one. Mutual exclusion is
321 not used as this is the only task accessing stdout. */
322 if( pcMessage != NULL )
327 /* Provide visual feedback of the system status. If the LED is toggled
328 every 5 seconds then no errors have been found. If the LED is toggled
329 every 500ms then at least one error has been found. */
330 vParTestToggleLED( mainCHECK_LED );
333 /*-----------------------------------------------------------*/
335 static void prvFirstRegTestTask( void *pvParameters )
337 /* Check the parameters are passed in as expected. */
338 if( pvParameters != mainREG_TEST_1_PARAMETER )
340 /* Don't execute any further so an error is recognised by the check
345 /* Fill registers with known values, then check that each register still
346 contains its expected value. An incorrect value is indicative of an error
347 in the context switching process.
349 If no errors are found ulRegTest1Counter is incremented. The check task
350 will recognise an error if ulRegTest1Counter stops being incremented.
351 This task also performs a manual yield in the middle of its execution, just
352 to increase the test coverage. */
354 " .extern ulRegTest1Counter \n" \
356 " addi r3, r0, 3 \n" \
357 " addi r4, r0, 4 \n" \
358 " addi r5, r0, 5 \n" \
359 " addi r6, r0, 6 \n" \
360 " addi r7, r0, 7 \n" \
361 " addi r8, r0, 8 \n" \
362 " addi r9, r0, 9 \n" \
363 " addi r10, r0, 10 \n" \
364 " addi r11, r0, 11 \n" \
365 " addi r12, r0, 12 \n" \
366 " addi r13, r0, 13 \n" \
367 " addi r14, r0, 14 \n" \
368 " addi r15, r0, 15 \n" \
369 " addi r16, r0, 16 \n" \
370 " addi r17, r0, 17 \n" \
371 " addi r18, r0, 18 \n" \
372 " addi r19, r0, 19 \n" \
373 " addi r20, r0, 20 \n" \
374 " addi r21, r0, 21 \n" \
375 " addi r22, r0, 22 \n" \
376 " addi r23, r0, 23 \n" \
377 " addi r28, r0, 28 \n" \
378 " addi r31, r0, 31 \n" \
380 " addi r2, r0, 0 \n" \
382 " bne r2, r0, RegTest1Error \n" \
383 " addi r2, r0, 3 \n" \
384 " bne r2, r3, RegTest1Error \n" \
385 " addi r2, r0, 4 \n" \
386 " bne r2, r4, RegTest1Error \n" \
387 " addi r2, r0, 5 \n" \
388 " bne r2, r5, RegTest1Error \n" \
389 " addi r2, r0, 6 \n" \
390 " bne r2, r6, RegTest1Error \n" \
391 " addi r2, r0, 7 \n" \
392 " bne r2, r7, RegTest1Error \n" \
393 " addi r2, r0, 8 \n" \
394 " bne r2, r8, RegTest1Error \n" \
395 " addi r2, r0, 9 \n" \
396 " bne r2, r9, RegTest1Error \n" \
397 " addi r2, r0, 10 \n" \
398 " bne r2, r10, RegTest1Error \n" \
399 " addi r2, r0, 11 \n" \
400 " bne r2, r11, RegTest1Error \n" \
401 " addi r2, r0, 12 \n" \
402 " bne r2, r12, RegTest1Error \n" \
403 " addi r2, r0, 13 \n" \
404 " bne r2, r13, RegTest1Error \n" \
405 " addi r2, r0, 14 \n" \
406 " bne r2, r14, RegTest1Error \n" \
407 " addi r2, r0, 15 \n" \
408 " bne r2, r15, RegTest1Error \n" \
409 " addi r2, r0, 16 \n" \
410 " bne r2, r16, RegTest1Error \n" \
411 " addi r2, r0, 17 \n" \
412 " bne r2, r17, RegTest1Error \n" \
413 " addi r2, r0, 18 \n" \
414 " bne r2, r18, RegTest1Error \n" \
415 " addi r2, r0, 19 \n" \
416 " bne r2, r19, RegTest1Error \n" \
417 " addi r2, r0, 20 \n" \
418 " bne r2, r20, RegTest1Error \n" \
419 " addi r2, r0, 21 \n" \
420 " bne r2, r21, RegTest1Error \n" \
421 " addi r2, r0, 22 \n" \
422 " bne r2, r22, RegTest1Error \n" \
423 " addi r2, r0, 23 \n" \
424 " bne r2, r23, RegTest1Error \n" \
425 " addi r2, r0, 28 \n" \
426 " bne r2, r28, RegTest1Error \n" \
427 " addi r2, r0, 31 \n" \
428 " bne r2, r31, RegTest1Error \n" \
429 " ldw r2, %gprel(ulRegTest1Counter)(gp) \n" \
430 " addi r2, r2, 1 \n" \
431 " stw r2, %gprel(ulRegTest1Counter)(gp) \n" \
433 "RegTest1Error: \n" \
434 " br RegTest1Error \n"
437 /*-----------------------------------------------------------*/
439 static void prvSecondRegTestTask( void *pvParameters )
441 /* Check the parameters are passed in as expected. */
442 if( pvParameters != mainREG_TEST_2_PARAMETER )
444 /* Don't execute any further so an error is recognised by the check
449 /* Fill registers with known values, then check that each register still
450 contains its expected value. An incorrect value is indicative of an error
451 in the context switching process.
453 If no errors are found ulRegTest2Counter is incremented. The check task
454 will recognise an error if ulRegTest2Counter stops being incremented. */
456 " .extern ulRegTest2Counter \n" \
458 " addi r3, r0, 3 \n" \
459 " addi r4, r0, 4 \n" \
460 " addi r5, r0, 5 \n" \
461 " addi r6, r0, 6 \n" \
462 " addi r7, r0, 7 \n" \
463 " addi r8, r0, 8 \n" \
464 " addi r9, r0, 9 \n" \
465 " addi r10, r0, 10 \n" \
466 " addi r11, r0, 11 \n" \
467 " addi r12, r0, 12 \n" \
468 " addi r13, r0, 13 \n" \
469 " addi r14, r0, 14 \n" \
470 " addi r15, r0, 15 \n" \
471 " addi r16, r0, 16 \n" \
472 " addi r17, r0, 17 \n" \
473 " addi r18, r0, 18 \n" \
474 " addi r19, r0, 19 \n" \
475 " addi r20, r0, 20 \n" \
476 " addi r21, r0, 21 \n" \
477 " addi r22, r0, 22 \n" \
478 " addi r23, r0, 23 \n" \
479 " addi r28, r0, 28 \n" \
480 " addi r31, r0, 31 \n" \
482 " addi r2, r0, 0 \n" \
483 " bne r2, r0, RegTest2Error \n" \
484 " addi r2, r0, 3 \n" \
485 " bne r2, r3, RegTest2Error \n" \
486 " addi r2, r0, 4 \n" \
487 " bne r2, r4, RegTest2Error \n" \
488 " addi r2, r0, 5 \n" \
489 " bne r2, r5, RegTest2Error \n" \
490 " addi r2, r0, 6 \n" \
491 " bne r2, r6, RegTest2Error \n" \
492 " addi r2, r0, 7 \n" \
493 " bne r2, r7, RegTest2Error \n" \
494 " addi r2, r0, 8 \n" \
495 " bne r2, r8, RegTest2Error \n" \
496 " addi r2, r0, 9 \n" \
497 " bne r2, r9, RegTest2Error \n" \
498 " addi r2, r0, 10 \n" \
499 " bne r2, r10, RegTest2Error \n" \
500 " addi r2, r0, 11 \n" \
501 " bne r2, r11, RegTest2Error \n" \
502 " addi r2, r0, 12 \n" \
503 " bne r2, r12, RegTest2Error \n" \
504 " addi r2, r0, 13 \n" \
505 " bne r2, r13, RegTest2Error \n" \
506 " addi r2, r0, 14 \n" \
507 " bne r2, r14, RegTest2Error \n" \
508 " addi r2, r0, 15 \n" \
509 " bne r2, r15, RegTest2Error \n" \
510 " addi r2, r0, 16 \n" \
511 " bne r2, r16, RegTest2Error \n" \
512 " addi r2, r0, 17 \n" \
513 " bne r2, r17, RegTest2Error \n" \
514 " addi r2, r0, 18 \n" \
515 " bne r2, r18, RegTest2Error \n" \
516 " addi r2, r0, 19 \n" \
517 " bne r2, r19, RegTest2Error \n" \
518 " addi r2, r0, 20 \n" \
519 " bne r2, r20, RegTest2Error \n" \
520 " addi r2, r0, 21 \n" \
521 " bne r2, r21, RegTest2Error \n" \
522 " addi r2, r0, 22 \n" \
523 " bne r2, r22, RegTest2Error \n" \
524 " addi r2, r0, 23 \n" \
525 " bne r2, r23, RegTest2Error \n" \
526 " addi r2, r0, 28 \n" \
527 " bne r2, r28, RegTest2Error \n" \
528 " addi r2, r0, 31 \n" \
529 " bne r2, r31, RegTest2Error \n" \
530 " ldw r2, %gprel(ulRegTest2Counter)(gp) \n" \
531 " addi r2, r2, 1 \n" \
532 " stw r2, %gprel(ulRegTest2Counter)(gp) \n" \
534 "RegTest2Error: \n" \
535 " br RegTest2Error \n"
538 /*-----------------------------------------------------------*/