]> begriffs open source - freertos/blob - Demo/PPC440_SP_FPU_Xilinx_Virtex5_GCC/RTOSDemo/flop/flop.c
Update version number.
[freertos] / Demo / PPC440_SP_FPU_Xilinx_Virtex5_GCC / RTOSDemo / flop / flop.c
1 /*\r
2         FreeRTOS.org V5.4.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  * Creates eight tasks, each of which loops continuously performing a\r
54  * floating point calculation.\r
55  *\r
56  * All the tasks run at the idle priority and never block or yield.  This causes \r
57  * all eight tasks to time slice with the idle task.  Running at the idle priority \r
58  * means that these tasks will get pre-empted any time another task is ready to run\r
59  * or a time slice occurs.  More often than not the pre-emption will occur mid \r
60  * calculation, creating a good test of the schedulers context switch mechanism - a \r
61  * calculation producing an unexpected result could be a symptom of a corruption in \r
62  * the context of a task.\r
63  *\r
64  * This file demonstrates the use of the task tag and traceTASK_SWITCHED_IN and\r
65  * traceTASK_SWITCHED_OUT macros to save and restore the floating point context.\r
66  */\r
67 \r
68 #include <stdlib.h>\r
69 #include <math.h>\r
70 \r
71 /* Scheduler include files. */\r
72 #include "FreeRTOS.h"\r
73 #include "task.h"\r
74 \r
75 /* Demo program include files. */\r
76 #include "flop.h"\r
77 \r
78 /* Misc. definitions. */\r
79 #define mathSTACK_SIZE          configMINIMAL_STACK_SIZE\r
80 #define mathNUMBER_OF_TASKS  ( 8 )\r
81 \r
82 /* Four tasks, each of which performs a different floating point calculation.  \r
83 Each of the four is created twice. */\r
84 static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );\r
85 static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );\r
86 static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );\r
87 static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );\r
88 \r
89 /* These variables are used to check that all the tasks are still running.  If a \r
90 task gets a calculation wrong it will stop incrementing its check variable. */\r
91 static volatile unsigned portSHORT usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };\r
92 \r
93 /* Buffers into which the flop registers will be saved.  There is a buffer for \r
94 each task created within this file.  Zeroing out this array is the normal and\r
95 safe option as this will cause the task to start with all zeros in its flop\r
96 context. */\r
97 static unsigned portLONG ulFlopRegisters[ mathNUMBER_OF_TASKS ][ portNO_FLOP_REGISTERS_TO_SAVE ];\r
98 \r
99 /*-----------------------------------------------------------*/\r
100 \r
101 void vStartMathTasks( unsigned portBASE_TYPE uxPriority )\r
102 {\r
103 xTaskHandle xTaskJustCreated;\r
104 portBASE_TYPE x, y;\r
105 \r
106         /* Place known values into the buffers into which the flop registers are \r
107         to be saved.  This is for debug purposes only, it is not normally\r
108         required.  The last position in each array is left at zero as the status\r
109         register will be loaded from there. \r
110         \r
111         It is intended that these values can be viewed being loaded into the\r
112         flop registers when a task is started - however the Insight debugger\r
113         does not seem to want to show the flop register values. */\r
114         for( x = 0; x < mathNUMBER_OF_TASKS; x++ )\r
115         {\r
116                 for( y = 0; y < ( portNO_FLOP_REGISTERS_TO_SAVE - 1 ); y++ )\r
117                 {\r
118                         ulFlopRegisters[ x ][ y ] = ( x + 1 );\r
119                 }\r
120         }\r
121 \r
122         /* Create the first task - passing it the address of the check variable\r
123         that it is going to increment.  This check variable is used as an \r
124         indication that the task is still running. */\r
125         xTaskCreate( vCompetingMathTask1, ( signed portCHAR * ) "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, &xTaskJustCreated );\r
126 \r
127         /* The task     tag value is a value that can be associated with a task, but \r
128         is not used by the scheduler itself.  Its use is down to the application so\r
129         it makes a convenient place in this case to store the pointer to the buffer\r
130         into which the flop context of the task will be stored.  The first created\r
131         task uses ulFlopRegisters[ 0 ], the second ulFlopRegisters[ 1 ], etc. */\r
132         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 0 ][ 0 ] ) );\r
133 \r
134         /* Create another 7 tasks, allocating a buffer for each. */\r
135         xTaskCreate( vCompetingMathTask2, ( signed portCHAR * ) "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, &xTaskJustCreated  );\r
136         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 1 ][ 0 ] ) );\r
137 \r
138         xTaskCreate( vCompetingMathTask3, ( signed portCHAR * ) "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, &xTaskJustCreated  );\r
139         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 2 ][ 0 ] ) );\r
140 \r
141         xTaskCreate( vCompetingMathTask4, ( signed portCHAR * ) "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, &xTaskJustCreated  );\r
142         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 3 ][ 0 ] ) );\r
143 \r
144         xTaskCreate( vCompetingMathTask1, ( signed portCHAR * ) "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, &xTaskJustCreated  );\r
145         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 4 ][ 0 ] ) );\r
146 \r
147         xTaskCreate( vCompetingMathTask2, ( signed portCHAR * ) "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, &xTaskJustCreated  );\r
148         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 5 ][ 0 ] ) );\r
149 \r
150         xTaskCreate( vCompetingMathTask3, ( signed portCHAR * ) "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, &xTaskJustCreated  );\r
151         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 6 ][ 0 ] ) );\r
152 \r
153         xTaskCreate( vCompetingMathTask4, ( signed portCHAR * ) "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, &xTaskJustCreated  );\r
154         vTaskSetApplicationTaskTag( xTaskJustCreated, ( void * ) &( ulFlopRegisters[ 7 ][ 0 ] ) );\r
155 }\r
156 /*-----------------------------------------------------------*/\r
157 \r
158 static portTASK_FUNCTION( vCompetingMathTask1, pvParameters )\r
159 {\r
160 volatile portFLOAT ff1, ff2, ff3, ff4;\r
161 volatile unsigned portSHORT *pusTaskCheckVariable;\r
162 volatile portFLOAT fAnswer;\r
163 portSHORT sError = pdFALSE;\r
164 \r
165         ff1 = 123.4567F;\r
166         ff2 = 2345.6789F;\r
167         ff3 = -918.222F;\r
168 \r
169         fAnswer = ( ff1 + ff2 ) * ff3;\r
170 \r
171         /* The variable this task increments to show it is still running is passed in \r
172         as the parameter. */\r
173         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
174 \r
175         /* Keep performing a calculation and checking the result against a constant. */\r
176         for(;;)\r
177         {\r
178                 ff1 = 123.4567F;\r
179                 ff2 = 2345.6789F;\r
180                 ff3 = -918.222F;\r
181 \r
182                 ff4 = ( ff1 + ff2 ) * ff3;\r
183 \r
184                 #if configUSE_PREEMPTION == 0\r
185                         taskYIELD();\r
186                 #endif\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( fabs( ff4 - fAnswer ) > 0.001F )\r
191                 {\r
192                         sError = pdTRUE;\r
193                 }\r
194 \r
195                 if( sError == pdFALSE )\r
196                 {\r
197                         /* If the calculation has always been correct, increment the check \r
198                         variable so we know this task is still running okay. */\r
199                         ( *pusTaskCheckVariable )++;\r
200                 }\r
201 \r
202                 #if configUSE_PREEMPTION == 0\r
203                         taskYIELD();\r
204                 #endif\r
205 \r
206         }\r
207 }\r
208 /*-----------------------------------------------------------*/\r
209 \r
210 static portTASK_FUNCTION( vCompetingMathTask2, pvParameters )\r
211 {\r
212 volatile portFLOAT ff1, ff2, ff3, ff4;\r
213 volatile unsigned portSHORT *pusTaskCheckVariable;\r
214 volatile portFLOAT fAnswer;\r
215 portSHORT sError = pdFALSE;\r
216 \r
217         ff1 = -389.38F;\r
218         ff2 = 32498.2F;\r
219         ff3 = -2.0001F;\r
220 \r
221         fAnswer = ( ff1 / ff2 ) * ff3;\r
222 \r
223 \r
224         /* The variable this task increments to show it is still running is passed in \r
225         as the parameter. */\r
226         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
227 \r
228         /* Keep performing a calculation and checking the result against a constant. */\r
229         for( ;; )\r
230         {\r
231                 ff1 = -389.38F;\r
232                 ff2 = 32498.2F;\r
233                 ff3 = -2.0001F;\r
234 \r
235                 ff4 = ( ff1 / ff2 ) * ff3;\r
236 \r
237                 #if configUSE_PREEMPTION == 0\r
238                         taskYIELD();\r
239                 #endif\r
240                 \r
241                 /* If the calculation does not match the expected constant, stop the \r
242                 increment of the check variable. */\r
243                 if( fabs( ff4 - fAnswer ) > 0.001F )\r
244                 {\r
245                         sError = pdTRUE;\r
246                 }\r
247 \r
248                 if( sError == pdFALSE )\r
249                 {\r
250                         /* If the calculation has always been correct, increment the check \r
251                         variable so we know\r
252                         this task is still running okay. */\r
253                         ( *pusTaskCheckVariable )++;\r
254                 }\r
255 \r
256                 #if configUSE_PREEMPTION == 0\r
257                         taskYIELD();\r
258                 #endif\r
259         }\r
260 }\r
261 /*-----------------------------------------------------------*/\r
262 \r
263 static portTASK_FUNCTION( vCompetingMathTask3, pvParameters )\r
264 {\r
265 volatile portFLOAT *pfArray, fTotal1, fTotal2, fDifference;\r
266 volatile unsigned portSHORT *pusTaskCheckVariable;\r
267 const size_t xArraySize = 10;\r
268 size_t xPosition;\r
269 portSHORT sError = pdFALSE;\r
270 \r
271         /* The variable this task increments to show it is still running is passed in \r
272         as the parameter. */\r
273         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
274 \r
275         pfArray = ( portFLOAT * ) pvPortMalloc( xArraySize * sizeof( portFLOAT ) );\r
276 \r
277         /* Keep filling an array, keeping a running total of the values placed in the \r
278         array.  Then run through the array adding up all the values.  If the two totals \r
279         do not match, stop the check variable from incrementing. */\r
280         for( ;; )\r
281         {\r
282                 fTotal1 = 0.0F;\r
283                 fTotal2 = 0.0F;\r
284 \r
285                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
286                 {\r
287                         pfArray[ xPosition ] = ( portFLOAT ) xPosition + 5.5F;\r
288                         fTotal1 += ( portFLOAT ) xPosition + 5.5F;      \r
289                 }\r
290 \r
291                 #if configUSE_PREEMPTION == 0\r
292                         taskYIELD();\r
293                 #endif\r
294 \r
295                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
296                 {\r
297                         fTotal2 += pfArray[ xPosition ];\r
298                 }\r
299 \r
300                 fDifference = fTotal1 - fTotal2;\r
301                 if( fabs( fDifference ) > 0.001F )\r
302                 {\r
303                         sError = pdTRUE;\r
304                 }\r
305 \r
306                 #if configUSE_PREEMPTION == 0\r
307                         taskYIELD();\r
308                 #endif\r
309 \r
310                 if( sError == pdFALSE )\r
311                 {\r
312                         /* If the calculation has always been correct, increment the check \r
313                         variable so we know     this task is still running okay. */\r
314                         ( *pusTaskCheckVariable )++;\r
315                 }\r
316         }\r
317 }\r
318 /*-----------------------------------------------------------*/\r
319 \r
320 static portTASK_FUNCTION( vCompetingMathTask4, pvParameters )\r
321 {\r
322 volatile portFLOAT *pfArray, fTotal1, fTotal2, fDifference;\r
323 volatile unsigned portSHORT *pusTaskCheckVariable;\r
324 const size_t xArraySize = 10;\r
325 size_t xPosition;\r
326 portSHORT sError = pdFALSE;\r
327 \r
328         /* The variable this task increments to show it is still running is passed in \r
329         as the parameter. */\r
330         pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters;\r
331 \r
332         pfArray = ( portFLOAT * ) pvPortMalloc( xArraySize * sizeof( portFLOAT ) );\r
333 \r
334         /* Keep filling an array, keeping a running total of the values placed in the \r
335         array.  Then run through the array adding up all the values.  If the two totals \r
336         do not match, stop the check variable from incrementing. */\r
337         for( ;; )\r
338         {\r
339                 fTotal1 = 0.0F;\r
340                 fTotal2 = 0.0F;\r
341 \r
342                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
343                 {\r
344                         pfArray[ xPosition ] = ( portFLOAT ) xPosition * 12.123F;\r
345                         fTotal1 += ( portFLOAT ) xPosition * 12.123F;   \r
346                 }\r
347 \r
348                 #if configUSE_PREEMPTION == 0\r
349                         taskYIELD();\r
350                 #endif\r
351 \r
352                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )\r
353                 {\r
354                         fTotal2 += pfArray[ xPosition ];\r
355                 }\r
356 \r
357                 fDifference = fTotal1 - fTotal2;\r
358                 if( fabs( fDifference ) > 0.001F )\r
359                 {\r
360                         sError = pdTRUE;\r
361                 }\r
362 \r
363                 #if configUSE_PREEMPTION == 0\r
364                         taskYIELD();\r
365                 #endif\r
366 \r
367                 if( sError == pdFALSE )\r
368                 {\r
369                         /* If the calculation has always been correct, increment the check \r
370                         variable so we know     this task is still running okay. */\r
371                         ( *pusTaskCheckVariable )++;\r
372                 }\r
373         }\r
374 }                                \r
375 /*-----------------------------------------------------------*/\r
376 \r
377 /* This is called to check that all the created tasks are still running. */\r
378 portBASE_TYPE xAreMathsTaskStillRunning( void )\r
379 {\r
380 /* Keep a history of the check variables so we know if they have been incremented \r
381 since the last call. */\r
382 static unsigned portSHORT usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 };\r
383 portBASE_TYPE xReturn = pdTRUE, xTask;\r
384 \r
385         /* Check the maths tasks are still running by ensuring their check variables \r
386         are still incrementing. */\r
387         for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )\r
388         {\r
389                 if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )\r
390                 {\r
391                         /* The check has not incremented so an error exists. */\r
392                         xReturn = pdFALSE;\r
393                 }\r
394 \r
395                 usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];\r
396         }\r
397 \r
398         return xReturn;\r
399 }\r
400 \r
401 \r
402 \r