]> begriffs open source - cmsis-freertos/blob - Demo/RX600_RX62N-RSK_Renesas/RTOSDemo/main-full.c
Updated to FreeRTOS V10.0.1
[cmsis-freertos] / Demo / RX600_RX62N-RSK_Renesas / RTOSDemo / main-full.c
1 /*
2  * FreeRTOS Kernel V10.0.1
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
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:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
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.
21  *
22  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /* ****************************************************************************
29  * This project includes a lot of tasks and tests and is therefore complex.
30  * If you would prefer a much simpler project to get started with then select
31  * the 'Blinky' build configuration within the HEW IDE.
32  * ****************************************************************************
33  *
34  * Creates all the demo application tasks, then starts the scheduler.  The web
35  * documentation provides more details of the standard demo application tasks,
36  * which provide no particular functionality but do provide a good example of
37  * how to use the FreeRTOS API.  The tasks defined in flop.c are included in the
38  * set of standard demo tasks to ensure the floating point unit gets some
39  * exercise.
40  *
41  * In addition to the standard demo tasks, the following tasks and tests are
42  * defined and/or created within this file:
43  *
44  * Webserver ("uIP") task - This serves a number of dynamically generated WEB
45  * pages to a standard WEB browser.  The IP and MAC addresses are configured by
46  * constants defined at the bottom of FreeRTOSConfig.h.  Use either a standard
47  * Ethernet cable to connect through a hug, or a cross over (point to point)
48  * cable to connect directly.  Ensure the IP address used is compatible with the
49  * IP address of the machine running the browser - the easiest way to achieve
50  * this is to ensure the first three octets of the IP addresses are the same.
51  *
52  * "Reg test" tasks - These fill the registers with known values, then check
53  * that each register still contains its expected value.  Each task uses
54  * different values.  The tasks run with very low priority so get preempted
55  * very frequently.  A check variable is incremented on each iteration of the
56  * test loop.  A register containing an unexpected value is indicative of an
57  * error in the context switching mechanism and will result in a branch to a
58  * null loop - which in turn will prevent the check variable from incrementing
59  * any further and allow the check task (described below) to determine that an
60  * error has occurred.  The nature of the reg test tasks necessitates that they
61  * are written in assembly code.
62  *
63  * "Check" task - This only executes every five seconds but has a high priority
64  * to ensure it gets processor time.  Its main function is to check that all the
65  * standard demo tasks are still operational.  While no errors have been
66  * discovered the check task will toggle LED 5 every 5 seconds - the toggle
67  * rate increasing to 200ms being a visual indication that at least one task has
68  * reported unexpected behaviour.
69  *
70  * "High frequency timer test" - A high frequency periodic interrupt is
71  * generated using a timer - the interrupt is assigned a priority above
72  * configMAX_SYSCALL_INTERRUPT_PRIORITY so should not be effected by anything
73  * the kernel is doing.  The frequency and priority of the interrupt, in
74  * combination with other standard tests executed in this demo, should result
75  * in interrupts nesting at least 3 and probably 4 deep.  This test is only
76  * included in build configurations that have the optimiser switched on.  In
77  * optimised builds the count of high frequency ticks is used as the time base
78  * for the run time stats.
79  *
80  * *NOTE 1* If LED5 is toggling every 5 seconds then all the demo application
81  * tasks are executing as expected and no errors have been reported in any
82  * tasks.  The toggle rate increasing to 200ms indicates that at least one task
83  * has reported unexpected behaviour.
84  *
85  * *NOTE 2* vApplicationSetupTimerInterrupt() is called by the kernel to let
86  * the application set up a timer to generate the tick interrupt.  In this
87  * example a compare match timer is used for this purpose.
88  *
89  * *NOTE 3* The CPU must be in Supervisor mode when the scheduler is started.
90  * The PowerON_Reset_PC() supplied in resetprg.c with this demo has
91  * Change_PSW_PM_to_UserMode() commented out to ensure this is the case.
92  *
93  * *NOTE 4* The IntQueue common demo tasks test interrupt nesting and make use
94  * of all the 8bit timers (as two cascaded 16bit units).
95 */
96
97 /* Hardware specific includes. */
98 #include "iodefine.h"
99
100 /* Kernel includes. */
101 #include "FreeRTOS.h"
102 #include "task.h"
103
104 /* Standard demo includes. */
105 #include "partest.h"
106 #include "flash.h"
107 #include "IntQueue.h"
108 #include "BlockQ.h"
109 #include "death.h"
110 #include "integer.h"
111 #include "blocktim.h"
112 #include "semtest.h"
113 #include "PollQ.h"
114 #include "GenQTest.h"
115 #include "QPeek.h"
116 #include "recmutex.h"
117 #include "flop.h"
118
119 /* Values that are passed into the reg test tasks using the task parameter.  The
120 tasks check that the values are passed in correctly. */
121 #define mainREG_TEST_1_PARAMETER        ( 0x12121212UL )
122 #define mainREG_TEST_2_PARAMETER        ( 0x12345678UL )
123
124 /* Priorities at which the tasks are created. */
125 #define mainCHECK_TASK_PRIORITY         ( configMAX_PRIORITIES - 1 )
126 #define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 1 )
127 #define mainSEM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 1 )
128 #define mainBLOCK_Q_PRIORITY            ( tskIDLE_PRIORITY + 2 )
129 #define mainCREATOR_TASK_PRIORITY   ( tskIDLE_PRIORITY + 3 )
130 #define mainFLASH_TASK_PRIORITY         ( tskIDLE_PRIORITY + 1 )
131 #define mainuIP_TASK_PRIORITY           ( tskIDLE_PRIORITY + 2 )
132 #define mainINTEGER_TASK_PRIORITY   ( tskIDLE_PRIORITY )
133 #define mainGEN_QUEUE_TASK_PRIORITY     ( tskIDLE_PRIORITY )
134 #define mainFLOP_TASK_PRIORITY          ( tskIDLE_PRIORITY )
135
136 /* The WEB server uses string handling functions, which in turn use a bit more
137 stack than most of the other tasks. */
138 #define mainuIP_STACK_SIZE                      ( configMINIMAL_STACK_SIZE * 3 )
139
140 /* The LED toggled by the check task. */
141 #define mainCHECK_LED                           ( 5 )
142
143 /* The rate at which mainCHECK_LED will toggle when all the tasks are running
144 without error.  Controlled by the check task as described at the top of this
145 file. */
146 #define mainNO_ERROR_CYCLE_TIME         ( 5000 / portTICK_PERIOD_MS )
147
148 /* The rate at which mainCHECK_LED will toggle when an error has been reported
149 by at least one task.  Controlled by the check task as described at the top of
150 this file. */
151 #define mainERROR_CYCLE_TIME            ( 200 / portTICK_PERIOD_MS )
152
153 /*
154  * vApplicationMallocFailedHook() will only be called if
155  * configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
156  * function that will execute if a call to pvPortMalloc() fails.
157  * pvPortMalloc() is called internally by the kernel whenever a task, queue or
158  * semaphore is created.  It is also called by various parts of the demo
159  * application.
160  */
161 void vApplicationMallocFailedHook( void );
162
163 /*
164  * vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set to 1
165  * in FreeRTOSConfig.h.  It is a hook function that is called on each iteration
166  * of the idle task.  It is essential that code added to this hook function
167  * never attempts to block in any way (for example, call xQueueReceive() with
168  * a block time specified).  If the application makes use of the vTaskDelete()
169  * API function (as this demo application does) then it is also important that
170  * vApplicationIdleHook() is permitted to return to its calling function because
171  * it is the responsibility of the idle task to clean up memory allocated by the
172  * kernel to any task that has since been deleted.
173  */
174 void vApplicationIdleHook( void );
175
176 /*
177  * vApplicationStackOverflowHook() will only be called if
178  * configCHECK_FOR_STACK_OVERFLOW is set to a non-zero value.  The handle and
179  * name of the offending task should be passed in the function parameters, but
180  * it is possible that the stack overflow will have corrupted these - in which
181  * case pxCurrentTCB can be inspected to find the same information.
182  */
183 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
184
185 /*
186  * The reg test tasks as described at the top of this file.
187  */
188 static void prvRegTest1Task( void *pvParameters );
189 static void prvRegTest2Task( void *pvParameters );
190
191 /*
192  * The actual implementation of the reg test functionality, which, because of
193  * the direct register access, have to be in assembly.
194  */
195 static void prvRegTest1Implementation( void );
196 static void prvRegTest2Implementation( void );
197
198 /*
199  * The check task as described at the top of this file.
200  */
201 static void prvCheckTask( void *pvParameters );
202
203 /*
204  * Contains the implementation of the WEB server.
205  */
206 extern void vuIP_Task( void *pvParameters );
207
208 /*-----------------------------------------------------------*/
209
210 /* Variables that are incremented on each iteration of the reg test tasks -
211 provided the tasks have not reported any errors.  The check task inspects these
212 variables to ensure they are still incrementing as expected.  If a variable
213 stops incrementing then it is likely that its associate task has stalled. */
214 unsigned long ulRegTest1CycleCount = 0UL, ulRegTest2CycleCount = 0UL;
215
216 /* The status message that is displayed at the bottom of the "task stats" web
217 page, which is served by the uIP task.  This will report any errors picked up
218 by the reg test task. */
219 const char *pcStatusMessage = "All tasks executing without error.";
220
221 /*-----------------------------------------------------------*/
222
223 void main(void)
224 {
225 extern void HardwareSetup( void );
226
227         /* Renesas provided CPU configuration routine.  The clocks are configured in
228         here. */
229         HardwareSetup();
230
231         /* Turn all LEDs off. */
232         vParTestInitialise();
233
234         /* Start the reg test tasks which test the context switching mechanism. */
235         xTaskCreate( prvRegTest1Task, "RegTst1", configMINIMAL_STACK_SIZE, ( void * ) mainREG_TEST_1_PARAMETER, tskIDLE_PRIORITY, NULL );
236         xTaskCreate( prvRegTest2Task, "RegTst2", configMINIMAL_STACK_SIZE, ( void * ) mainREG_TEST_2_PARAMETER, tskIDLE_PRIORITY, NULL );
237
238         /* The web server task. */
239         xTaskCreate( vuIP_Task, "uIP", mainuIP_STACK_SIZE, NULL, mainuIP_TASK_PRIORITY, NULL );
240
241         /* Start the check task as described at the top of this file. */
242         xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE * 3, NULL, mainCHECK_TASK_PRIORITY, NULL );
243
244         /* Create the standard demo tasks. */
245         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
246         vCreateBlockTimeTasks();
247         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
248         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
249         vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
250         vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
251         vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );
252         vStartQueuePeekTasks();
253         vStartRecursiveMutexTasks();
254         vStartInterruptQueueTasks();
255         vStartMathTasks( mainFLOP_TASK_PRIORITY );
256
257         /* The suicide tasks must be created last as they need to know how many
258         tasks were running prior to their creation in order to ascertain whether
259         or not the correct/expected number of tasks are running at any given time. */
260         vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
261
262         /* Start the tasks running. */
263         vTaskStartScheduler();
264
265         /* If all is well we will never reach here as the scheduler will now be
266         running.  If we do reach here then it is likely that there was insufficient
267         heap available for the idle task to be created. */
268         for( ;; );
269 }
270 /*-----------------------------------------------------------*/
271
272 static void prvCheckTask( void *pvParameters )
273 {
274 static volatile unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL;
275 TickType_t xNextWakeTime, xCycleFrequency = mainNO_ERROR_CYCLE_TIME;
276 extern void vSetupHighFrequencyTimer( void );
277
278         /* If this is being executed then the kernel has been started.  Start the high
279         frequency timer test as described at the top of this file.  This is only
280         included in the optimised build configuration - otherwise it takes up too much
281         CPU time and can disrupt other tests. */
282         #ifdef INCLUDE_HIGH_FREQUENCY_TIMER_TEST
283                 vSetupHighFrequencyTimer();
284         #endif
285
286         /* Initialise xNextWakeTime - this only needs to be done once. */
287         xNextWakeTime = xTaskGetTickCount();
288
289         for( ;; )
290         {
291                 /* Place this task in the blocked state until it is time to run again. */
292                 vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );
293
294                 /* Check the standard demo tasks are running without error. */
295                 if( xAreGenericQueueTasksStillRunning() != pdTRUE )
296                 {
297                         /* Increase the rate at which this task cycles, which will increase the
298                         rate at which mainCHECK_LED flashes to give visual feedback that an error
299                         has occurred. */
300                         xCycleFrequency = mainERROR_CYCLE_TIME;
301                         pcStatusMessage = "Error: GenQueue";
302                 }
303                 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
304                 {
305                         xCycleFrequency = mainERROR_CYCLE_TIME;
306                         pcStatusMessage = "Error: QueuePeek";
307                 }
308                 else if( xAreBlockingQueuesStillRunning() != pdTRUE )
309                 {
310                         xCycleFrequency = mainERROR_CYCLE_TIME;
311                         pcStatusMessage = "Error: BlockQueue";
312                 }
313                 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
314                 {
315                         xCycleFrequency = mainERROR_CYCLE_TIME;
316                         pcStatusMessage = "Error: BlockTime";
317                 }
318                 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
319                 {
320                         xCycleFrequency = mainERROR_CYCLE_TIME;
321                         pcStatusMessage = "Error: SemTest";
322                 }
323                 else if( xArePollingQueuesStillRunning() != pdTRUE )
324                 {
325                         xCycleFrequency = mainERROR_CYCLE_TIME;
326                         pcStatusMessage = "Error: PollQueue";
327                 }
328                 else if( xIsCreateTaskStillRunning() != pdTRUE )
329                 {
330                         xCycleFrequency = mainERROR_CYCLE_TIME;
331                         pcStatusMessage = "Error: Death";
332                 }
333                 else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
334                 {
335                         xCycleFrequency = mainERROR_CYCLE_TIME;
336                         pcStatusMessage = "Error: IntMath";
337                 }
338                 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
339                 {
340                         xCycleFrequency = mainERROR_CYCLE_TIME;
341                         pcStatusMessage = "Error: RecMutex";
342                 }
343                 else if( xAreIntQueueTasksStillRunning() != pdPASS )
344                 {
345                         xCycleFrequency = mainERROR_CYCLE_TIME;
346                         pcStatusMessage = "Error: IntQueue";
347                 }
348                 else if( xAreMathsTaskStillRunning() != pdPASS )
349                 {
350                         xCycleFrequency = mainERROR_CYCLE_TIME;
351                         pcStatusMessage = "Error: Flop";
352                 }
353
354                 /* Check the reg test tasks are still cycling.  They will stop incrementing
355                 their loop counters if they encounter an error. */
356                 if( ulRegTest1CycleCount == ulLastRegTest1CycleCount )
357                 {
358                         xCycleFrequency = mainERROR_CYCLE_TIME;
359                         pcStatusMessage = "Error: RegTest1";
360                 }
361
362                 if( ulRegTest2CycleCount == ulLastRegTest2CycleCount )
363                 {
364                         xCycleFrequency = mainERROR_CYCLE_TIME;
365                         pcStatusMessage = "Error: RegTest2";
366                 }
367
368                 ulLastRegTest1CycleCount = ulRegTest1CycleCount;
369                 ulLastRegTest2CycleCount = ulRegTest2CycleCount;
370
371                 /* Toggle the check LED to give an indication of the system status.  If
372                 the LED toggles every 5 seconds then everything is ok.  A faster toggle
373                 indicates an error. */
374                 vParTestToggleLED( mainCHECK_LED );
375         }
376 }
377 /*-----------------------------------------------------------*/
378
379 /* The RX port uses this callback function to configure its tick interrupt.
380 This allows the application to choose the tick interrupt source. */
381 void vApplicationSetupTimerInterrupt( void )
382 {
383         /* Enable compare match timer 0. */
384         MSTP( CMT0 ) = 0;
385
386         /* Interrupt on compare match. */
387         CMT0.CMCR.BIT.CMIE = 1;
388
389         /* Set the compare match value. */
390         CMT0.CMCOR = ( unsigned short ) ( ( ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ ) -1 ) / 8 );
391
392         /* Divide the PCLK by 8. */
393         CMT0.CMCR.BIT.CKS = 0;
394
395         /* Enable the interrupt... */
396         _IEN( _CMT0_CMI0 ) = 1;
397
398         /* ...and set its priority to the application defined kernel priority. */
399         _IPR( _CMT0_CMI0 ) = configKERNEL_INTERRUPT_PRIORITY;
400
401         /* Start the timer. */
402         CMT.CMSTR0.BIT.STR0 = 1;
403 }
404 /*-----------------------------------------------------------*/
405
406 /* This function is explained by the comments above its prototype at the top
407 of this file. */
408 void vApplicationMallocFailedHook( void )
409 {
410         for( ;; );
411 }
412 /*-----------------------------------------------------------*/
413
414 /* This function is explained by the comments above its prototype at the top
415 of this file. */
416 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
417 {
418         for( ;; );
419 }
420 /*-----------------------------------------------------------*/
421
422 /* This function is explained by the comments above its prototype at the top
423 of this file. */
424 void vApplicationIdleHook( void )
425 {
426 }
427 /*-----------------------------------------------------------*/
428
429 /* This function is explained in the comments at the top of this file. */
430 static void prvRegTest1Task( void *pvParameters )
431 {
432         if( ( ( unsigned long ) pvParameters ) != mainREG_TEST_1_PARAMETER )
433         {
434                 /* The parameter did not contain the expected value. */
435                 for( ;; )
436                 {
437                         /* Stop the tick interrupt so its obvious something has gone wrong. */
438                         taskDISABLE_INTERRUPTS();
439                 }
440         }
441
442         /* This is an inline asm function that never returns. */
443         prvRegTest1Implementation();
444 }
445 /*-----------------------------------------------------------*/
446
447 /* This function is explained in the comments at the top of this file. */
448 static void prvRegTest2Task( void *pvParameters )
449 {
450         if( ( ( unsigned long ) pvParameters ) != mainREG_TEST_2_PARAMETER )
451         {
452                 /* The parameter did not contain the expected value. */
453                 for( ;; )
454                 {
455                         /* Stop the tick interrupt so its obvious something has gone wrong. */
456                         taskDISABLE_INTERRUPTS();
457                 }
458         }
459
460         /* This is an inline asm function that never returns. */
461         prvRegTest2Implementation();
462 }
463 /*-----------------------------------------------------------*/
464
465 /* This function is explained in the comments at the top of this file. */
466 #pragma inline_asm prvRegTest1Implementation
467 static void prvRegTest1Implementation( void )
468 {
469         ; Put a known value in each register.
470         MOV.L   #1, R1
471         MOV.L   #2, R2
472         MOV.L   #3, R3
473         MOV.L   #4, R4
474         MOV.L   #5, R5
475         MOV.L   #6, R6
476         MOV.L   #7, R7
477         MOV.L   #8, R8
478         MOV.L   #9, R9
479         MOV.L   #10, R10
480         MOV.L   #11, R11
481         MOV.L   #12, R12
482         MOV.L   #13, R13
483         MOV.L   #14, R14
484         MOV.L   #15, R15
485
486         ; Loop, checking each iteration that each register still contains the
487         ; expected value.
488 TestLoop1:
489
490         ; Push the registers that are going to get clobbered.
491         PUSHM   R14-R15
492
493         ; Increment the loop counter to show this task is still getting CPU time.
494         MOV.L   #_ulRegTest1CycleCount, R14
495         MOV.L   [ R14 ], R15
496         ADD             #1, R15
497         MOV.L   R15, [ R14 ]
498
499         ; Yield to extend the text coverage.  Set the bit in the ITU SWINTR register.
500         MOV.L   #1, R14
501         MOV.L   #0872E0H, R15
502         MOV.B   R14, [R15]
503         NOP
504         NOP
505
506         ; Restore the clobbered registers.
507         POPM    R14-R15
508
509         ; Now compare each register to ensure it still contains the value that was
510         ; set before this loop was entered.
511         CMP             #1, R1
512         BNE             RegTest1Error
513         CMP             #2, R2
514         BNE             RegTest1Error
515         CMP             #3, R3
516         BNE             RegTest1Error
517         CMP             #4, R4
518         BNE             RegTest1Error
519         CMP             #5, R5
520         BNE             RegTest1Error
521         CMP             #6, R6
522         BNE             RegTest1Error
523         CMP             #7, R7
524         BNE             RegTest1Error
525         CMP             #8, R8
526         BNE             RegTest1Error
527         CMP             #9, R9
528         BNE             RegTest1Error
529         CMP             #10, R10
530         BNE             RegTest1Error
531         CMP             #11, R11
532         BNE             RegTest1Error
533         CMP             #12, R12
534         BNE             RegTest1Error
535         CMP             #13, R13
536         BNE             RegTest1Error
537         CMP             #14, R14
538         BNE             RegTest1Error
539         CMP             #15, R15
540         BNE             RegTest1Error
541
542         ; All comparisons passed, start a new itteratio of this loop.
543         BRA             TestLoop1
544
545 RegTest1Error:
546         ; A compare failed, just loop here so the loop counter stops incrementing
547         ; causing the check task to indicate the error.
548         BRA RegTest1Error
549 }
550 /*-----------------------------------------------------------*/
551
552 /* This function is explained in the comments at the top of this file. */
553 #pragma inline_asm prvRegTest2Implementation
554 static void prvRegTest2Implementation( void )
555 {
556         ; Put a known value in each register.
557         MOV.L   #10, R1
558         MOV.L   #20, R2
559         MOV.L   #30, R3
560         MOV.L   #40, R4
561         MOV.L   #50, R5
562         MOV.L   #60, R6
563         MOV.L   #70, R7
564         MOV.L   #80, R8
565         MOV.L   #90, R9
566         MOV.L   #100, R10
567         MOV.L   #110, R11
568         MOV.L   #120, R12
569         MOV.L   #130, R13
570         MOV.L   #140, R14
571         MOV.L   #150, R15
572
573         ; Loop, checking on each iteration that each register still contains the
574         ; expected value.
575 TestLoop2:
576
577         ; Push the registers that are going to get clobbered.
578         PUSHM   R14-R15
579
580         ; Increment the loop counter to show this task is still getting CPU time.
581         MOV.L   #_ulRegTest2CycleCount, R14
582         MOV.L   [ R14 ], R15
583         ADD             #1, R15
584         MOV.L   R15, [ R14 ]
585
586         ; Restore the clobbered registers.
587         POPM    R14-R15
588
589         CMP             #10, R1
590         BNE             RegTest2Error
591         CMP             #20, R2
592         BNE             RegTest2Error
593         CMP             #30, R3
594         BNE             RegTest2Error
595         CMP             #40, R4
596         BNE             RegTest2Error
597         CMP             #50, R5
598         BNE             RegTest2Error
599         CMP             #60, R6
600         BNE             RegTest2Error
601         CMP             #70, R7
602         BNE             RegTest2Error
603         CMP             #80, R8
604         BNE             RegTest2Error
605         CMP             #90, R9
606         BNE             RegTest2Error
607         CMP             #100, R10
608         BNE             RegTest2Error
609         CMP             #110, R11
610         BNE             RegTest2Error
611         CMP             #120, R12
612         BNE             RegTest2Error
613         CMP             #130, R13
614         BNE             RegTest2Error
615         CMP             #140, R14
616         BNE             RegTest2Error
617         CMP             #150, R15
618         BNE             RegTest2Error
619
620         ; All comparisons passed, start a new itteratio of this loop.
621         BRA             TestLoop2
622
623 RegTest2Error:
624         ; A compare failed, just loop here so the loop counter stops incrementing
625         ; - causing the check task to indicate the error.
626         BRA RegTest2Error
627 }
628 /*-----------------------------------------------------------*/
629
630 char *pcGetTaskStatusMessage( void )
631 {
632         /* Not bothered about a critical section here although technically because of
633         the task priorities the pointer could change it will be atomic if not near
634         atomic and its not critical. */
635         return ( char * ) pcStatusMessage;
636 }
637 /*-----------------------------------------------------------*/
638
639