]> git.sur5r.net Git - freertos/blob - Demo/Common/Full/flop.c
Prepare for V5.3.0 release.
[freertos] / Demo / Common / Full / flop.c
1 /*\r
2         FreeRTOS.org V5.3.0 - Copyright (C) 2003-2009 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify it\r
7         under the terms of the GNU General Public License (version 2) as published\r
8         by the 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.org without being obliged to provide\r
11         the source code for any proprietary components.  Alternative commercial\r
12         license and support terms are also available upon request.  See the \r
13         licensing section of http://www.FreeRTOS.org for full details.\r
14 \r
15         FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT\r
16         ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
17         FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
18         more details.\r
19 \r
20         You should have received a copy of the GNU General Public License along\r
21         with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59\r
22         Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
23 \r
24 \r
25         ***************************************************************************\r
26         *                                                                         *\r
27         * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
28         *                                                                         *\r
29         * This is a concise, step by step, 'hands on' guide that describes both   *\r
30         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
31         * explains numerous examples that are written using the FreeRTOS API.     *\r
32         * Full source code for all the examples is provided in an accompanying    *\r
33         * .zip file.                                                              *\r
34         *                                                                         *\r
35         ***************************************************************************\r
36 \r
37         1 tab == 4 spaces!\r
38 \r
39         Please ensure to read the configuration and relevant port sections of the\r
40         online documentation.\r
41 \r
42         http://www.FreeRTOS.org - Documentation, latest information, license and\r
43         contact details.\r
44 \r
45         http://www.SafeRTOS.com - A version that is certified for use in safety\r
46         critical systems.\r
47 \r
48         http://www.OpenRTOS.com - Commercial support, development, porting,\r
49         licensing and training services.\r
50 */\r
51 \r
52 /*\r
53 Changes from V1.2.3\r
54         \r
55         + The created tasks now include calls to tskYIELD(), allowing them to be used\r
56           with the cooperative scheduler.\r
57 */\r
58 \r
59 /**\r
60  * Creates eight tasks, each of which loops continuously performing an (emulated) \r
61  * floating point calculation.\r
62  *\r
63  * All the tasks run at the idle priority and never block or yield.  This causes \r
64  * all eight tasks to time slice with the idle task.  Running at the idle priority \r
65  * means that these tasks will get pre-empted any time another task is ready to run\r
66  * or a time slice occurs.  More often than not the pre-emption will occur mid \r
67  * calculation, creating a good test of the schedulers context switch mechanism - a \r
68  * calculation producing an unexpected result could be a symptom of a corruption in \r
69  * the context of a task.\r
70  *\r
71  * \page FlopC flop.c\r
72  * \ingroup DemoFiles\r
73  * <HR>\r
74  */\r
75 \r
76 #include <stdlib.h>\r
77 #include <math.h>\r
78 \r
79 /* Scheduler include files. */\r
80 #include "FreeRTOS.h"\r
81 #include "task.h"\r
82 #include "print.h"\r
83 \r
84 /* Demo program include files. */\r
85 #include "flop.h"\r
86 \r
87 #define mathSTACK_SIZE          ( ( unsigned portSHORT ) 512 )\r
88 #define mathNUMBER_OF_TASKS  ( 8 )\r
89 \r
90 /* Four tasks, each of which performs a different floating point calculation.  \r
91 Each of the four is created twice. */\r
92 static void vCompetingMathTask1( void *pvParameters );\r
93 static void vCompetingMathTask2( void *pvParameters );\r
94 static void vCompetingMathTask3( void *pvParameters );\r
95 static void vCompetingMathTask4( void *pvParameters );\r
96 \r
97 /* These variables are used to check that all the tasks are still running.  If a \r
98 task gets a calculation wrong it will\r
99 stop incrementing its check variable. */\r
100 static volatile unsigned portSHORT usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };\r
101 \r
102 /*-----------------------------------------------------------*/\r
103 \r
104 void vStartMathTasks( unsigned portBASE_TYPE uxPriority )\r
105 {\r
106         xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );\r
107         xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );\r
108         xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );\r
109         xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );\r
110         xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );\r
111         xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );\r
112         xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );\r
113         xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );\r
114 }\r
115 /*-----------------------------------------------------------*/\r
116 \r
117 static void vCompetingMathTask1( void *pvParameters )\r
118 {\r
119 portDOUBLE d1, d2, d3, d4;\r
120 volatile unsigned portSHORT *pusTaskCheckVariable;\r
121 const portDOUBLE dAnswer = ( 123.4567 + 2345.6789 ) * -918.222;\r
122 const portCHAR * const pcTaskStartMsg = "Math task 1 started.\r\n";\r
123 const portCHAR * const pcTaskFailMsg = "Math task 1 failed.\r\n";\r
124 portSHORT sError = pdFALSE;\r
125 \r
126         /* Queue a message for printing to say the task has started. */\r
127         vPrintDisplayMessage( &pcTaskStartMsg );\r
128 \r
129         /* The variable this task increments to show it is still running is passed in \r
130         as the parameter. */\r
131         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
132 \r
133         /* Keep performing a calculation and checking the result against a constant. */\r
134         for(;;)\r
135         {\r
136                 d1 = 123.4567;\r
137                 d2 = 2345.6789;\r
138                 d3 = -918.222;\r
139 \r
140                 d4 = ( d1 + d2 ) * d3;\r
141 \r
142                 taskYIELD();\r
143 \r
144                 /* If the calculation does not match the expected constant, stop the \r
145                 increment of the check variable. */\r
146                 if( fabs( d4 - dAnswer ) > 0.001 )\r
147                 {\r
148                         vPrintDisplayMessage( &pcTaskFailMsg );\r
149                         sError = pdTRUE;\r
150                 }\r
151 \r
152                 if( sError == pdFALSE )\r
153                 {\r
154                         /* If the calculation has always been correct, increment the check \r
155                         variable so we know this task is still running okay. */\r
156                         ( *pusTaskCheckVariable )++;\r
157                 }\r
158 \r
159                 taskYIELD();\r
160         }\r
161 }\r
162 /*-----------------------------------------------------------*/\r
163 \r
164 static void vCompetingMathTask2( void *pvParameters )\r
165 {\r
166 portDOUBLE d1, d2, d3, d4;\r
167 volatile unsigned portSHORT *pusTaskCheckVariable;\r
168 const portDOUBLE dAnswer = ( -389.38 / 32498.2 ) * -2.0001;\r
169 const portCHAR * const pcTaskStartMsg = "Math task 2 started.\r\n";\r
170 const portCHAR * const pcTaskFailMsg = "Math task 2 failed.\r\n";\r
171 portSHORT sError = pdFALSE;\r
172 \r
173         /* Queue a message for printing to say the task has started. */\r
174         vPrintDisplayMessage( &pcTaskStartMsg );\r
175 \r
176         /* The variable this task increments to show it is still running is passed in \r
177         as the parameter. */\r
178         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
179 \r
180         /* Keep performing a calculation and checking the result against a constant. */\r
181         for( ;; )\r
182         {\r
183                 d1 = -389.38;\r
184                 d2 = 32498.2;\r
185                 d3 = -2.0001;\r
186 \r
187                 d4 = ( d1 / d2 ) * d3;\r
188 \r
189                 taskYIELD();\r
190                 \r
191                 /* If the calculation does not match the expected constant, stop the \r
192                 increment of the check variable. */\r
193                 if( fabs( d4 - dAnswer ) > 0.001 )\r
194                 {\r
195                         vPrintDisplayMessage( &pcTaskFailMsg );\r
196                         sError = pdTRUE;\r
197                 }\r
198 \r
199                 if( sError == pdFALSE )\r
200                 {\r
201                         /* If the calculation has always been correct, increment the check \r
202                         variable so we know\r
203                         this task is still running okay. */\r
204                         ( *pusTaskCheckVariable )++;\r
205                 }\r
206 \r
207                 taskYIELD();\r
208         }\r
209 }\r
210 /*-----------------------------------------------------------*/\r
211 \r
212 static void vCompetingMathTask3( void *pvParameters )\r
213 {\r
214 portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;\r
215 volatile unsigned portSHORT *pusTaskCheckVariable;\r
216 const unsigned portSHORT usArraySize = 250;\r
217 unsigned portSHORT usPosition;\r
218 const portCHAR * const pcTaskStartMsg = "Math task 3 started.\r\n";\r
219 const portCHAR * const pcTaskFailMsg = "Math task 3 failed.\r\n";\r
220 portSHORT sError = pdFALSE;\r
221 \r
222         /* Queue a message for printing to say the task has started. */\r
223         vPrintDisplayMessage( &pcTaskStartMsg );\r
224 \r
225         /* The variable this task increments to show it is still running is passed in \r
226         as the parameter. */\r
227         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
228 \r
229         pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );\r
230 \r
231         /* Keep filling an array, keeping a running total of the values placed in the \r
232         array.  Then run through the array adding up all the values.  If the two totals \r
233         do not match, stop the check variable from incrementing. */\r
234         for( ;; )\r
235         {\r
236                 dTotal1 = 0.0;\r
237                 dTotal2 = 0.0;\r
238 \r
239                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
240                 {\r
241                         pdArray[ usPosition ] = ( portDOUBLE ) usPosition + 5.5;\r
242                         dTotal1 += ( portDOUBLE ) usPosition + 5.5;     \r
243                 }\r
244 \r
245                 taskYIELD();\r
246 \r
247                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
248                 {\r
249                         dTotal2 += pdArray[ usPosition ];\r
250                 }\r
251 \r
252                 dDifference = dTotal1 - dTotal2;\r
253                 if( fabs( dDifference ) > 0.001 )\r
254                 {\r
255                         vPrintDisplayMessage( &pcTaskFailMsg );\r
256                         sError = pdTRUE;\r
257                 }\r
258 \r
259                 taskYIELD();\r
260 \r
261                 if( sError == pdFALSE )\r
262                 {\r
263                         /* If the calculation has always been correct, increment the check \r
264                         variable so we know     this task is still running okay. */\r
265                         ( *pusTaskCheckVariable )++;\r
266                 }\r
267         }\r
268 }\r
269 /*-----------------------------------------------------------*/\r
270 \r
271 static void vCompetingMathTask4( void *pvParameters )\r
272 {\r
273 portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;\r
274 volatile unsigned portSHORT *pusTaskCheckVariable;\r
275 const unsigned portSHORT usArraySize = 250;\r
276 unsigned portSHORT usPosition;\r
277 const portCHAR * const pcTaskStartMsg = "Math task 4 started.\r\n";\r
278 const portCHAR * const pcTaskFailMsg = "Math task 4 failed.\r\n";\r
279 portSHORT sError = pdFALSE;\r
280 \r
281         /* Queue a message for printing to say the task has started. */\r
282         vPrintDisplayMessage( &pcTaskStartMsg );\r
283 \r
284         /* The variable this task increments to show it is still running is passed in \r
285         as the parameter. */\r
286         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
287 \r
288         pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );\r
289 \r
290         /* Keep filling an array, keeping a running total of the values placed in the \r
291         array.  Then run through the array adding up all the values.  If the two totals \r
292         do not match, stop the check variable from incrementing. */\r
293         for( ;; )\r
294         {\r
295                 dTotal1 = 0.0;\r
296                 dTotal2 = 0.0;\r
297 \r
298                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
299                 {\r
300                         pdArray[ usPosition ] = ( portDOUBLE ) usPosition * 12.123;\r
301                         dTotal1 += ( portDOUBLE ) usPosition * 12.123;  \r
302                 }\r
303 \r
304                 taskYIELD();\r
305 \r
306                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
307                 {\r
308                         dTotal2 += pdArray[ usPosition ];\r
309                 }\r
310 \r
311                 dDifference = dTotal1 - dTotal2;\r
312                 if( fabs( dDifference ) > 0.001 )\r
313                 {\r
314                         vPrintDisplayMessage( &pcTaskFailMsg );\r
315                         sError = pdTRUE;\r
316                 }\r
317 \r
318                 taskYIELD();\r
319 \r
320                 if( sError == pdFALSE )\r
321                 {\r
322                         /* If the calculation has always been correct, increment the check \r
323                         variable so we know     this task is still running okay. */\r
324                         ( *pusTaskCheckVariable )++;\r
325                 }\r
326         }\r
327 }\r
328 /*-----------------------------------------------------------*/\r
329 \r
330 /* This is called to check that all the created tasks are still running. */\r
331 portBASE_TYPE xAreMathsTaskStillRunning( void )\r
332 {\r
333 /* Keep a history of the check variables so we know if they have been incremented \r
334 since the last call. */\r
335 static unsigned portSHORT usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };\r
336 portBASE_TYPE xReturn = pdTRUE, xTask;\r
337 \r
338         /* Check the maths tasks are still running by ensuring their check variables \r
339         are still incrementing. */\r
340         for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )\r
341         {\r
342                 if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )\r
343                 {\r
344                         /* The check has not incremented so an error exists. */\r
345                         xReturn = pdFALSE;\r
346                 }\r
347 \r
348                 usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];\r
349         }\r
350 \r
351         return xReturn;\r
352 }\r
353 \r
354 \r
355 \r