2 FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd.
\r
4 This file is part of the FreeRTOS distribution.
\r
6 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
7 the terms of the GNU General Public License (version 2) as published by the
\r
8 Free Software Foundation and modified by the FreeRTOS exception.
\r
9 **NOTE** The exception to the GPL is included to allow you to distribute a
\r
10 combined work that includes FreeRTOS without being obliged to provide the
\r
11 source code for proprietary components outside of the FreeRTOS kernel.
\r
12 Alternative commercial license and support terms are also available upon
\r
13 request. See the licensing section of http://www.FreeRTOS.org for full
\r
16 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
\r
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
21 You should have received a copy of the GNU General Public License along
\r
22 with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59
\r
23 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
\r
26 ***************************************************************************
\r
28 * Looking for a quick start? Then check out the FreeRTOS eBook! *
\r
29 * See http://www.FreeRTOS.org/Documentation for details *
\r
31 ***************************************************************************
\r
35 Please ensure to read the configuration and relevant port sections of the
\r
36 online documentation.
\r
38 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
41 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
44 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
45 licensing and training services.
\r
49 * Creates all the demo application tasks, then starts the scheduler.
\r
50 * In addition to the standard demo tasks, the following tasks and tests are
\r
51 * defined and/or created within this file:
\r
53 * "Check" task - This only executes every five seconds but has the highest
\r
54 * priority so is guaranteed to get processor time. Its main function is to
\r
55 * check that all the standard demo tasks are still operational. The check
\r
56 * task will write an error message to the console should an error be detected
\r
57 * within any of the demo tasks. The check task also toggles the LED defined
\r
58 * by mainCHECK_LED every 5 seconds while the system is error free, with the
\r
59 * toggle rate increasing to every 500ms should an error occur.
\r
61 * "Reg test" tasks - These fill the registers with known values, then check
\r
62 * that each register still contains its expected value. Each task uses
\r
63 * different values. The tasks run with very low priority so get preempted very
\r
64 * frequently. A register containing an unexpected value is indicative of an
\r
65 * error in the context switching mechanism.
\r
67 * See the online documentation for this demo for more information on interrupt
\r
71 /* Standard includes. */
\r
76 /* Scheduler includes. */
\r
77 #include "FreeRTOS.h"
\r
81 /* Demo application includes. */
\r
82 #include "partest.h"
\r
84 #include "blocktim.h"
\r
85 #include "semtest.h"
\r
87 #include "comtest.h"
\r
88 #include "GenQTest.h"
\r
90 #include "integer.h"
\r
93 #include "dynamic.h"
\r
94 #include "countsem.h"
\r
95 #include "recmutex.h"
\r
98 /*-----------------------------------------------------------*/
\r
100 /* The rate at which the LED controlled by the 'check' task will toggle when no
\r
101 errors have been detected. */
\r
102 #define mainNO_ERROR_PERIOD ( 5000 )
\r
104 /* The rate at which the LED controlled by the 'check' task will toggle when an
\r
105 error has been detected. */
\r
106 #define mainERROR_PERIOD ( 500 )
\r
108 /* The LED toggled by the Check task. */
\r
109 #define mainCHECK_LED ( 7 )
\r
111 /* The first LED used by the ComTest tasks. One LED toggles each time a
\r
112 character is transmitted, and one each time a character is received and
\r
113 verified as being the expected character. */
\r
114 #define mainCOMTEST_LED ( 4 )
\r
116 /* Priority definitions for the tasks in the demo application. */
\r
117 #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
118 #define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
\r
119 #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 4 )
\r
120 #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
\r
121 #define mainQUEUE_BLOCK_PRIORITY ( tskIDLE_PRIORITY + 3 )
\r
122 #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
\r
123 #define mainSEMAPHORE_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
124 #define mainGENERIC_QUEUE_PRIORITY ( tskIDLE_PRIORITY )
\r
125 #define mainREG_TEST_PRIORITY ( tskIDLE_PRIORITY )
\r
128 #define mainDONT_WAIT ( 0 )
\r
130 /* The parameters passed to the reg test tasks. This is just done to check
\r
131 the parameter passing mechanism is working correctly. */
\r
132 #define mainREG_TEST_1_PARAMETER ( ( void * ) 0x12345678 )
\r
133 #define mainREG_TEST_2_PARAMETER ( ( void * ) 0x87654321 )
\r
135 /*-----------------------------------------------------------*/
\r
138 * Setup the processor ready for the demo.
\r
140 static void prvSetupHardware( void );
\r
143 * Execute all of the check functions to ensure the tests haven't failed.
\r
145 static void prvCheckTask( void *pvParameters );
\r
148 * The register test (or RegTest) tasks as described at the top of this file.
\r
150 static void prvFirstRegTestTask( void *pvParameters );
\r
151 static void prvSecondRegTestTask( void *pvParameters );
\r
153 /*-----------------------------------------------------------*/
\r
155 /* Counters that are incremented on each iteration of the RegTest tasks
\r
156 so long as no errors have been detected. */
\r
157 volatile unsigned long ulRegTest1Counter = 0UL, ulRegTest2Counter = 0UL;
\r
159 /*-----------------------------------------------------------*/
\r
162 * Create the demo tasks then start the scheduler.
\r
166 /* Configure any hardware required for this demo. */
\r
167 prvSetupHardware();
\r
169 /* Create all the other standard demo tasks. These serve no purpose other
\r
170 than to test the port and demonstrate the use of the FreeRTOS API. */
\r
171 vStartLEDFlashTasks( tskIDLE_PRIORITY );
\r
172 vStartIntegerMathTasks( mainGENERIC_QUEUE_PRIORITY );
\r
173 vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
\r
174 vStartBlockingQueueTasks( mainQUEUE_BLOCK_PRIORITY );
\r
175 vCreateBlockTimeTasks();
\r
176 vStartSemaphoreTasks( mainSEMAPHORE_TASK_PRIORITY );
\r
177 vStartDynamicPriorityTasks();
\r
178 vStartQueuePeekTasks();
\r
179 vStartGenericQueueTasks( mainGENERIC_QUEUE_PRIORITY );
\r
180 vStartCountingSemaphoreTasks();
\r
181 vStartRecursiveMutexTasks();
\r
182 vAltStartComTestTasks( mainCOM_TEST_PRIORITY, 0, mainCOMTEST_LED );
\r
184 /* prvCheckTask uses sprintf so requires more stack. */
\r
185 xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
\r
187 /* The RegTest tasks as described at the top of this file. */
\r
188 xTaskCreate( prvFirstRegTestTask, "Rreg1", configMINIMAL_STACK_SIZE, mainREG_TEST_1_PARAMETER, mainREG_TEST_PRIORITY, NULL );
\r
189 xTaskCreate( prvSecondRegTestTask, "Rreg2", configMINIMAL_STACK_SIZE, mainREG_TEST_2_PARAMETER, mainREG_TEST_PRIORITY, NULL );
\r
191 /* This task has to be created last as it keeps account of the number of tasks
\r
192 it expects to see running. */
\r
193 vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
\r
195 /* Finally start the scheduler. */
\r
196 vTaskStartScheduler();
\r
198 /* Will only reach here if there is insufficient heap available to start
\r
202 /*-----------------------------------------------------------*/
\r
204 static void prvSetupHardware( void )
\r
206 /* Setup the digital IO for the LED's. */
\r
207 vParTestInitialise();
\r
209 /*-----------------------------------------------------------*/
\r
211 void vApplicationStackOverflowHook( void )
\r
213 /* Look at pxCurrentTCB to see which task overflowed its stack. */
\r
219 /*-----------------------------------------------------------*/
\r
221 void _general_exception_handler( unsigned portLONG ulCause, unsigned portLONG ulStatus )
\r
223 /* This overrides the definition provided by the kernel. Other exceptions
\r
224 should be handled here. */
\r
230 /*-----------------------------------------------------------*/
\r
232 static void prvCheckTask( void *pvParameters )
\r
234 portTickType xLastExecutionTime, ulTicksToWait = mainNO_ERROR_PERIOD;
\r
235 unsigned long ulLastRegTest1 = 0UL, ulLastRegTest2 = 0UL;
\r
236 const portCHAR * pcMessage;
\r
238 /* Initialise the variable used to control our iteration rate prior to
\r
240 xLastExecutionTime = xTaskGetTickCount();
\r
244 /* Wait until it is time to run the tests again. */
\r
245 vTaskDelayUntil( &xLastExecutionTime, ulTicksToWait );
\r
247 /* Have any of the standard demo tasks detected an error in their
\r
249 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
\r
251 ulTicksToWait = mainERROR_PERIOD;
\r
252 pcMessage = "Error: Integer Maths.\n";
\r
254 else if( xAreGenericQueueTasksStillRunning() != pdTRUE )
\r
256 ulTicksToWait = mainERROR_PERIOD;
\r
257 pcMessage = "Error: GenQ.\n";
\r
259 else if( xAreBlockingQueuesStillRunning() != pdTRUE )
\r
261 ulTicksToWait = mainERROR_PERIOD;
\r
262 pcMessage = "Error: BlockQ.\n";
\r
264 else if( xArePollingQueuesStillRunning() != pdTRUE )
\r
266 ulTicksToWait = mainERROR_PERIOD;
\r
267 pcMessage = "Error: PollQ.\n";
\r
269 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
\r
271 ulTicksToWait = mainERROR_PERIOD;
\r
272 pcMessage = "Error: PeekQ.\n";
\r
274 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
\r
276 ulTicksToWait = mainERROR_PERIOD;
\r
277 pcMessage = "Error: Block Time.\n";
\r
279 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
\r
281 ulTicksToWait = mainERROR_PERIOD;
\r
282 pcMessage = "Error: Semaphore Test.\n";
\r
284 else if( xAreComTestTasksStillRunning() != pdTRUE )
\r
286 ulTicksToWait = mainERROR_PERIOD;
\r
287 pcMessage = "Error: Comm Test.\n";
\r
289 else if( xIsCreateTaskStillRunning() != pdTRUE )
\r
291 ulTicksToWait = mainERROR_PERIOD;
\r
292 pcMessage = "Error: Suicidal Tasks.\n";
\r
294 else if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
\r
296 ulTicksToWait = mainERROR_PERIOD;
\r
297 pcMessage = "Error: Dynamic Priority.\n";
\r
299 else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )
\r
301 ulTicksToWait = mainERROR_PERIOD;
\r
302 pcMessage = "Error: Count Semaphore.\n";
\r
304 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
\r
306 ulTicksToWait = mainERROR_PERIOD;
\r
307 pcMessage = "Error: Recursive Mutex.\n";
\r
309 else if( ulLastRegTest1 == ulRegTest1Counter )
\r
311 /* ulRegTest1Counter is no longer being incremented, indicating
\r
312 that an error has been discovered in prvFirstRegTestTask(). */
\r
313 ulTicksToWait = mainERROR_PERIOD;
\r
314 pcMessage = "Error: Reg Test1.\n";
\r
316 else if( ulLastRegTest2 == ulRegTest2Counter )
\r
318 /* ulRegTest2Counter is no longer being incremented, indicating
\r
319 that an error has been discovered in prvSecondRegTestTask(). */
\r
320 ulTicksToWait = mainERROR_PERIOD;
\r
321 pcMessage = "Error: Reg Test2.\n";
\r
328 /* Remember the counter values this time around so a counter failing
\r
329 to be incremented correctly can be spotted. */
\r
330 ulLastRegTest1 = ulRegTest1Counter;
\r
331 ulLastRegTest2 = ulRegTest2Counter;
\r
333 /* Print out an error message if there is one. Mutual exclusion is
\r
334 not used as this is the only task accessing stdout. */
\r
335 if( pcMessage != NULL )
\r
337 printf( pcMessage );
\r
340 /* Provide visual feedback of the system status. If the LED is toggled
\r
341 every 5 seconds then no errors have been found. If the LED is toggled
\r
342 every 500ms then at least one error has been found. */
\r
343 vParTestToggleLED( mainCHECK_LED );
\r
346 /*-----------------------------------------------------------*/
\r
348 static void prvFirstRegTestTask( void *pvParameters )
\r
350 /* Check the parameters are passed in as expected. */
\r
351 if( pvParameters != mainREG_TEST_1_PARAMETER )
\r
353 /* Don't execute any further so an error is recognised by the check
\r
355 vTaskDelete( NULL );
\r
358 /* Fill registers with known values, then check that each register still
\r
359 contains its expected value. An incorrect value is indicative of an error
\r
360 in the context switching process.
\r
362 If no errors are found ulRegTest1Counter is incremented. The check task
\r
363 will recognise an error if ulRegTest1Counter stops being incremented.
\r
364 This task also performs a manual yield in the middle of its execution, just
\r
365 to increase the test coverage. */
\r
367 " .extern ulRegTest1Counter \n" \
\r
369 " addi r3, r0, 3 \n" \
\r
370 " addi r4, r0, 4 \n" \
\r
371 " addi r5, r0, 5 \n" \
\r
372 " addi r6, r0, 6 \n" \
\r
373 " addi r7, r0, 7 \n" \
\r
374 " addi r8, r0, 8 \n" \
\r
375 " addi r9, r0, 9 \n" \
\r
376 " addi r10, r0, 10 \n" \
\r
377 " addi r11, r0, 11 \n" \
\r
378 " addi r12, r0, 12 \n" \
\r
379 " addi r13, r0, 13 \n" \
\r
380 " addi r14, r0, 14 \n" \
\r
381 " addi r15, r0, 15 \n" \
\r
382 " addi r16, r0, 16 \n" \
\r
383 " addi r17, r0, 17 \n" \
\r
384 " addi r18, r0, 18 \n" \
\r
385 " addi r19, r0, 19 \n" \
\r
386 " addi r20, r0, 20 \n" \
\r
387 " addi r21, r0, 21 \n" \
\r
388 " addi r22, r0, 22 \n" \
\r
389 " addi r23, r0, 23 \n" \
\r
390 " addi r28, r0, 28 \n" \
\r
391 " addi r31, r0, 31 \n" \
\r
393 " addi r2, r0, 0 \n" \
\r
395 " bne r2, r0, RegTest1Error \n" \
\r
396 " addi r2, r0, 3 \n" \
\r
397 " bne r2, r3, RegTest1Error \n" \
\r
398 " addi r2, r0, 4 \n" \
\r
399 " bne r2, r4, RegTest1Error \n" \
\r
400 " addi r2, r0, 5 \n" \
\r
401 " bne r2, r5, RegTest1Error \n" \
\r
402 " addi r2, r0, 6 \n" \
\r
403 " bne r2, r6, RegTest1Error \n" \
\r
404 " addi r2, r0, 7 \n" \
\r
405 " bne r2, r7, RegTest1Error \n" \
\r
406 " addi r2, r0, 8 \n" \
\r
407 " bne r2, r8, RegTest1Error \n" \
\r
408 " addi r2, r0, 9 \n" \
\r
409 " bne r2, r9, RegTest1Error \n" \
\r
410 " addi r2, r0, 10 \n" \
\r
411 " bne r2, r10, RegTest1Error \n" \
\r
412 " addi r2, r0, 11 \n" \
\r
413 " bne r2, r11, RegTest1Error \n" \
\r
414 " addi r2, r0, 12 \n" \
\r
415 " bne r2, r12, RegTest1Error \n" \
\r
416 " addi r2, r0, 13 \n" \
\r
417 " bne r2, r13, RegTest1Error \n" \
\r
418 " addi r2, r0, 14 \n" \
\r
419 " bne r2, r14, RegTest1Error \n" \
\r
420 " addi r2, r0, 15 \n" \
\r
421 " bne r2, r15, RegTest1Error \n" \
\r
422 " addi r2, r0, 16 \n" \
\r
423 " bne r2, r16, RegTest1Error \n" \
\r
424 " addi r2, r0, 17 \n" \
\r
425 " bne r2, r17, RegTest1Error \n" \
\r
426 " addi r2, r0, 18 \n" \
\r
427 " bne r2, r18, RegTest1Error \n" \
\r
428 " addi r2, r0, 19 \n" \
\r
429 " bne r2, r19, RegTest1Error \n" \
\r
430 " addi r2, r0, 20 \n" \
\r
431 " bne r2, r20, RegTest1Error \n" \
\r
432 " addi r2, r0, 21 \n" \
\r
433 " bne r2, r21, RegTest1Error \n" \
\r
434 " addi r2, r0, 22 \n" \
\r
435 " bne r2, r22, RegTest1Error \n" \
\r
436 " addi r2, r0, 23 \n" \
\r
437 " bne r2, r23, RegTest1Error \n" \
\r
438 " addi r2, r0, 28 \n" \
\r
439 " bne r2, r28, RegTest1Error \n" \
\r
440 " addi r2, r0, 31 \n" \
\r
441 " bne r2, r31, RegTest1Error \n" \
\r
442 " ldw r2, %gprel(ulRegTest1Counter)(gp) \n" \
\r
443 " addi r2, r2, 1 \n" \
\r
444 " stw r2, %gprel(ulRegTest1Counter)(gp) \n" \
\r
445 " br RegTest1 \n" \
\r
446 "RegTest1Error: \n" \
\r
447 " br RegTest1Error \n"
\r
450 /*-----------------------------------------------------------*/
\r
452 static void prvSecondRegTestTask( void *pvParameters )
\r
454 /* Check the parameters are passed in as expected. */
\r
455 if( pvParameters != mainREG_TEST_2_PARAMETER )
\r
457 /* Don't execute any further so an error is recognised by the check
\r
459 vTaskDelete( NULL );
\r
462 /* Fill registers with known values, then check that each register still
\r
463 contains its expected value. An incorrect value is indicative of an error
\r
464 in the context switching process.
\r
466 If no errors are found ulRegTest2Counter is incremented. The check task
\r
467 will recognise an error if ulRegTest2Counter stops being incremented. */
\r
469 " .extern ulRegTest2Counter \n" \
\r
471 " addi r3, r0, 3 \n" \
\r
472 " addi r4, r0, 4 \n" \
\r
473 " addi r5, r0, 5 \n" \
\r
474 " addi r6, r0, 6 \n" \
\r
475 " addi r7, r0, 7 \n" \
\r
476 " addi r8, r0, 8 \n" \
\r
477 " addi r9, r0, 9 \n" \
\r
478 " addi r10, r0, 10 \n" \
\r
479 " addi r11, r0, 11 \n" \
\r
480 " addi r12, r0, 12 \n" \
\r
481 " addi r13, r0, 13 \n" \
\r
482 " addi r14, r0, 14 \n" \
\r
483 " addi r15, r0, 15 \n" \
\r
484 " addi r16, r0, 16 \n" \
\r
485 " addi r17, r0, 17 \n" \
\r
486 " addi r18, r0, 18 \n" \
\r
487 " addi r19, r0, 19 \n" \
\r
488 " addi r20, r0, 20 \n" \
\r
489 " addi r21, r0, 21 \n" \
\r
490 " addi r22, r0, 22 \n" \
\r
491 " addi r23, r0, 23 \n" \
\r
492 " addi r28, r0, 28 \n" \
\r
493 " addi r31, r0, 31 \n" \
\r
495 " addi r2, r0, 0 \n" \
\r
496 " bne r2, r0, RegTest2Error \n" \
\r
497 " addi r2, r0, 3 \n" \
\r
498 " bne r2, r3, RegTest2Error \n" \
\r
499 " addi r2, r0, 4 \n" \
\r
500 " bne r2, r4, RegTest2Error \n" \
\r
501 " addi r2, r0, 5 \n" \
\r
502 " bne r2, r5, RegTest2Error \n" \
\r
503 " addi r2, r0, 6 \n" \
\r
504 " bne r2, r6, RegTest2Error \n" \
\r
505 " addi r2, r0, 7 \n" \
\r
506 " bne r2, r7, RegTest2Error \n" \
\r
507 " addi r2, r0, 8 \n" \
\r
508 " bne r2, r8, RegTest2Error \n" \
\r
509 " addi r2, r0, 9 \n" \
\r
510 " bne r2, r9, RegTest2Error \n" \
\r
511 " addi r2, r0, 10 \n" \
\r
512 " bne r2, r10, RegTest2Error \n" \
\r
513 " addi r2, r0, 11 \n" \
\r
514 " bne r2, r11, RegTest2Error \n" \
\r
515 " addi r2, r0, 12 \n" \
\r
516 " bne r2, r12, RegTest2Error \n" \
\r
517 " addi r2, r0, 13 \n" \
\r
518 " bne r2, r13, RegTest2Error \n" \
\r
519 " addi r2, r0, 14 \n" \
\r
520 " bne r2, r14, RegTest2Error \n" \
\r
521 " addi r2, r0, 15 \n" \
\r
522 " bne r2, r15, RegTest2Error \n" \
\r
523 " addi r2, r0, 16 \n" \
\r
524 " bne r2, r16, RegTest2Error \n" \
\r
525 " addi r2, r0, 17 \n" \
\r
526 " bne r2, r17, RegTest2Error \n" \
\r
527 " addi r2, r0, 18 \n" \
\r
528 " bne r2, r18, RegTest2Error \n" \
\r
529 " addi r2, r0, 19 \n" \
\r
530 " bne r2, r19, RegTest2Error \n" \
\r
531 " addi r2, r0, 20 \n" \
\r
532 " bne r2, r20, RegTest2Error \n" \
\r
533 " addi r2, r0, 21 \n" \
\r
534 " bne r2, r21, RegTest2Error \n" \
\r
535 " addi r2, r0, 22 \n" \
\r
536 " bne r2, r22, RegTest2Error \n" \
\r
537 " addi r2, r0, 23 \n" \
\r
538 " bne r2, r23, RegTest2Error \n" \
\r
539 " addi r2, r0, 28 \n" \
\r
540 " bne r2, r28, RegTest2Error \n" \
\r
541 " addi r2, r0, 31 \n" \
\r
542 " bne r2, r31, RegTest2Error \n" \
\r
543 " ldw r2, %gprel(ulRegTest2Counter)(gp) \n" \
\r
544 " addi r2, r2, 1 \n" \
\r
545 " stw r2, %gprel(ulRegTest2Counter)(gp) \n" \
\r
546 " br RegTest2 \n" \
\r
547 "RegTest2Error: \n" \
\r
548 " br RegTest2Error \n"
\r
551 /*-----------------------------------------------------------*/
\r