TriCore demo: Add comments and modify the reg test tasks to give a better change of error detection.

pull/4/head
Richard Barry 13 years ago
parent 45fe448d73
commit dd10b91fc4

@ -51,6 +51,10 @@
licensing and training services. licensing and training services.
*/ */
/* _RB_ Add description here. */
/* Standard includes. */ /* Standard includes. */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -77,14 +81,14 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Constants for the ComTest tasks. */ /* Constants for the ComTest tasks. */
#define mainCOM_TEST_BAUD_RATE ( ( unsigned long ) 115200 ) #define mainCOM_TEST_BAUD_RATE ( ( unsigned long ) 115200 )
#define mainCOM_TEST_LED ( 5 ) #define mainCOM_TEST_LED ( 5 )
/* Priorities for the demo application tasks. */ /* Priorities for the demo application tasks. */
#define mainLED_TASK_PRIORITY ( ( tskIDLE_PRIORITY + 1 ) | portPRIVILEGE_BIT ) #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainCOM_TEST_PRIORITY ( ( tskIDLE_PRIORITY + 2 ) | portPRIVILEGE_BIT ) #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainCHECK_TASK_PRIORITY ( ( tskIDLE_PRIORITY + 4 ) | portPRIVILEGE_BIT ) #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 4 )
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
@ -93,7 +97,7 @@ error. */
#define mainNO_ERROR_FLASH_PERIOD ( ( portTickType ) 5000 / portTICK_RATE_MS ) #define mainNO_ERROR_FLASH_PERIOD ( ( portTickType ) 5000 / portTICK_RATE_MS )
#define mainERROR_FLASH_PERIOD ( ( portTickType ) 500 / portTICK_RATE_MS ) #define mainERROR_FLASH_PERIOD ( ( portTickType ) 500 / portTICK_RATE_MS )
#define mainON_BOARD_LED_BIT ( ( unsigned long ) 7 ) #define mainON_BOARD_LED_BIT ( ( unsigned long ) 7 )
#define mainREG_TEST_TASKS 1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -107,51 +111,43 @@ static long prvCheckOtherTasksAreStillRunning( void );
* prvCheckOtherTasksAreStillRunning(). See the description at the top * prvCheckOtherTasksAreStillRunning(). See the description at the top
* of the file. * of the file.
*/ */
static void vErrorChecks( void *pvParameters ); static void prvCheckTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* /*
* Configure the processor for use with the Olimex demo board. This includes * Configure the processor ready to run this demo.
* setup for the I/O, system clock, and access timings.
*/ */
static void prvSetupHardware( void ); static void prvSetupHardware( void );
/*
* Function to create the heavily restricted RegTest tasks.
*/
static void vStartRegTestTasks( unsigned portBASE_TYPE uxPriority );
#if mainREG_TEST_TASKS == 1
/* /*
* Writes to and checks the value of each register that is used in the context * Writes to and checks the value of each register that is used in the context
* of a task. * of a task.
*/ */
static void vRegTask1( void *pvParameters ); static void prvRegTask1( void *pvParameters );
static void vRegTask2( void *pvParameters ); static void prvRegTask2( void *pvParameters );
/* /*
* Specific check to see if the Register test functions are still operating. * Specific check to see if the Register test functions are still operating
* correctly.
*/ */
static portBASE_TYPE xAreRegTestTasksStillRunning( void ); static portBASE_TYPE prvAreRegTestTasksStillRunning( void );
#endif /* mainREG_TEST_TASKS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Used by the register test tasks to indicated liveness. */ /* Used by the register test tasks to indicated liveness. */
static unsigned long ulRegisterTest1Count = 0; static unsigned long ulRegisterTest1Count = 0;
static unsigned long ulRegisterTest2Count = 0; static unsigned long ulRegisterTest2Count = 0;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* Starts all the other tasks, then starts the scheduler. * Starts all the tasks, then starts the scheduler.
*/ */
int main( void ) int main( void )
{ {
/* Setup the hardware for use with the TriCore evaluation board. */ /* Setup the hardware for use with the TriCore evaluation board. */
prvSetupHardware(); prvSetupHardware();
/* Start the demo/test application tasks. */ /* Start standard demo/test application tasks. */
vStartIntegerMathTasks( tskIDLE_PRIORITY ); vStartIntegerMathTasks( tskIDLE_PRIORITY );
vStartLEDFlashTasks( mainLED_TASK_PRIORITY ); vStartLEDFlashTasks( mainLED_TASK_PRIORITY );
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
@ -163,41 +159,60 @@ int main( void )
vStartGenericQueueTasks( tskIDLE_PRIORITY ); vStartGenericQueueTasks( tskIDLE_PRIORITY );
vStartRecursiveMutexTasks(); vStartRecursiveMutexTasks();
vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED ); vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );
vStartRegTestTasks( tskIDLE_PRIORITY ); /* _RB_ Create the timer test task here too. */
/* Create the register test tasks, as described at the top of this file. */
xTaskCreate( prvRegTask1, ( signed char * ) "Reg 1", configMINIMAL_STACK_SIZE, &ulRegisterTest1Count, tskIDLE_PRIORITY, NULL );
xTaskCreate( prvRegTask2, ( signed char * ) "Reg 2", configMINIMAL_STACK_SIZE, &ulRegisterTest2Count, tskIDLE_PRIORITY, NULL );
/* Start the check task - which is defined in this file. */ /* Start the check task - which is defined in this file. */
xTaskCreate( vErrorChecks, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); xTaskCreate( prvCheckTask, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
/* _RB_ start the death tasks here too. */
/* Now all the tasks have been started - start the scheduler. */ /* Now all the tasks have been started - start the scheduler. */
vTaskStartScheduler(); vTaskStartScheduler();
/* Should never reach here! */ /* If all is well then the following line will never be reached. If
execution does reach here, then it is highly probably that the heap size
is too small for the idle and/or timer tasks to be created within
vTaskStartScheduler(). */
for( ;; ); for( ;; );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void vErrorChecks( void *pvParameters ) static void prvCheckTask( void *pvParameters )
{ {
portTickType xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; portTickType xDelayPeriod = mainNO_ERROR_FLASH_PERIOD;
portTickType xLastExecutionTime;
/* Just to stop compiler warnings. */ /* Just to stop compiler warnings. */
( void ) pvParameters; ( void ) pvParameters;
/* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()
works correctly. */
xLastExecutionTime = xTaskGetTickCount();
/* Cycle for ever, delaying then checking all the other tasks are still /* Cycle for ever, delaying then checking all the other tasks are still
operating without error. If an error is detected then the delay period operating without error. If an error is detected then the delay period
is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so
the on board LED flash rate will increase. */ the on board LED flash rate will increase. NOTE: This task could easily
be replaced by a software timer callback to remove the overhead of having
an extra task. */
for( ;; ) for( ;; )
{ {
/* Delay until it is time to execute again. */ /* Delay until it is time to execute again. */
vTaskDelay( xDelayPeriod ); vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod );
/* Check all the standard demo application tasks are executing without /* Check all the standard demo application tasks are executing without
error. */ error. */
if( prvCheckOtherTasksAreStillRunning() != pdPASS ) if( prvCheckOtherTasksAreStillRunning() != pdPASS )
{ {
/* An error has been detected in one of the tasks - flash faster. */ /* An error has been detected in one of the tasks - flash the LED
at a higher frequency to give visible feedback that something has
gone wrong (it might just be that the loop back connector required
by the comtest tasks has not been fitted). */
xDelayPeriod = mainERROR_FLASH_PERIOD; xDelayPeriod = mainERROR_FLASH_PERIOD;
} }
@ -213,8 +228,7 @@ static long prvCheckOtherTasksAreStillRunning( void )
long lReturn = pdPASS; long lReturn = pdPASS;
/* Check all the demo tasks (other than the flash tasks) to ensure /* Check all the demo tasks (other than the flash tasks) to ensure
that they are all still running, and that none of them have detected that they are all still running, and that none have detected an error. */
an error. */
if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
{ {
@ -261,7 +275,7 @@ long lReturn = pdPASS;
lReturn = pdFAIL; lReturn = pdFAIL;
} }
if( xAreRegTestTasksStillRunning() != pdTRUE ) if( prvAreRegTestTasksStillRunning() != pdTRUE )
{ {
lReturn = pdFAIL; lReturn = pdFAIL;
} }
@ -284,53 +298,63 @@ extern void set_cpu_frequency(void);
void vApplicationMallocFailedHook( void ) void vApplicationMallocFailedHook( void )
{ {
/* This function will be called if a call to pvPortMalloc() fails to return /* vApplicationMallocFailedHook() will only be called if
the requested memory. pvPortMalloc() is called internally by the scheduler configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
whenever a task, queue or semaphore is created. */ function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue,
timer or semaphore is created. It is also called by various parts of the
demo application. If heap_1.c or heap_2.c are used, then the size of the
heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
_debug(); _debug();
taskDISABLE_INTERRUPTS();
for( ;; ); for( ;; );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vApplicationTickHook( void ) void vApplicationTickHook( void )
{ {
/* /* vApplicationTickHook() will only be called if configUSE_TICK_HOOK is set
* This function will be called whenever the system tick is incremented. to 1 in FreeRTOSConfig.h. It is a hook function that will get called during
* Note that it is executed as part of an interrupt and as such should each FreeRTOS tick interrupt. Note that vApplicationTickHook() is called
* not block nor be used for any long running execution. from an interrupt context. */
*/
vParTestToggleLED( mainON_BOARD_LED_BIT - 1 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vApplicationIdleHook( void ) void vApplicationIdleHook( void )
{ {
/* /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
* This function will be called during the normal execution of the IDLE task. to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
*/ task. It is essential that code added to this hook function never attempts
} to block in any way (for example, call xQueueReceive() with a block time
/*-----------------------------------------------------------*/ specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
#if mainREG_TEST_TASKS == 1 important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
static void vStartRegTestTasks( unsigned portBASE_TYPE uxPriority ) memory allocated by the kernel to any task that has since been deleted. */
{
(void)xTaskCreate( vRegTask1, ( signed char * ) "Reg 1", configMINIMAL_STACK_SIZE, &ulRegisterTest1Count, uxPriority, NULL );
(void)xTaskCreate( vRegTask2, ( signed char * ) "Reg 2", configMINIMAL_STACK_SIZE, &ulRegisterTest2Count, uxPriority, NULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portBASE_TYPE xAreRegTestTasksStillRunning( void ) static portBASE_TYPE prvAreRegTestTasksStillRunning( void )
{ {
static unsigned long ulPreviousRegisterTest1Count = 0; static unsigned long ulPreviousRegisterTest1Count = 0;
static unsigned long ulPreviousRegisterTest2Count = 0; static unsigned long ulPreviousRegisterTest2Count = 0;
portBASE_TYPE xReturn = pdFALSE; portBASE_TYPE xReturn = pdPASS;
/* Check to see if the Counts have changed since the last check. */ /* Check to see if the Counts have changed since the last check. */
xReturn = ( ulPreviousRegisterTest1Count != ulRegisterTest1Count ); if( ulRegisterTest1Count == ulPreviousRegisterTest1Count )
xReturn = xReturn && ( ulPreviousRegisterTest2Count != ulRegisterTest2Count ); {
xReturn = pdFAIL;
}
/* Record the last count. */ if( ulRegisterTest2Count == ulPreviousRegisterTest2Count )
{
xReturn = pdFAIL;
}
/* Remember the current count for the next time this function is called. */
ulPreviousRegisterTest1Count = ulRegisterTest1Count; ulPreviousRegisterTest1Count = ulRegisterTest1Count;
ulPreviousRegisterTest2Count = ulRegisterTest2Count; ulPreviousRegisterTest2Count = ulRegisterTest2Count;
@ -338,12 +362,7 @@ portBASE_TYPE xReturn = pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* static void prvRegTask1( void *pvParameters )
* Set all of the registers that are used as part of the task context
* to known values and test that those values are maintained across
* context switches.
*/
void vRegTask1( void *pvParameters )
{ {
/* Make space on the stack for the parameter and a counter. */ /* Make space on the stack for the parameter and a counter. */
__asm volatile( " sub.a %sp, 4 \n" __asm volatile( " sub.a %sp, 4 \n"
@ -351,114 +370,107 @@ void vRegTask1( void *pvParameters )
" mov %d15, 0 \n" " mov %d15, 0 \n"
" st.w [%sp]4, %d15 \n" ); " st.w [%sp]4, %d15 \n" );
for (;;) /* Change all of the Context sensitive registers (except SP and RA). */
{ __asm volatile(
/* Change all of the Context sensitive registers (except SP and RA). */ " mov %d0, 0 \n"
__asm volatile( " mov %d1, 1 \n"
" mov %d0, 0 \n" " mov %d2, 2 \n"
" mov %d1, 1 \n" " mov %d3, 3 \n"
" mov %d2, 2 \n" " mov %d4, 4 \n"
" mov %d3, 3 \n" " mov %d5, 5 \n"
" mov %d4, 4 \n" " mov %d6, 6 \n"
" mov %d5, 5 \n" " mov %d7, 7 \n"
" mov %d6, 6 \n" " mov %d8, 8 \n"
" mov %d7, 7 \n" " mov %d9, 9 \n"
" mov %d8, 8 \n" " mov %d10, 10 \n"
" mov %d9, 9 \n" " mov %d11, 11 \n"
" mov %d10, 10 \n" " mov %d12, 12 \n"
" mov %d11, 11 \n" " mov %d13, 13 \n"
" mov %d12, 12 \n" " mov %d14, 14 \n"
" mov %d13, 13 \n" " mov %d15, 15 \n"
" mov %d14, 14 \n" " mov.a %a2, 2 \n"
" mov %d15, 15 \n" " mov.a %a3, 3 \n"
" mov.a %a2, 2 \n" " mov.a %a4, 4 \n"
" mov.a %a3, 3 \n" " mov.a %a5, 5 \n"
" mov.a %a4, 4 \n" " mov.a %a6, 6 \n"
" mov.a %a5, 5 \n" " mov.a %a7, 7 \n"
" mov.a %a6, 6 \n" " mov.a %a12, 12 \n"
" mov.a %a7, 7 \n" " mov.a %a13, 13 \n"
" mov.a %a12, 12 \n" " mov.a %a14, 14 \n" );
" mov.a %a13, 13 \n"
" mov.a %a14, 14 \n" ); /* Check the values of the registers. */
/* Yield to force a context switch. */ __asm( " _task1_loop: \n" \
taskYIELD(); " eq %d1, %d0, 0 \n" \
/* Check the values of the registers. */ " jne %d1, 1, _task1_error_loop \n" \
__asm( " eq %d0, %d0, 0 \n" \ " eq %d1, %d1, 1 \n" \
" jne %d0, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d1, %d1, 1 \n" \ " eq %d1, %d2, 2 \n" \
" jne %d1, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d2, %d2, 2 \n" \ " eq %d1, %d3, 3 \n" \
" jne %d2, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d3, %d3, 3 \n" \ " eq %d1, %d4, 4 \n" \
" jne %d3, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d4, %d4, 4 \n" \ " eq %d1, %d5, 5 \n" \
" jne %d4, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d5, %d5, 5 \n" \ " eq %d1, %d6, 6 \n" \
" jne %d5, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d6, %d6, 6 \n" \ " eq %d1, %d7, 7 \n" \
" jne %d6, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d7, %d7, 7 \n" \ " eq %d1, %d8, 8 \n" \
" jne %d7, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d8, %d8, 8 \n" \ " eq %d1, %d9, 9 \n" \
" jne %d8, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d9, %d9, 9 \n" \ " eq %d1, %d10, 10 \n" \
" jne %d9, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d10, %d10, 10 \n" \ " eq %d1, %d11, 11 \n" \
" jne %d10, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d11, %d11, 11 \n" \ " eq %d1, %d12, 12 \n" \
" jne %d11, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d12, %d12, 12 \n" \ " eq %d1, %d13, 13 \n" \
" jne %d12, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d13, %d13, 13 \n" \ " eq %d1, %d14, 14 \n" \
" jne %d13, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d14, %d14, 14 \n" \ " eq %d1, %d15, 15 \n" \
" jne %d14, 1, _task1_loop \n" \ " jne %d1, 1, _task1_error_loop \n" \
" eq %d15, %d15, 15 \n" \ " mov.a %a15, 2 \n" \
" jne %d15, 1, _task1_loop \n" \ " jne.a %a15, %a2, _task1_error_loop \n" \
" mov.a %a15, 2 \n" \ " mov.a %a15, 3 \n" \
" jne.a %a15, %a2, _task1_loop \n" \ " jne.a %a15, %a3, _task1_error_loop \n" \
" mov.a %a15, 3 \n" \ " mov.a %a15, 4 \n" \
" jne.a %a15, %a3, _task1_loop \n" \ " jne.a %a15, %a4, _task1_error_loop \n" \
" mov.a %a15, 4 \n" \ " mov.a %a15, 5 \n" \
" jne.a %a15, %a4, _task1_loop \n" \ " jne.a %a15, %a5, _task1_error_loop \n" \
" mov.a %a15, 5 \n" \ " mov.a %a15, 6 \n" \
" jne.a %a15, %a5, _task1_loop \n" \ " jne.a %a15, %a6, _task1_error_loop \n" \
" mov.a %a15, 6 \n" \ " mov.a %a15, 7 \n" \
" jne.a %a15, %a6, _task1_loop \n" \ " jne.a %a15, %a7, _task1_error_loop \n" \
" mov.a %a15, 7 \n" \ " mov.a %a15, 12 \n" \
" jne.a %a15, %a7, _task1_loop \n" \ " jne.a %a15, %a12, _task1_error_loop \n" \
" mov.a %a15, 12 \n" \ " mov.a %a15, 13 \n" \
" jne.a %a15, %a12, _task1_loop \n" \ " jne.a %a15, %a13, _task1_error_loop \n" \
" mov.a %a15, 13 \n" \ " mov.a %a15, 14 \n" \
" jne.a %a15, %a13, _task1_loop \n" \ " jne.a %a15, %a14, _task1_error_loop \n" \
" mov.a %a15, 14 \n" \ " j _task1_skip_error_loop \n" \
" jne.a %a15, %a14, _task1_loop \n" \ "_task1_error_loop: \n" /* Hitting this error loop will stop the counter incrementing, allowing the check task to recognise an error. */ \
" j _task1_skip \n" \ " debug \n" \
"_task1_loop: \n" \ " j _task1_error_loop \n" \
" debug \n" \ "_task1_skip_error_loop: \n" );
" j _task1_loop \n" \
"_task1_skip: \n" ); /* Load the parameter address from the stack and modify the value. */
__asm volatile( \
/* Load the parameter address from the stack and modify the value. */ " ld.w %d1, [%sp]4 \n" \
__asm volatile( \ " add %d1, %d15, 1 \n" \
" ld.w %d15, [%sp]4 \n" \ " st.w [%sp]4, %d1 \n" \
" add %d15, %d15, 1 \n" \ " ld.a %a15, [%sp] \n" \
" st.w [%sp]4, %d15 \n" \ " st.w [%a15], %d1 \n" \
" ld.a %a4, [%sp] \n" \ " j _task1_loop \n" );
" st.w [%a4], %d15 \n" );
}
/* The parameter is used but in the assembly. */ /* The parameter is used but in the assembly. */
(void)pvParameters; (void)pvParameters;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* static void prvRegTask2( void *pvParameters )
* Set all of the registers that are used as part of the task context
* to known values and test that those values are maintained across
* context switches.
*/
void vRegTask2( void *pvParameters )
{ {
/* Make space on the stack for the parameter and a counter. */ /* Make space on the stack for the parameter and a counter. */
__asm volatile( " sub.a %sp, 4 \n" \ __asm volatile( " sub.a %sp, 4 \n" \
@ -466,103 +478,102 @@ void vRegTask2( void *pvParameters )
" mov %d15, 0 \n" \ " mov %d15, 0 \n" \
" st.w [%sp]4, %d15 \n" ); " st.w [%sp]4, %d15 \n" );
for (;;) /* Change all of the Context sensitive registers (except SP and RA). */
{ __asm volatile( " mov %d0, 7 \n" \
/* Change all of the Context sensitive registers (except SP and RA). */ " mov %d1, 1 \n" \
__asm( " mov %d0, 7 \n" \ " mov %d2, 5 \n" \
" mov %d1, 6 \n" \ " mov %d3, 4 \n" \
" mov %d2, 5 \n" \ " mov %d4, 3 \n" \
" mov %d3, 4 \n" \ " mov %d5, 2 \n" \
" mov %d4, 3 \n" \ " mov %d6, 1 \n" \
" mov %d5, 2 \n" \ " mov %d7, 0 \n" \
" mov %d6, 1 \n" \ " mov %d8, 15 \n" \
" mov %d7, 0 \n" \ " mov %d9, 14 \n" \
" mov %d8, 15 \n" \ " mov %d10, 13 \n" \
" mov %d9, 14 \n" \ " mov %d11, 12 \n" \
" mov %d10, 13 \n" \ " mov %d12, 11 \n" \
" mov %d11, 12 \n" \ " mov %d13, 10 \n" \
" mov %d12, 11 \n" \ " mov %d14, 9 \n" \
" mov %d13, 10 \n" \ " mov %d15, 8 \n" \
" mov %d14, 9 \n" \ " mov.a %a2, 14 \n" \
" mov %d15, 8 \n" \ " mov.a %a3, 13 \n" \
" mov.a %a2, 14 \n" \ " mov.a %a4, 12 \n" \
" mov.a %a3, 13 \n" \ " mov.a %a5, 7 \n" \
" mov.a %a4, 12 \n" \ " mov.a %a6, 6 \n" \
" mov.a %a5, 7 \n" \ " mov.a %a7, 5 \n" \
" mov.a %a6, 6 \n" \ " mov.a %a12, 4 \n" \
" mov.a %a7, 5 \n" \ " mov.a %a13, 3 \n" \
" mov.a %a12, 4 \n" \ " mov.a %a14, 2 \n" );
" mov.a %a13, 3 \n" \ /* Yield to force a context switch. */
" mov.a %a14, 2 \n" ); taskYIELD();
/* Yield to force a context switch. */
taskYIELD(); /* Check the values of the registers. */
/* Check the values of the registers. */ __asm volatile( " _task2_loop: \n" \
__asm( " eq %d0, %d0, 7 \n" \ " eq %d1, %d0, 7 \n" \
" jne %d0, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d1, %d1, 6 \n" \ " eq %d1, %d1, 1 \n" \
" jne %d1, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d2, %d2, 5 \n" \ " eq %d1, %d2, 5 \n" \
" jne %d2, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d3, %d3, 4 \n" \ " eq %d1, %d3, 4 \n" \
" jne %d3, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d4, %d4, 3 \n" \ " eq %d1, %d4, 3 \n" \
" jne %d4, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d5, %d5, 2 \n" \ " eq %d1, %d5, 2 \n" \
" jne %d5, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d6, %d6, 1 \n" \ " eq %d1, %d6, 1 \n" \
" jne %d6, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d7, %d7, 0 \n" \ " eq %d1, %d7, 0 \n" \
" jne %d7, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d8, %d8, 15 \n" \ " eq %d1, %d8, 15 \n" \
" jne %d8, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d9, %d9, 14 \n" \ " eq %d1, %d9, 14 \n" \
" jne %d9, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d10, %d10, 13 \n" \ " eq %d1, %d10, 13 \n" \
" jne %d10, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d11, %d11, 12 \n" \ " eq %d1, %d11, 12 \n" \
" jne %d11, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d12, %d12, 11 \n" \ " eq %d1, %d12, 11 \n" \
" jne %d12, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d13, %d13, 10 \n" \ " eq %d1, %d13, 10 \n" \
" jne %d13, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d14, %d14, 9 \n" \ " eq %d1, %d14, 9 \n" \
" jne %d14, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" eq %d15, %d15, 8 \n" \ " eq %d1, %d15, 8 \n" \
" jne %d15, 1, _task2_loop \n" \ " jne %d1, 1, _task2_error_loop \n" \
" mov.a %a15, 14 \n" \ " mov.a %a15, 14 \n" \
" jne.a %a15, %a2, _task2_loop \n" \ " jne.a %a15, %a2, _task2_error_loop \n" \
" mov.a %a15, 13 \n" \ " mov.a %a15, 13 \n" \
" jne.a %a15, %a3, _task2_loop \n" \ " jne.a %a15, %a3, _task2_error_loop \n" \
" mov.a %a15, 12 \n" \ " mov.a %a15, 12 \n" \
" jne.a %a15, %a4, _task2_loop \n" \ " jne.a %a15, %a4, _task2_error_loop \n" \
" mov.a %a15, 7 \n" \ " mov.a %a15, 7 \n" \
" jne.a %a15, %a5, _task2_loop \n" \ " jne.a %a15, %a5, _task2_error_loop \n" \
" mov.a %a15, 6 \n" \ " mov.a %a15, 6 \n" \
" jne.a %a15, %a6, _task2_loop \n" \ " jne.a %a15, %a6, _task2_error_loop \n" \
" mov.a %a15, 5 \n" \ " mov.a %a15, 5 \n" \
" jne.a %a15, %a7, _task2_loop \n" \ " jne.a %a15, %a7, _task2_error_loop \n" \
" mov.a %a15, 4 \n" \ " mov.a %a15, 4 \n" \
" jne.a %a15, %a12, _task2_loop \n" \ " jne.a %a15, %a12, _task2_error_loop \n" \
" mov.a %a15, 3 \n" \ " mov.a %a15, 3 \n" \
" jne.a %a15, %a13, _task2_loop \n" \ " jne.a %a15, %a13, _task2_error_loop \n" \
" mov.a %a15, 2 \n" \ " mov.a %a15, 2 \n" \
" jne.a %a15, %a14, _task2_loop \n" \ " jne.a %a15, %a14, _task2_error_loop \n" \
" j _task2_skip \n" \ " j _task2_skip_error_loop \n" \
"_task2_loop: \n" \ "_task2_error_loop: \n" /* Hitting this error loop will stop the counter incrementing, allowing the check task to recognise an error. */ \
" j _task2_loop \n" \ " j _task2_error_loop \n" \
"_task2_skip: \n" ); "_task2_skip_error_loop: \n" );
/* Load the parameter address from the stack and modify the value. */ /* Load the parameter address from the stack and modify the value. */
__asm volatile( \ __asm volatile( " ld.w %d1, [%sp]4 \n" \
" ld.w %d15, [%sp]4 \n" \ " add %d1, %d1, 1 \n" \
" add %d15, %d15, 1 \n" \ " st.w [%sp]4, %d1 \n" \
" st.w [%sp]4, %d15 \n" \ " ld.a %a15, [%sp] \n" \
" ld.a %a4, [%sp] \n" \ " st.w [%a15], %d1 \n" \
" st.w [%a4], %d15 \n" ); " j _task2_loop \n" );
}
/* The parameter is used but in the assembly. */ /* The parameter is used but in the assembly. */
(void)pvParameters; (void)pvParameters;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#endif /* mainREG_TEST_TASKS */

Loading…
Cancel
Save