]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Full/flop.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / Common / Full / flop.c
1 /*\r
2     FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.\r
3         \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\r
11      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
12      *    ensuring you get running as quickly as possible and with an        *\r
13      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
14      *    the FreeRTOS project to continue with its mission of providing     *\r
15      *    professional grade, cross platform, de facto standard solutions    *\r
16      *    for microcontrollers - completely free of charge!                  *\r
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     >>>NOTE<<< The modification to the GPL is included to allow you to\r
31     distribute a combined work that includes FreeRTOS without being obliged to\r
32     provide the source code for proprietary components outside of the FreeRTOS\r
33     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
34     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
35     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public\r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43     \r
44     ***************************************************************************\r
45      *                                                                       *\r
46      *    Having a problem?  Start by reading the FAQ "My application does   *\r
47      *    not run, what could be wrong?                                      *\r
48      *                                                                       *\r
49      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
50      *                                                                       *\r
51     ***************************************************************************\r
52 \r
53     \r
54     http://www.FreeRTOS.org - Documentation, training, latest information, \r
55     license and contact details.\r
56     \r
57     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
58     including FreeRTOS+Trace - an indispensable productivity tool.\r
59 \r
60     Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
61     the code with commercial support, indemnification, and middleware, under \r
62     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
63     provide a safety engineered and independently SIL3 certified version under \r
64     the SafeRTOS brand: http://www.SafeRTOS.com.\r
65 */\r
66 \r
67 /*\r
68 Changes from V1.2.3\r
69         \r
70         + The created tasks now include calls to tskYIELD(), allowing them to be used\r
71           with the cooperative scheduler.\r
72 */\r
73 \r
74 /**\r
75  * Creates eight tasks, each of which loops continuously performing an (emulated) \r
76  * floating point calculation.\r
77  *\r
78  * All the tasks run at the idle priority and never block or yield.  This causes \r
79  * all eight tasks to time slice with the idle task.  Running at the idle priority \r
80  * means that these tasks will get pre-empted any time another task is ready to run\r
81  * or a time slice occurs.  More often than not the pre-emption will occur mid \r
82  * calculation, creating a good test of the schedulers context switch mechanism - a \r
83  * calculation producing an unexpected result could be a symptom of a corruption in \r
84  * the context of a task.\r
85  *\r
86  * \page FlopC flop.c\r
87  * \ingroup DemoFiles\r
88  * <HR>\r
89  */\r
90 \r
91 #include <stdlib.h>\r
92 #include <math.h>\r
93 \r
94 /* Scheduler include files. */\r
95 #include "FreeRTOS.h"\r
96 #include "task.h"\r
97 #include "print.h"\r
98 \r
99 /* Demo program include files. */\r
100 #include "flop.h"\r
101 \r
102 #define mathSTACK_SIZE          ( ( unsigned short ) 512 )\r
103 #define mathNUMBER_OF_TASKS  ( 8 )\r
104 \r
105 /* Four tasks, each of which performs a different floating point calculation.  \r
106 Each of the four is created twice. */\r
107 static void vCompetingMathTask1( void *pvParameters );\r
108 static void vCompetingMathTask2( void *pvParameters );\r
109 static void vCompetingMathTask3( void *pvParameters );\r
110 static void vCompetingMathTask4( void *pvParameters );\r
111 \r
112 /* These variables are used to check that all the tasks are still running.  If a \r
113 task gets a calculation wrong it will\r
114 stop incrementing its check variable. */\r
115 static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };\r
116 \r
117 /*-----------------------------------------------------------*/\r
118 \r
119 void vStartMathTasks( unsigned portBASE_TYPE uxPriority )\r
120 {\r
121         xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );\r
122         xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );\r
123         xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );\r
124         xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );\r
125         xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );\r
126         xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );\r
127         xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );\r
128         xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );\r
129 }\r
130 /*-----------------------------------------------------------*/\r
131 \r
132 static void vCompetingMathTask1( void *pvParameters )\r
133 {\r
134 portDOUBLE d1, d2, d3, d4;\r
135 volatile unsigned short *pusTaskCheckVariable;\r
136 const portDOUBLE dAnswer = ( 123.4567 + 2345.6789 ) * -918.222;\r
137 const char * const pcTaskStartMsg = "Math task 1 started.\r\n";\r
138 const char * const pcTaskFailMsg = "Math task 1 failed.\r\n";\r
139 short sError = pdFALSE;\r
140 \r
141         /* Queue a message for printing to say the task has started. */\r
142         vPrintDisplayMessage( &pcTaskStartMsg );\r
143 \r
144         /* The variable this task increments to show it is still running is passed in \r
145         as the parameter. */\r
146         pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
147 \r
148         /* Keep performing a calculation and checking the result against a constant. */\r
149         for(;;)\r
150         {\r
151                 d1 = 123.4567;\r
152                 d2 = 2345.6789;\r
153                 d3 = -918.222;\r
154 \r
155                 d4 = ( d1 + d2 ) * d3;\r
156 \r
157                 taskYIELD();\r
158 \r
159                 /* If the calculation does not match the expected constant, stop the \r
160                 increment of the check variable. */\r
161                 if( fabs( d4 - dAnswer ) > 0.001 )\r
162                 {\r
163                         vPrintDisplayMessage( &pcTaskFailMsg );\r
164                         sError = pdTRUE;\r
165                 }\r
166 \r
167                 if( sError == pdFALSE )\r
168                 {\r
169                         /* If the calculation has always been correct, increment the check \r
170                         variable so we know this task is still running okay. */\r
171                         ( *pusTaskCheckVariable )++;\r
172                 }\r
173 \r
174                 taskYIELD();\r
175         }\r
176 }\r
177 /*-----------------------------------------------------------*/\r
178 \r
179 static void vCompetingMathTask2( void *pvParameters )\r
180 {\r
181 portDOUBLE d1, d2, d3, d4;\r
182 volatile unsigned short *pusTaskCheckVariable;\r
183 const portDOUBLE dAnswer = ( -389.38 / 32498.2 ) * -2.0001;\r
184 const char * const pcTaskStartMsg = "Math task 2 started.\r\n";\r
185 const char * const pcTaskFailMsg = "Math task 2 failed.\r\n";\r
186 short sError = pdFALSE;\r
187 \r
188         /* Queue a message for printing to say the task has started. */\r
189         vPrintDisplayMessage( &pcTaskStartMsg );\r
190 \r
191         /* The variable this task increments to show it is still running is passed in \r
192         as the parameter. */\r
193         pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
194 \r
195         /* Keep performing a calculation and checking the result against a constant. */\r
196         for( ;; )\r
197         {\r
198                 d1 = -389.38;\r
199                 d2 = 32498.2;\r
200                 d3 = -2.0001;\r
201 \r
202                 d4 = ( d1 / d2 ) * d3;\r
203 \r
204                 taskYIELD();\r
205                 \r
206                 /* If the calculation does not match the expected constant, stop the \r
207                 increment of the check variable. */\r
208                 if( fabs( d4 - dAnswer ) > 0.001 )\r
209                 {\r
210                         vPrintDisplayMessage( &pcTaskFailMsg );\r
211                         sError = pdTRUE;\r
212                 }\r
213 \r
214                 if( sError == pdFALSE )\r
215                 {\r
216                         /* If the calculation has always been correct, increment the check \r
217                         variable so we know\r
218                         this task is still running okay. */\r
219                         ( *pusTaskCheckVariable )++;\r
220                 }\r
221 \r
222                 taskYIELD();\r
223         }\r
224 }\r
225 /*-----------------------------------------------------------*/\r
226 \r
227 static void vCompetingMathTask3( void *pvParameters )\r
228 {\r
229 portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;\r
230 volatile unsigned short *pusTaskCheckVariable;\r
231 const unsigned short usArraySize = 250;\r
232 unsigned short usPosition;\r
233 const char * const pcTaskStartMsg = "Math task 3 started.\r\n";\r
234 const char * const pcTaskFailMsg = "Math task 3 failed.\r\n";\r
235 short sError = pdFALSE;\r
236 \r
237         /* Queue a message for printing to say the task has started. */\r
238         vPrintDisplayMessage( &pcTaskStartMsg );\r
239 \r
240         /* The variable this task increments to show it is still running is passed in \r
241         as the parameter. */\r
242         pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
243 \r
244         pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );\r
245 \r
246         /* Keep filling an array, keeping a running total of the values placed in the \r
247         array.  Then run through the array adding up all the values.  If the two totals \r
248         do not match, stop the check variable from incrementing. */\r
249         for( ;; )\r
250         {\r
251                 dTotal1 = 0.0;\r
252                 dTotal2 = 0.0;\r
253 \r
254                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
255                 {\r
256                         pdArray[ usPosition ] = ( portDOUBLE ) usPosition + 5.5;\r
257                         dTotal1 += ( portDOUBLE ) usPosition + 5.5;     \r
258                 }\r
259 \r
260                 taskYIELD();\r
261 \r
262                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
263                 {\r
264                         dTotal2 += pdArray[ usPosition ];\r
265                 }\r
266 \r
267                 dDifference = dTotal1 - dTotal2;\r
268                 if( fabs( dDifference ) > 0.001 )\r
269                 {\r
270                         vPrintDisplayMessage( &pcTaskFailMsg );\r
271                         sError = pdTRUE;\r
272                 }\r
273 \r
274                 taskYIELD();\r
275 \r
276                 if( sError == pdFALSE )\r
277                 {\r
278                         /* If the calculation has always been correct, increment the check \r
279                         variable so we know     this task is still running okay. */\r
280                         ( *pusTaskCheckVariable )++;\r
281                 }\r
282         }\r
283 }\r
284 /*-----------------------------------------------------------*/\r
285 \r
286 static void vCompetingMathTask4( void *pvParameters )\r
287 {\r
288 portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;\r
289 volatile unsigned short *pusTaskCheckVariable;\r
290 const unsigned short usArraySize = 250;\r
291 unsigned short usPosition;\r
292 const char * const pcTaskStartMsg = "Math task 4 started.\r\n";\r
293 const char * const pcTaskFailMsg = "Math task 4 failed.\r\n";\r
294 short sError = pdFALSE;\r
295 \r
296         /* Queue a message for printing to say the task has started. */\r
297         vPrintDisplayMessage( &pcTaskStartMsg );\r
298 \r
299         /* The variable this task increments to show it is still running is passed in \r
300         as the parameter. */\r
301         pusTaskCheckVariable = ( unsigned short * ) pvParameters;\r
302 \r
303         pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );\r
304 \r
305         /* Keep filling an array, keeping a running total of the values placed in the \r
306         array.  Then run through the array adding up all the values.  If the two totals \r
307         do not match, stop the check variable from incrementing. */\r
308         for( ;; )\r
309         {\r
310                 dTotal1 = 0.0;\r
311                 dTotal2 = 0.0;\r
312 \r
313                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
314                 {\r
315                         pdArray[ usPosition ] = ( portDOUBLE ) usPosition * 12.123;\r
316                         dTotal1 += ( portDOUBLE ) usPosition * 12.123;  \r
317                 }\r
318 \r
319                 taskYIELD();\r
320 \r
321                 for( usPosition = 0; usPosition < usArraySize; usPosition++ )\r
322                 {\r
323                         dTotal2 += pdArray[ usPosition ];\r
324                 }\r
325 \r
326                 dDifference = dTotal1 - dTotal2;\r
327                 if( fabs( dDifference ) > 0.001 )\r
328                 {\r
329                         vPrintDisplayMessage( &pcTaskFailMsg );\r
330                         sError = pdTRUE;\r
331                 }\r
332 \r
333                 taskYIELD();\r
334 \r
335                 if( sError == pdFALSE )\r
336                 {\r
337                         /* If the calculation has always been correct, increment the check \r
338                         variable so we know     this task is still running okay. */\r
339                         ( *pusTaskCheckVariable )++;\r
340                 }\r
341         }\r
342 }\r
343 /*-----------------------------------------------------------*/\r
344 \r
345 /* This is called to check that all the created tasks are still running. */\r
346 portBASE_TYPE xAreMathsTaskStillRunning( void )\r
347 {\r
348 /* Keep a history of the check variables so we know if they have been incremented \r
349 since the last call. */\r
350 static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };\r
351 portBASE_TYPE xReturn = pdTRUE, xTask;\r
352 \r
353         /* Check the maths tasks are still running by ensuring their check variables \r
354         are still incrementing. */\r
355         for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )\r
356         {\r
357                 if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )\r
358                 {\r
359                         /* The check has not incremented so an error exists. */\r
360                         xReturn = pdFALSE;\r
361                 }\r
362 \r
363                 usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];\r
364         }\r
365 \r
366         return xReturn;\r
367 }\r
368 \r
369 \r
370 \r