2 FreeRTOS V4.0.1 - Copyright (C) 2003-2006 Richard Barry.
\r
4 This file is part of the FreeRTOS distribution.
\r
6 FreeRTOS is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 FreeRTOS is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS, without being obliged to provide
\r
22 the source code for any proprietary components. See the licensing section
\r
23 of http://www.FreeRTOS.org for full details of how and when the exception
\r
26 ***************************************************************************
\r
27 See http://www.FreeRTOS.org for documentation, latest information, license
\r
28 and contact details. Please ensure to read the configuration and relevant
\r
29 port sections of the online documentation.
\r
30 ***************************************************************************
\r
36 + The created tasks now include calls to tskYIELD(), allowing them to be used
\r
37 with the cooperative scheduler.
\r
41 * This does the same as flop. c, but uses variables of type long instead of
\r
44 * As with flop. c, the tasks created in this file are a good test of the
\r
45 * scheduler context switch mechanism. The processor has to access 32bit
\r
46 * variables in two or four chunks (depending on the processor). The low
\r
47 * priority of these tasks means there is a high probability that a context
\r
48 * switch will occur mid calculation. See the flop. c documentation for
\r
51 * \page IntegerC integer.c
\r
52 * \ingroup DemoFiles
\r
59 + The constants used in the calculations are larger to ensure the
\r
60 optimiser does not truncate them to 16 bits.
\r
65 /* Scheduler include files. */
\r
66 #include "FreeRTOS.h"
\r
70 /* Demo program include files. */
\r
71 #include "integer.h"
\r
73 #define intgSTACK_SIZE ( ( unsigned portSHORT ) 256 )
\r
74 #define intgNUMBER_OF_TASKS ( 8 )
\r
76 /* Four tasks, each of which performs a different calculation on four byte
\r
77 variables. Each of the four is created twice. */
\r
78 static void vCompeteingIntMathTask1( void *pvParameters );
\r
79 static void vCompeteingIntMathTask2( void *pvParameters );
\r
80 static void vCompeteingIntMathTask3( void *pvParameters );
\r
81 static void vCompeteingIntMathTask4( void *pvParameters );
\r
83 /* These variables are used to check that all the tasks are still running. If a
\r
84 task gets a calculation wrong it will stop incrementing its check variable. */
\r
85 static volatile unsigned portSHORT usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };
\r
86 /*-----------------------------------------------------------*/
\r
88 void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority )
\r
90 xTaskCreate( vCompeteingIntMathTask1, "IntMath1", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
\r
91 xTaskCreate( vCompeteingIntMathTask2, "IntMath2", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
\r
92 xTaskCreate( vCompeteingIntMathTask3, "IntMath3", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
\r
93 xTaskCreate( vCompeteingIntMathTask4, "IntMath4", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
\r
94 xTaskCreate( vCompeteingIntMathTask1, "IntMath5", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );
\r
95 xTaskCreate( vCompeteingIntMathTask2, "IntMath6", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );
\r
96 xTaskCreate( vCompeteingIntMathTask3, "IntMath7", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );
\r
97 xTaskCreate( vCompeteingIntMathTask4, "IntMath8", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );
\r
99 /*-----------------------------------------------------------*/
\r
101 static void vCompeteingIntMathTask1( void *pvParameters )
\r
103 portLONG l1, l2, l3, l4;
\r
104 portSHORT sError = pdFALSE;
\r
105 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
106 const portLONG lAnswer = ( ( portLONG ) 74565L + ( portLONG ) 1234567L ) * ( portLONG ) -918L;
\r
107 const portCHAR * const pcTaskStartMsg = "Integer math task 1 started.\r\n";
\r
108 const portCHAR * const pcTaskFailMsg = "Integer math task 1 failed.\r\n";
\r
110 /* Queue a message for printing to say the task has started. */
\r
111 vPrintDisplayMessage( &pcTaskStartMsg );
\r
113 /* The variable this task increments to show it is still running is passed in
\r
114 as the parameter. */
\r
115 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
117 /* Keep performing a calculation and checking the result against a constant. */
\r
120 l1 = ( portLONG ) 74565L;
\r
121 l2 = ( portLONG ) 1234567L;
\r
122 l3 = ( portLONG ) -918L;
\r
124 l4 = ( l1 + l2 ) * l3;
\r
128 /* If the calculation does not match the expected constant, stop the
\r
129 increment of the check variable. */
\r
130 if( l4 != lAnswer )
\r
132 vPrintDisplayMessage( &pcTaskFailMsg );
\r
136 if( sError == pdFALSE )
\r
138 /* If the calculation has always been correct, increment the check
\r
139 variable so we know this task is still running okay. */
\r
140 ( *pusTaskCheckVariable )++;
\r
144 /*-----------------------------------------------------------*/
\r
146 static void vCompeteingIntMathTask2( void *pvParameters )
\r
148 portLONG l1, l2, l3, l4;
\r
149 portSHORT sError = pdFALSE;
\r
150 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
151 const portLONG lAnswer = ( ( portLONG ) -389000L / ( portLONG ) 329999L ) * ( portLONG ) -89L;
\r
152 const portCHAR * const pcTaskStartMsg = "Integer math task 2 started.\r\n";
\r
153 const portCHAR * const pcTaskFailMsg = "Integer math task 2 failed.\r\n";
\r
155 /* Queue a message for printing to say the task has started. */
\r
156 vPrintDisplayMessage( &pcTaskStartMsg );
\r
158 /* The variable this task increments to show it is still running is passed in
\r
159 as the parameter. */
\r
160 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
162 /* Keep performing a calculation and checking the result against a constant. */
\r
169 l4 = ( l1 / l2 ) * l3;
\r
173 /* If the calculation does not match the expected constant, stop the
\r
174 increment of the check variable. */
\r
175 if( l4 != lAnswer )
\r
177 vPrintDisplayMessage( &pcTaskFailMsg );
\r
181 if( sError == pdFALSE )
\r
183 /* If the calculation has always been correct, increment the check
\r
184 variable so we know this task is still running okay. */
\r
185 ( *pusTaskCheckVariable )++;
\r
189 /*-----------------------------------------------------------*/
\r
191 static void vCompeteingIntMathTask3( void *pvParameters )
\r
193 portLONG *plArray, lTotal1, lTotal2;
\r
194 portSHORT sError = pdFALSE;
\r
195 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
196 const unsigned portSHORT usArraySize = ( unsigned portSHORT ) 250;
\r
197 unsigned portSHORT usPosition;
\r
198 const portCHAR * const pcTaskStartMsg = "Integer math task 3 started.\r\n";
\r
199 const portCHAR * const pcTaskFailMsg = "Integer math task 3 failed.\r\n";
\r
201 /* Queue a message for printing to say the task has started. */
\r
202 vPrintDisplayMessage( &pcTaskStartMsg );
\r
204 /* The variable this task increments to show it is still running is passed in
\r
205 as the parameter. */
\r
206 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
208 /* Create the array we are going to use for our check calculation. */
\r
209 plArray = ( portLONG * ) pvPortMalloc( ( size_t ) 250 * sizeof( portLONG ) );
\r
211 /* Keep filling the array, keeping a running total of the values placed in the
\r
212 array. Then run through the array adding up all the values. If the two totals
\r
213 do not match, stop the check variable from incrementing. */
\r
216 lTotal1 = ( portLONG ) 0;
\r
217 lTotal2 = ( portLONG ) 0;
\r
219 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
221 plArray[ usPosition ] = ( portLONG ) usPosition + ( portLONG ) 5;
\r
222 lTotal1 += ( portLONG ) usPosition + ( portLONG ) 5;
\r
227 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
229 lTotal2 += plArray[ usPosition ];
\r
232 if( lTotal1 != lTotal2 )
\r
234 vPrintDisplayMessage( &pcTaskFailMsg );
\r
240 if( sError == pdFALSE )
\r
242 /* If the calculation has always been correct, increment the check
\r
243 variable so we know this task is still running okay. */
\r
244 ( *pusTaskCheckVariable )++;
\r
248 /*-----------------------------------------------------------*/
\r
250 static void vCompeteingIntMathTask4( void *pvParameters )
\r
252 portLONG *plArray, lTotal1, lTotal2;
\r
253 portSHORT sError = pdFALSE;
\r
254 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
255 const unsigned portSHORT usArraySize = 250;
\r
256 unsigned portSHORT usPosition;
\r
257 const portCHAR * const pcTaskStartMsg = "Integer math task 4 started.\r\n";
\r
258 const portCHAR * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
\r
260 /* Queue a message for printing to say the task has started. */
\r
261 vPrintDisplayMessage( &pcTaskStartMsg );
\r
263 /* The variable this task increments to show it is still running is passed in
\r
264 as the parameter. */
\r
265 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
267 /* Create the array we are going to use for our check calculation. */
\r
268 plArray = ( portLONG * ) pvPortMalloc( ( size_t ) 250 * sizeof( portLONG ) );
\r
270 /* Keep filling the array, keeping a running total of the values placed in the
\r
271 array. Then run through the array adding up all the values. If the two totals
\r
272 do not match, stop the check variable from incrementing. */
\r
275 lTotal1 = ( portLONG ) 0;
\r
276 lTotal2 = ( portLONG ) 0;
\r
278 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
280 plArray[ usPosition ] = ( portLONG ) usPosition * ( portLONG ) 12;
\r
281 lTotal1 += ( portLONG ) usPosition * ( portLONG ) 12;
\r
286 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
288 lTotal2 += plArray[ usPosition ];
\r
292 if( lTotal1 != lTotal2 )
\r
294 vPrintDisplayMessage( &pcTaskFailMsg );
\r
300 if( sError == pdFALSE )
\r
302 /* If the calculation has always been correct, increment the check
\r
303 variable so we know this task is still running okay. */
\r
304 ( *pusTaskCheckVariable )++;
\r
308 /*-----------------------------------------------------------*/
\r
310 /* This is called to check that all the created tasks are still running. */
\r
311 portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )
\r
313 /* Keep a history of the check variables so we know if they have been incremented
\r
314 since the last call. */
\r
315 static unsigned portSHORT usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };
\r
316 portBASE_TYPE xReturn = pdTRUE, xTask;
\r
318 /* Check the maths tasks are still running by ensuring their check variables
\r
319 are still incrementing. */
\r
320 for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ )
\r
322 if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
\r
324 /* The check has not incremented so an error exists. */
\r
328 usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];
\r