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
51 + The created tasks now include calls to tskYIELD(), allowing them to be used
\r
52 with the cooperative scheduler.
\r
56 * This does the same as flop. c, but uses variables of type long instead of
\r
59 * As with flop. c, the tasks created in this file are a good test of the
\r
60 * scheduler context switch mechanism. The processor has to access 32bit
\r
61 * variables in two or four chunks (depending on the processor). The low
\r
62 * priority of these tasks means there is a high probability that a context
\r
63 * switch will occur mid calculation. See the flop. c documentation for
\r
66 * \page IntegerC integer.c
\r
67 * \ingroup DemoFiles
\r
74 + The constants used in the calculations are larger to ensure the
\r
75 optimiser does not truncate them to 16 bits.
\r
80 /* Scheduler include files. */
\r
81 #include "FreeRTOS.h"
\r
85 /* Demo program include files. */
\r
86 #include "integer.h"
\r
88 #define intgSTACK_SIZE ( ( unsigned portSHORT ) 256 )
\r
89 #define intgNUMBER_OF_TASKS ( 8 )
\r
91 /* Four tasks, each of which performs a different calculation on four byte
\r
92 variables. Each of the four is created twice. */
\r
93 static void vCompeteingIntMathTask1( void *pvParameters );
\r
94 static void vCompeteingIntMathTask2( void *pvParameters );
\r
95 static void vCompeteingIntMathTask3( void *pvParameters );
\r
96 static void vCompeteingIntMathTask4( void *pvParameters );
\r
98 /* These variables are used to check that all the tasks are still running. If a
\r
99 task gets a calculation wrong it will stop incrementing its check variable. */
\r
100 static volatile unsigned portSHORT usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };
\r
101 /*-----------------------------------------------------------*/
\r
103 void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority )
\r
105 xTaskCreate( vCompeteingIntMathTask1, "IntMath1", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
\r
106 xTaskCreate( vCompeteingIntMathTask2, "IntMath2", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
\r
107 xTaskCreate( vCompeteingIntMathTask3, "IntMath3", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
\r
108 xTaskCreate( vCompeteingIntMathTask4, "IntMath4", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
\r
109 xTaskCreate( vCompeteingIntMathTask1, "IntMath5", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );
\r
110 xTaskCreate( vCompeteingIntMathTask2, "IntMath6", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );
\r
111 xTaskCreate( vCompeteingIntMathTask3, "IntMath7", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );
\r
112 xTaskCreate( vCompeteingIntMathTask4, "IntMath8", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );
\r
114 /*-----------------------------------------------------------*/
\r
116 static void vCompeteingIntMathTask1( void *pvParameters )
\r
118 portLONG l1, l2, l3, l4;
\r
119 portSHORT sError = pdFALSE;
\r
120 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
121 const portLONG lAnswer = ( ( portLONG ) 74565L + ( portLONG ) 1234567L ) * ( portLONG ) -918L;
\r
122 const portCHAR * const pcTaskStartMsg = "Integer math task 1 started.\r\n";
\r
123 const portCHAR * const pcTaskFailMsg = "Integer math task 1 failed.\r\n";
\r
125 /* Queue a message for printing to say the task has started. */
\r
126 vPrintDisplayMessage( &pcTaskStartMsg );
\r
128 /* The variable this task increments to show it is still running is passed in
\r
129 as the parameter. */
\r
130 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
132 /* Keep performing a calculation and checking the result against a constant. */
\r
135 l1 = ( portLONG ) 74565L;
\r
136 l2 = ( portLONG ) 1234567L;
\r
137 l3 = ( portLONG ) -918L;
\r
139 l4 = ( l1 + l2 ) * l3;
\r
143 /* If the calculation does not match the expected constant, stop the
\r
144 increment of the check variable. */
\r
145 if( l4 != lAnswer )
\r
147 vPrintDisplayMessage( &pcTaskFailMsg );
\r
151 if( sError == pdFALSE )
\r
153 /* If the calculation has always been correct, increment the check
\r
154 variable so we know this task is still running okay. */
\r
155 ( *pusTaskCheckVariable )++;
\r
159 /*-----------------------------------------------------------*/
\r
161 static void vCompeteingIntMathTask2( void *pvParameters )
\r
163 portLONG l1, l2, l3, l4;
\r
164 portSHORT sError = pdFALSE;
\r
165 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
166 const portLONG lAnswer = ( ( portLONG ) -389000L / ( portLONG ) 329999L ) * ( portLONG ) -89L;
\r
167 const portCHAR * const pcTaskStartMsg = "Integer math task 2 started.\r\n";
\r
168 const portCHAR * const pcTaskFailMsg = "Integer math task 2 failed.\r\n";
\r
170 /* Queue a message for printing to say the task has started. */
\r
171 vPrintDisplayMessage( &pcTaskStartMsg );
\r
173 /* The variable this task increments to show it is still running is passed in
\r
174 as the parameter. */
\r
175 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
177 /* Keep performing a calculation and checking the result against a constant. */
\r
184 l4 = ( l1 / l2 ) * l3;
\r
188 /* If the calculation does not match the expected constant, stop the
\r
189 increment of the check variable. */
\r
190 if( l4 != lAnswer )
\r
192 vPrintDisplayMessage( &pcTaskFailMsg );
\r
196 if( sError == pdFALSE )
\r
198 /* If the calculation has always been correct, increment the check
\r
199 variable so we know this task is still running okay. */
\r
200 ( *pusTaskCheckVariable )++;
\r
204 /*-----------------------------------------------------------*/
\r
206 static void vCompeteingIntMathTask3( void *pvParameters )
\r
208 portLONG *plArray, lTotal1, lTotal2;
\r
209 portSHORT sError = pdFALSE;
\r
210 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
211 const unsigned portSHORT usArraySize = ( unsigned portSHORT ) 250;
\r
212 unsigned portSHORT usPosition;
\r
213 const portCHAR * const pcTaskStartMsg = "Integer math task 3 started.\r\n";
\r
214 const portCHAR * const pcTaskFailMsg = "Integer math task 3 failed.\r\n";
\r
216 /* Queue a message for printing to say the task has started. */
\r
217 vPrintDisplayMessage( &pcTaskStartMsg );
\r
219 /* The variable this task increments to show it is still running is passed in
\r
220 as the parameter. */
\r
221 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
223 /* Create the array we are going to use for our check calculation. */
\r
224 plArray = ( portLONG * ) pvPortMalloc( ( size_t ) 250 * sizeof( portLONG ) );
\r
226 /* Keep filling the array, keeping a running total of the values placed in the
\r
227 array. Then run through the array adding up all the values. If the two totals
\r
228 do not match, stop the check variable from incrementing. */
\r
231 lTotal1 = ( portLONG ) 0;
\r
232 lTotal2 = ( portLONG ) 0;
\r
234 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
236 plArray[ usPosition ] = ( portLONG ) usPosition + ( portLONG ) 5;
\r
237 lTotal1 += ( portLONG ) usPosition + ( portLONG ) 5;
\r
242 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
244 lTotal2 += plArray[ usPosition ];
\r
247 if( lTotal1 != lTotal2 )
\r
249 vPrintDisplayMessage( &pcTaskFailMsg );
\r
255 if( sError == pdFALSE )
\r
257 /* If the calculation has always been correct, increment the check
\r
258 variable so we know this task is still running okay. */
\r
259 ( *pusTaskCheckVariable )++;
\r
263 /*-----------------------------------------------------------*/
\r
265 static void vCompeteingIntMathTask4( void *pvParameters )
\r
267 portLONG *plArray, lTotal1, lTotal2;
\r
268 portSHORT sError = pdFALSE;
\r
269 volatile unsigned portSHORT *pusTaskCheckVariable;
\r
270 const unsigned portSHORT usArraySize = 250;
\r
271 unsigned portSHORT usPosition;
\r
272 const portCHAR * const pcTaskStartMsg = "Integer math task 4 started.\r\n";
\r
273 const portCHAR * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
\r
275 /* Queue a message for printing to say the task has started. */
\r
276 vPrintDisplayMessage( &pcTaskStartMsg );
\r
278 /* The variable this task increments to show it is still running is passed in
\r
279 as the parameter. */
\r
280 pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;
\r
282 /* Create the array we are going to use for our check calculation. */
\r
283 plArray = ( portLONG * ) pvPortMalloc( ( size_t ) 250 * sizeof( portLONG ) );
\r
285 /* Keep filling the array, keeping a running total of the values placed in the
\r
286 array. Then run through the array adding up all the values. If the two totals
\r
287 do not match, stop the check variable from incrementing. */
\r
290 lTotal1 = ( portLONG ) 0;
\r
291 lTotal2 = ( portLONG ) 0;
\r
293 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
295 plArray[ usPosition ] = ( portLONG ) usPosition * ( portLONG ) 12;
\r
296 lTotal1 += ( portLONG ) usPosition * ( portLONG ) 12;
\r
301 for( usPosition = 0; usPosition < usArraySize; usPosition++ )
\r
303 lTotal2 += plArray[ usPosition ];
\r
307 if( lTotal1 != lTotal2 )
\r
309 vPrintDisplayMessage( &pcTaskFailMsg );
\r
315 if( sError == pdFALSE )
\r
317 /* If the calculation has always been correct, increment the check
\r
318 variable so we know this task is still running okay. */
\r
319 ( *pusTaskCheckVariable )++;
\r
323 /*-----------------------------------------------------------*/
\r
325 /* This is called to check that all the created tasks are still running. */
\r
326 portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )
\r
328 /* Keep a history of the check variables so we know if they have been incremented
\r
329 since the last call. */
\r
330 static unsigned portSHORT usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };
\r
331 portBASE_TYPE xReturn = pdTRUE, xTask;
\r
333 /* Check the maths tasks are still running by ensuring their check variables
\r
334 are still incrementing. */
\r
335 for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ )
\r
337 if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
\r
339 /* The check has not incremented so an error exists. */
\r
343 usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];
\r