]> begriffs open source - freertos/blob - Demo/Common/Full/integer.c
Update to V5.4.1
[freertos] / Demo / Common / Full / integer.c
1 /*\r
2         FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd.\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 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
14         license details.\r
15 \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
19         more details.\r
20 \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
24 \r
25 \r
26         ***************************************************************************\r
27         *                                                                         *\r
28         * Looking for a quick start?  Then check out the FreeRTOS eBook!          *\r
29         * See http://www.FreeRTOS.org/Documentation for details                   *\r
30         *                                                                         *\r
31         ***************************************************************************\r
32 \r
33         1 tab == 4 spaces!\r
34 \r
35         Please ensure to read the configuration and relevant port sections of the\r
36         online documentation.\r
37 \r
38         http://www.FreeRTOS.org - Documentation, latest information, license and\r
39         contact details.\r
40 \r
41         http://www.SafeRTOS.com - A version that is certified for use in safety\r
42         critical systems.\r
43 \r
44         http://www.OpenRTOS.com - Commercial support, development, porting,\r
45         licensing and training services.\r
46 */\r
47 \r
48 /*\r
49 Changes from V1.2.3\r
50         \r
51         + The created tasks now include calls to tskYIELD(), allowing them to be used\r
52           with the cooperative scheduler.\r
53 */\r
54 \r
55 /**\r
56  * This does the same as flop. c, but uses variables of type long instead of \r
57  * type double.  \r
58  *\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
64  * more information.\r
65  *\r
66  * \page IntegerC integer.c\r
67  * \ingroup DemoFiles\r
68  * <HR>\r
69  */\r
70 \r
71 /*\r
72 Changes from V1.2.1\r
73 \r
74         + The constants used in the calculations are larger to ensure the\r
75           optimiser does not truncate them to 16 bits.\r
76 */\r
77 \r
78 #include <stdlib.h>\r
79 \r
80 /* Scheduler include files. */\r
81 #include "FreeRTOS.h"\r
82 #include "task.h"\r
83 #include "print.h"\r
84 \r
85 /* Demo program include files. */\r
86 #include "integer.h"\r
87 \r
88 #define intgSTACK_SIZE          ( ( unsigned portSHORT ) 256 )\r
89 #define intgNUMBER_OF_TASKS  ( 8 )\r
90 \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
97 \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
102 \r
103 void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority )\r
104 {\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
113 }\r
114 /*-----------------------------------------------------------*/\r
115 \r
116 static void vCompeteingIntMathTask1( void *pvParameters )\r
117 {\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
124 \r
125         /* Queue a message for printing to say the task has started. */\r
126         vPrintDisplayMessage( &pcTaskStartMsg );\r
127 \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
131 \r
132         /* Keep performing a calculation and checking the result against a constant. */\r
133         for(;;)\r
134         {\r
135                 l1 = ( portLONG ) 74565L;\r
136                 l2 = ( portLONG ) 1234567L;\r
137                 l3 = ( portLONG ) -918L;\r
138 \r
139                 l4 = ( l1 + l2 ) * l3;\r
140 \r
141                 taskYIELD();\r
142 \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
146                 {\r
147                         vPrintDisplayMessage( &pcTaskFailMsg );\r
148                         sError = pdTRUE;\r
149                 }\r
150 \r
151                 if( sError == pdFALSE )\r
152                 {\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
156                 }\r
157         }\r
158 }\r
159 /*-----------------------------------------------------------*/\r
160 \r
161 static void vCompeteingIntMathTask2( void *pvParameters )\r
162 {\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
169 \r
170         /* Queue a message for printing to say the task has started. */\r
171         vPrintDisplayMessage( &pcTaskStartMsg );\r
172 \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
176 \r
177         /* Keep performing a calculation and checking the result against a constant. */\r
178         for( ;; )\r
179         {\r
180                 l1 = -389000L;\r
181                 l2 = 329999L;\r
182                 l3 = -89L;\r
183 \r
184                 l4 = ( l1 / l2 ) * l3;\r
185 \r
186                 taskYIELD();\r
187 \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
191                 {\r
192                         vPrintDisplayMessage( &pcTaskFailMsg );\r
193                         sError = pdTRUE;\r
194                 }\r
195 \r
196                 if( sError == pdFALSE )\r
197                 {\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
201                 }\r
202         }\r
203 }\r
204 /*-----------------------------------------------------------*/\r
205 \r
206 static void vCompeteingIntMathTask3( void *pvParameters )\r
207 {\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
215 \r
216         /* Queue a message for printing to say the task has started. */\r
217         vPrintDisplayMessage( &pcTaskStartMsg );\r
218 \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
222 \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
225 \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
229         for( ;; )\r
230         {\r
231                 lTotal1 = ( portLONG ) 0;\r
232                 lTotal2 = ( portLONG ) 0;\r
233 \r
234                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
235                 {\r
236                         plArray[ usPosition ] = ( portLONG ) usPosition + ( portLONG ) 5;\r
237                         lTotal1 += ( portLONG ) usPosition + ( portLONG ) 5;\r
238                 }\r
239 \r
240                 taskYIELD();\r
241 \r
242                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
243                 {\r
244                         lTotal2 += plArray[ usPosition ];\r
245                 }\r
246 \r
247                 if( lTotal1 != lTotal2 )\r
248                 {\r
249                         vPrintDisplayMessage( &pcTaskFailMsg );\r
250                         sError = pdTRUE;\r
251                 }\r
252 \r
253                 taskYIELD();\r
254 \r
255                 if( sError == pdFALSE )\r
256                 {\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
260                 }\r
261         }\r
262 }\r
263 /*-----------------------------------------------------------*/\r
264 \r
265 static void vCompeteingIntMathTask4( void *pvParameters )\r
266 {\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
274 \r
275         /* Queue a message for printing to say the task has started. */\r
276         vPrintDisplayMessage( &pcTaskStartMsg );\r
277 \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
281 \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
284 \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
288         for( ;; )\r
289         {\r
290                 lTotal1 = ( portLONG ) 0;\r
291                 lTotal2 = ( portLONG ) 0;\r
292 \r
293                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
294                 {\r
295                         plArray[ usPosition ] = ( portLONG ) usPosition * ( portLONG ) 12;\r
296                         lTotal1 += ( portLONG ) usPosition * ( portLONG ) 12;   \r
297                 }\r
298 \r
299                 taskYIELD();\r
300         \r
301                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
302                 {\r
303                         lTotal2 += plArray[ usPosition ];\r
304                 }\r
305 \r
306 \r
307                 if( lTotal1 != lTotal2 )\r
308                 {\r
309                         vPrintDisplayMessage( &pcTaskFailMsg );\r
310                         sError = pdTRUE;\r
311                 }\r
312 \r
313                 taskYIELD();\r
314 \r
315                 if( sError == pdFALSE )\r
316                 {\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
320                 }\r
321         }\r
322 }\r
323 /*-----------------------------------------------------------*/\r
324 \r
325 /* This is called to check that all the created tasks are still running. */\r
326 portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )\r
327 {\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
332 \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
336         {\r
337                 if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )\r
338                 {\r
339                         /* The check has not incremented so an error exists. */\r
340                         xReturn = pdFALSE;\r
341                 }\r
342 \r
343                 usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];\r
344         }\r
345 \r
346         return xReturn;\r
347 }\r