Just updated comments.

pull/4/head
Richard Barry 15 years ago
parent 8dd9c7dfd9
commit 73b49130c6

@ -70,7 +70,7 @@
#define configUSE_PREEMPTION 1 #define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1 #define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1 #define configUSE_TICK_HOOK 1 /* Must be set to one for the timer interrupt to be cleared. */
#define configCPU_CLOCK_HZ ( 200000000UL ) #define configCPU_CLOCK_HZ ( 200000000UL )
#define configPERIPHERAL_CLOCK_HZ ( 50000000UL ) #define configPERIPHERAL_CLOCK_HZ ( 50000000UL )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configTICK_RATE_HZ ( ( portTickType ) 1000 )

@ -52,16 +52,19 @@
*/ */
/* /*
* Creates eight tasks, each of which loops continuously performing an (emulated) * Creates eight tasks, each of which loops continuously performing a floating
* floating point calculation. * point calculation and in so doing test the floating point context switching.
* This file also demonstrates the use of the xPortUsesFloatingPoint() function
* which informs the kernel that the task requires its floating point context
* saved on each switch.
* *
* All the tasks run at the idle priority and never block or yield. This causes * All the tasks run at the idle priority and never block or yield. This causes
* all eight tasks to time slice with the idle task. Running at the idle priority * all eight tasks to time slice with the idle task. Running at the idle
* means that these tasks will get pre-empted any time another task is ready to run * priority means that these tasks will get pre-empted any time another task is
* or a time slice occurs. More often than not the pre-emption will occur mid * ready to run or a time slice occurs. More often than not the pre-emption
* calculation, creating a good test of the schedulers context switch mechanism - a * will occur mid calculation, creating a good test of the schedulers context
* calculation producing an unexpected result could be a symptom of a corruption in * switch mechanism - a calculation producing an unexpected result could be a
* the context of a task. * symptom of a corruption in the context of a task.
*/ */
#include <stdlib.h> #include <stdlib.h>
@ -79,14 +82,15 @@
/* Four tasks, each of which performs a different floating point calculation. /* Four tasks, each of which performs a different floating point calculation.
Each of the four is created twice. */ Each of the four is created twice. */
static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters ); static void vCompetingMathTask1( void *pvParameters );
static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters ); static void vCompetingMathTask2( void *pvParameters );
static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters ); static void vCompetingMathTask3( void *pvParameters );
static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters ); static void vCompetingMathTask4( void *pvParameters );
/* These variables are used to check that all the tasks are still running. If a /* These variables are used to check that all the tasks are still running. If a
task gets a calculation wrong it will task gets a calculation wrong it will stop incrementing its check variable,
stop incrementing its check variable. */ otherwise the check variable will get incremented on each iteration of the
tasks execution. */
static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -125,7 +129,7 @@ xTaskHandle xCreatedTask;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portTASK_FUNCTION( vCompetingMathTask1, pvParameters ) static void vCompetingMathTask1( void *pvParameters )
{ {
volatile double d1, d2, d3, d4; volatile double d1, d2, d3, d4;
volatile unsigned short *pusTaskCheckVariable; volatile unsigned short *pusTaskCheckVariable;
@ -136,6 +140,7 @@ short sError = pdFALSE;
d2 = 2345.6789; d2 = 2345.6789;
d3 = -918.222; d3 = -918.222;
/* Calculate the expected answer. */
dAnswer = ( d1 + d2 ) * d3; dAnswer = ( d1 + d2 ) * d3;
/* The variable this task increments to show it is still running is passed in /* The variable this task increments to show it is still running is passed in
@ -145,16 +150,13 @@ short sError = pdFALSE;
/* Keep performing a calculation and checking the result against a constant. */ /* Keep performing a calculation and checking the result against a constant. */
for(;;) for(;;)
{ {
/* Perform the calculation. */
d1 = 123.4567; d1 = 123.4567;
d2 = 2345.6789; d2 = 2345.6789;
d3 = -918.222; d3 = -918.222;
d4 = ( d1 + d2 ) * d3; d4 = ( d1 + d2 ) * d3;
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* If the calculation does not match the expected constant, stop the /* If the calculation does not match the expected constant, stop the
increment of the check variable. */ increment of the check variable. */
if( fabs( d4 - dAnswer ) > 0.001 ) if( fabs( d4 - dAnswer ) > 0.001 )
@ -168,16 +170,11 @@ short sError = pdFALSE;
variable so we know this task is still running okay. */ variable so we know this task is still running okay. */
( *pusTaskCheckVariable )++; ( *pusTaskCheckVariable )++;
} }
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portTASK_FUNCTION( vCompetingMathTask2, pvParameters ) static void vCompetingMathTask2( void *pvParameters )
{ {
volatile double d1, d2, d3, d4; volatile double d1, d2, d3, d4;
volatile unsigned short *pusTaskCheckVariable; volatile unsigned short *pusTaskCheckVariable;
@ -188,6 +185,7 @@ short sError = pdFALSE;
d2 = 32498.2; d2 = 32498.2;
d3 = -2.0001; d3 = -2.0001;
/* Calculate the expected answer. */
dAnswer = ( d1 / d2 ) * d3; dAnswer = ( d1 / d2 ) * d3;
@ -198,16 +196,13 @@ short sError = pdFALSE;
/* Keep performing a calculation and checking the result against a constant. */ /* Keep performing a calculation and checking the result against a constant. */
for( ;; ) for( ;; )
{ {
/* Perform the calculation. */
d1 = -389.38; d1 = -389.38;
d2 = 32498.2; d2 = 32498.2;
d3 = -2.0001; d3 = -2.0001;
d4 = ( d1 / d2 ) * d3; d4 = ( d1 / d2 ) * d3;
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* If the calculation does not match the expected constant, stop the /* If the calculation does not match the expected constant, stop the
increment of the check variable. */ increment of the check variable. */
if( fabs( d4 - dAnswer ) > 0.001 ) if( fabs( d4 - dAnswer ) > 0.001 )
@ -222,15 +217,11 @@ short sError = pdFALSE;
this task is still running okay. */ this task is still running okay. */
( *pusTaskCheckVariable )++; ( *pusTaskCheckVariable )++;
} }
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portTASK_FUNCTION( vCompetingMathTask3, pvParameters ) static void vCompetingMathTask3( void *pvParameters )
{ {
volatile double *pdArray, dTotal1, dTotal2, dDifference; volatile double *pdArray, dTotal1, dTotal2, dDifference;
volatile unsigned short *pusTaskCheckVariable; volatile unsigned short *pusTaskCheckVariable;
@ -238,15 +229,16 @@ const size_t xArraySize = 10;
size_t xPosition; size_t xPosition;
short sError = pdFALSE; short sError = pdFALSE;
/* The variable this task increments to show it is still running is passed in /* The variable this task increments to show it is still running is passed
as the parameter. */ in as the parameter. */
pusTaskCheckVariable = ( unsigned short * ) pvParameters; pusTaskCheckVariable = ( unsigned short * ) pvParameters;
/* Allocate memory for use as an array. */
pdArray = ( double * ) pvPortMalloc( xArraySize * sizeof( double ) ); pdArray = ( double * ) pvPortMalloc( xArraySize * sizeof( double ) );
/* Keep filling an array, keeping a running total of the values placed in the /* Keep filling an array, keeping a running total of the values placed in
array. Then run through the array adding up all the values. If the two totals the array. Then run through the array adding up all the values. If the two
do not match, stop the check variable from incrementing. */ totals do not match, stop the check variable from incrementing. */
for( ;; ) for( ;; )
{ {
dTotal1 = 0.0; dTotal1 = 0.0;
@ -258,10 +250,6 @@ short sError = pdFALSE;
dTotal1 += ( double ) xPosition + 5.5; dTotal1 += ( double ) xPosition + 5.5;
} }
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
for( xPosition = 0; xPosition < xArraySize; xPosition++ ) for( xPosition = 0; xPosition < xArraySize; xPosition++ )
{ {
dTotal2 += pdArray[ xPosition ]; dTotal2 += pdArray[ xPosition ];
@ -273,10 +261,6 @@ short sError = pdFALSE;
sError = pdTRUE; sError = pdTRUE;
} }
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
if( sError == pdFALSE ) if( sError == pdFALSE )
{ {
/* If the calculation has always been correct, increment the check /* If the calculation has always been correct, increment the check
@ -287,7 +271,7 @@ short sError = pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portTASK_FUNCTION( vCompetingMathTask4, pvParameters ) static void vCompetingMathTask4( void *pvParameters )
{ {
volatile double *pdArray, dTotal1, dTotal2, dDifference; volatile double *pdArray, dTotal1, dTotal2, dDifference;
volatile unsigned short *pusTaskCheckVariable; volatile unsigned short *pusTaskCheckVariable;
@ -299,6 +283,7 @@ short sError = pdFALSE;
as the parameter. */ as the parameter. */
pusTaskCheckVariable = ( unsigned short * ) pvParameters; pusTaskCheckVariable = ( unsigned short * ) pvParameters;
/* Allocate RAM for use as an array. */
pdArray = ( double * ) pvPortMalloc( xArraySize * sizeof( double ) ); pdArray = ( double * ) pvPortMalloc( xArraySize * sizeof( double ) );
/* Keep filling an array, keeping a running total of the values placed in the /* Keep filling an array, keeping a running total of the values placed in the
@ -315,10 +300,6 @@ short sError = pdFALSE;
dTotal1 += ( double ) xPosition * 12.123; dTotal1 += ( double ) xPosition * 12.123;
} }
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
for( xPosition = 0; xPosition < xArraySize; xPosition++ ) for( xPosition = 0; xPosition < xArraySize; xPosition++ )
{ {
dTotal2 += pdArray[ xPosition ]; dTotal2 += pdArray[ xPosition ];
@ -330,10 +311,6 @@ short sError = pdFALSE;
sError = pdTRUE; sError = pdTRUE;
} }
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
if( sError == pdFALSE ) if( sError == pdFALSE )
{ {
/* If the calculation has always been correct, increment the check /* If the calculation has always been correct, increment the check
@ -347,8 +324,8 @@ short sError = pdFALSE;
/* This is called to check that all the created tasks are still running. */ /* This is called to check that all the created tasks are still running. */
portBASE_TYPE xAreMathsTaskStillRunning( void ) portBASE_TYPE xAreMathsTaskStillRunning( void )
{ {
/* Keep a history of the check variables so we know if they have been incremented /* Keep a history of the check variables so we know if they have been
since the last call. */ incremented since the last call. */
static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 }; static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
portBASE_TYPE xReturn = pdTRUE, xTask; portBASE_TYPE xReturn = pdTRUE, xTask;

@ -51,6 +51,57 @@
licensing and training services. licensing and training services.
*/ */
/*
* Creates all the demo application tasks, then starts the scheduler. The WEB
* documentation provides more details of the standard demo application tasks,
* which provide no particular functionality but do provide a good example of
* how to use the FreeRTOS API. In addition to the standard demo tasks, the
* following tasks and tests are defined and/or created within this file:
*
* "Reg test" tasks - These fill the registers with known values, then check
* that each register still contains its expected value. Each task uses
* different values. The tasks run with very low priority so get preempted very
* frequently. A register containing an unexpected value is indicative of an
* error in the context switching mechanism. Both standard and floating point
* registers are checked. The nature of the reg test tasks necessitates that
* they are written in assembly code. They are defined in regtest.src.
*
* "math" tasks - These are a set of 8 tasks that perform various double
* precision floating point calculations in order to check that the tasks
* floating point registers are being correctly saved and restored during
* context switches. The math tasks are defined in flop.c.
*
* "Check" task - This only executes every five seconds but has a high priority
* to ensure it gets processor time. Its main function is to check that all the
* standard demo tasks are still operational. While no errors have been
* discovered the check task will toggle an LED every 5 seconds - the toggle
* rate increasing to 500ms being a visual indication that at least one task has
* reported unexpected behaviour.
*
* *NOTE 1* If LED5 is toggling every 5 seconds then all the demo application
* tasks are executing as expected and no errors have been reported in any
* tasks. The toggle rate increasing to 200ms indicates that at least one task
* has reported unexpected behaviour.
*
* *NOTE 2* This file and flop.c both demonstrate the use of
* xPortUsesFloatingPoint() which informs the kernel that a task should maintain
* a floating point context.
*
* *NOTE 3* vApplicationSetupTimerInterrupt() is called by the kernel to let
* the application set up a timer to generate the tick interrupt. In this
* example a compare match timer is used for this purpose.
* vApplicationTickHook() is used to clear the timer interrupt and relies on
* configUSE_TICK_HOOK being set to 1 in FreeRTOSConfig.h.
*
* *NOTE 4* The traceTASK_SWITCHED_IN and traceTASK_SWITCHED_OUT trace hooks
* are used to save and restore the floating point context respectively for
* those tasks that require it (those for which xPortUsesFloatingPoint() has
* been called).
*
*/
/* Kernel includes. */ /* Kernel includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
@ -94,18 +145,58 @@ without error. */
by at least one task. */ by at least one task. */
#define mainERROR_CYCLE_TIME ( 200 / portTICK_RATE_MS ) #define mainERROR_CYCLE_TIME ( 200 / portTICK_RATE_MS )
/*
* vApplicationMallocFailedHook() will only be called if
* configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
* function that will execute if a call to pvPortMalloc() fails.
* pvPortMalloc() is called internally by the kernel whenever a task, queue or
* semaphore is created. It is also called by various parts of the demo
* application.
*/
void vApplicationMallocFailedHook( void ); void vApplicationMallocFailedHook( void );
/*
* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set to 1
* in FreeRTOSConfig.h. It is a hook function that is 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). If the application makes use of the vTaskDelete()
* API function (as this demo application does) then it is also important that
* vApplicationIdleHook() is permitted to return to its calling function because
* it is the responsibility of the idle task to clean up memory allocated by the
* kernel to any task that has since been deleted.
*/
void vApplicationIdleHook( void ); void vApplicationIdleHook( void );
/*
* Just sets up clocks, ports, etc. used by the demo application.
*/
static void prvSetupHardware( void ); static void prvSetupHardware( void );
/*
* The check task as described at the top of this file.
*/
static void prvCheckTask( void *pvParameters ); static void prvCheckTask( void *pvParameters );
/*
* The reg test tasks as described at the top of this file.
*/
extern void vRegTest1Task( void *pvParameters ); extern void vRegTest1Task( void *pvParameters );
extern void vRegTest2Task( void *pvParameters ); extern void vRegTest2Task( void *pvParameters );
/*-----------------------------------------------------------*/
/* Variables that are incremented on each iteration of the reg test tasks -
provided the tasks have not reported any errors. The check task inspects these
variables to ensure they are still incrementing as expected. */
volatile unsigned long ulRegTest1CycleCount = 0UL, ulRegTest2CycleCount = 0UL; volatile unsigned long ulRegTest1CycleCount = 0UL, ulRegTest2CycleCount = 0UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/*
* Creates the majority of the demo application tasks before starting the
* scheduler.
*/
void main(void) void main(void)
{ {
xTaskHandle xCreatedTask; xTaskHandle xCreatedTask;
@ -113,10 +204,10 @@ xTaskHandle xCreatedTask;
prvSetupHardware(); prvSetupHardware();
/* Start the reg test tasks which test the context switching mechanism. */ /* Start the reg test tasks which test the context switching mechanism. */
xTaskCreate( vRegTest1Task, "RegTest1", configMINIMAL_STACK_SIZE, ( void * ) 0x12345678UL, tskIDLE_PRIORITY, &xCreatedTask ); xTaskCreate( vRegTest1Task, "RegTest1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xCreatedTask );
xPortUsesFloatingPoint( xCreatedTask ); xPortUsesFloatingPoint( xCreatedTask );
xTaskCreate( vRegTest2Task, "RegTest2", configMINIMAL_STACK_SIZE, ( void * ) 0x11223344UL, tskIDLE_PRIORITY, &xCreatedTask ); xTaskCreate( vRegTest2Task, "RegTest2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xCreatedTask );
xPortUsesFloatingPoint( xCreatedTask ); xPortUsesFloatingPoint( xCreatedTask );
/* Start the check task as described at the top of this file. */ /* Start the check task as described at the top of this file. */
@ -133,6 +224,8 @@ xTaskHandle xCreatedTask;
vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY ); vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );
vStartQueuePeekTasks(); vStartQueuePeekTasks();
vStartRecursiveMutexTasks(); vStartRecursiveMutexTasks();
/* Start the math tasks as described at the top of this file. */
vStartMathTasks( mainFLOP_TASK_PRIORITY ); vStartMathTasks( mainFLOP_TASK_PRIORITY );
/* The suicide tasks must be created last as they need to know how many /* The suicide tasks must be created last as they need to know how many
@ -165,7 +258,7 @@ unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL;
/* Place this task in the blocked state until it is time to run again. */ /* Place this task in the blocked state until it is time to run again. */
vTaskDelayUntil( &xNextWakeTime, xCycleFrequency ); vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );
/* Inspect all the other tasks to esnure none have experienced any errors. */ /* Inspect all the other tasks to ensure none have experienced any errors. */
if( xAreGenericQueueTasksStillRunning() != pdTRUE ) if( xAreGenericQueueTasksStillRunning() != pdTRUE )
{ {
/* Increase the rate at which this task cycles, which will increase the /* Increase the rate at which this task cycles, which will increase the
@ -253,7 +346,10 @@ void vApplicationIdleHook( void )
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ) void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName )
{ {
/* Just to remove compiler warnings. */ /* Just to remove compiler warnings. This function will only actually
get called if configCHECK_FOR_STACK_OVERFLOW is set to a non zero value.
By default this demo does not use the stack overflow checking functionality
as the SuperH will normally execute an exception if the stack overflows. */
( void ) pxTask; ( void ) pxTask;
( void ) pcTaskName; ( void ) pcTaskName;
@ -282,7 +378,7 @@ volatile unsigned long ul;
void vApplicationSetupTimerInterrupt( void ) void vApplicationSetupTimerInterrupt( void )
{ {
/* The peripheral clock is divided by 32 before feeding the compare match /* The peripheral clock is divided by 32 before feeding the compare match
periphersl (CMT). */ peripheral (CMT). */
unsigned long ulCompareMatch = ( configPERIPHERAL_CLOCK_HZ / ( configTICK_RATE_HZ * 32 ) ) + 1; unsigned long ulCompareMatch = ( configPERIPHERAL_CLOCK_HZ / ( configTICK_RATE_HZ * 32 ) ) + 1;
/* Configure a timer to create the RTOS tick interrupt. This example uses /* Configure a timer to create the RTOS tick interrupt. This example uses

Loading…
Cancel
Save