]> git.sur5r.net Git - freertos/blob - Demo/Common/Full/integer.c
First version under SVN is V4.0.1
[freertos] / Demo / Common / Full / integer.c
1 /*\r
2         FreeRTOS V4.0.1 - Copyright (C) 2003-2006 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS distribution.\r
5 \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
10 \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
15 \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
19 \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
24         can be applied.\r
25 \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
31 */\r
32 \r
33 /*\r
34 Changes from V1.2.3\r
35         \r
36         + The created tasks now include calls to tskYIELD(), allowing them to be used\r
37           with the cooperative scheduler.\r
38 */\r
39 \r
40 /**\r
41  * This does the same as flop. c, but uses variables of type long instead of \r
42  * type double.  \r
43  *\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
49  * more information.\r
50  *\r
51  * \page IntegerC integer.c\r
52  * \ingroup DemoFiles\r
53  * <HR>\r
54  */\r
55 \r
56 /*\r
57 Changes from V1.2.1\r
58 \r
59         + The constants used in the calculations are larger to ensure the\r
60           optimiser does not truncate them to 16 bits.\r
61 */\r
62 \r
63 #include <stdlib.h>\r
64 \r
65 /* Scheduler include files. */\r
66 #include "FreeRTOS.h"\r
67 #include "task.h"\r
68 #include "print.h"\r
69 \r
70 /* Demo program include files. */\r
71 #include "integer.h"\r
72 \r
73 #define intgSTACK_SIZE          ( ( unsigned portSHORT ) 256 )\r
74 #define intgNUMBER_OF_TASKS  ( 8 )\r
75 \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
82 \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
87 \r
88 void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority )\r
89 {\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
98 }\r
99 /*-----------------------------------------------------------*/\r
100 \r
101 static void vCompeteingIntMathTask1( void *pvParameters )\r
102 {\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
109 \r
110         /* Queue a message for printing to say the task has started. */\r
111         vPrintDisplayMessage( &pcTaskStartMsg );\r
112 \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
116 \r
117         /* Keep performing a calculation and checking the result against a constant. */\r
118         for(;;)\r
119         {\r
120                 l1 = ( portLONG ) 74565L;\r
121                 l2 = ( portLONG ) 1234567L;\r
122                 l3 = ( portLONG ) -918L;\r
123 \r
124                 l4 = ( l1 + l2 ) * l3;\r
125 \r
126                 taskYIELD();\r
127 \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
131                 {\r
132                         vPrintDisplayMessage( &pcTaskFailMsg );\r
133                         sError = pdTRUE;\r
134                 }\r
135 \r
136                 if( sError == pdFALSE )\r
137                 {\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
141                 }\r
142         }\r
143 }\r
144 /*-----------------------------------------------------------*/\r
145 \r
146 static void vCompeteingIntMathTask2( void *pvParameters )\r
147 {\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
154 \r
155         /* Queue a message for printing to say the task has started. */\r
156         vPrintDisplayMessage( &pcTaskStartMsg );\r
157 \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
161 \r
162         /* Keep performing a calculation and checking the result against a constant. */\r
163         for( ;; )\r
164         {\r
165                 l1 = -389000L;\r
166                 l2 = 329999L;\r
167                 l3 = -89L;\r
168 \r
169                 l4 = ( l1 / l2 ) * l3;\r
170 \r
171                 taskYIELD();\r
172 \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
176                 {\r
177                         vPrintDisplayMessage( &pcTaskFailMsg );\r
178                         sError = pdTRUE;\r
179                 }\r
180 \r
181                 if( sError == pdFALSE )\r
182                 {\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
186                 }\r
187         }\r
188 }\r
189 /*-----------------------------------------------------------*/\r
190 \r
191 static void vCompeteingIntMathTask3( void *pvParameters )\r
192 {\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
200 \r
201         /* Queue a message for printing to say the task has started. */\r
202         vPrintDisplayMessage( &pcTaskStartMsg );\r
203 \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
207 \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
210 \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
214         for( ;; )\r
215         {\r
216                 lTotal1 = ( portLONG ) 0;\r
217                 lTotal2 = ( portLONG ) 0;\r
218 \r
219                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
220                 {\r
221                         plArray[ usPosition ] = ( portLONG ) usPosition + ( portLONG ) 5;\r
222                         lTotal1 += ( portLONG ) usPosition + ( portLONG ) 5;\r
223                 }\r
224 \r
225                 taskYIELD();\r
226 \r
227                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
228                 {\r
229                         lTotal2 += plArray[ usPosition ];\r
230                 }\r
231 \r
232                 if( lTotal1 != lTotal2 )\r
233                 {\r
234                         vPrintDisplayMessage( &pcTaskFailMsg );\r
235                         sError = pdTRUE;\r
236                 }\r
237 \r
238                 taskYIELD();\r
239 \r
240                 if( sError == pdFALSE )\r
241                 {\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
245                 }\r
246         }\r
247 }\r
248 /*-----------------------------------------------------------*/\r
249 \r
250 static void vCompeteingIntMathTask4( void *pvParameters )\r
251 {\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
259 \r
260         /* Queue a message for printing to say the task has started. */\r
261         vPrintDisplayMessage( &pcTaskStartMsg );\r
262 \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
266 \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
269 \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
273         for( ;; )\r
274         {\r
275                 lTotal1 = ( portLONG ) 0;\r
276                 lTotal2 = ( portLONG ) 0;\r
277 \r
278                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
279                 {\r
280                         plArray[ usPosition ] = ( portLONG ) usPosition * ( portLONG ) 12;\r
281                         lTotal1 += ( portLONG ) usPosition * ( portLONG ) 12;   \r
282                 }\r
283 \r
284                 taskYIELD();\r
285         \r
286                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
287                 {\r
288                         lTotal2 += plArray[ usPosition ];\r
289                 }\r
290 \r
291 \r
292                 if( lTotal1 != lTotal2 )\r
293                 {\r
294                         vPrintDisplayMessage( &pcTaskFailMsg );\r
295                         sError = pdTRUE;\r
296                 }\r
297 \r
298                 taskYIELD();\r
299 \r
300                 if( sError == pdFALSE )\r
301                 {\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
305                 }\r
306         }\r
307 }\r
308 /*-----------------------------------------------------------*/\r
309 \r
310 /* This is called to check that all the created tasks are still running. */\r
311 portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )\r
312 {\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
317 \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
321         {\r
322                 if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )\r
323                 {\r
324                         /* The check has not incremented so an error exists. */\r
325                         xReturn = pdFALSE;\r
326                 }\r
327 \r
328                 usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];\r
329         }\r
330 \r
331         return xReturn;\r
332 }\r