]> begriffs open source - cmsis-freertos/blob - Demo/Common/Minimal/flop.c
Update cmsis_os2.c
[cmsis-freertos] / Demo / Common / Minimal / flop.c
1 /*
2     FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
3     All rights reserved
4
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6
7     This file is part of the FreeRTOS distribution.
8
9     FreeRTOS is free software; you can redistribute it and/or modify it under
10     the terms of the GNU General Public License (version 2) as published by the
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
12
13     ***************************************************************************
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<
16     >>!   obliged to provide the source code for proprietary components     !<<
17     >>!   outside of the FreeRTOS kernel.                                   !<<
18     ***************************************************************************
19
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following
23     link: http://www.freertos.org/a00114.html
24
25     ***************************************************************************
26      *                                                                       *
27      *    FreeRTOS provides completely free yet professionally developed,    *
28      *    robust, strictly quality controlled, supported, and cross          *
29      *    platform software that is more than just the market leader, it     *
30      *    is the industry's de facto standard.                               *
31      *                                                                       *
32      *    Help yourself get started quickly while simultaneously helping     *
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *
34      *    tutorial book, reference manual, or both:                          *
35      *    http://www.FreeRTOS.org/Documentation                              *
36      *                                                                       *
37     ***************************************************************************
38
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
40     the FAQ page "My application does not run, what could be wrong?".  Have you
41     defined configASSERT()?
42
43     http://www.FreeRTOS.org/support - In return for receiving this top quality
44     embedded software for free we request you assist our global community by
45     participating in the support forum.
46
47     http://www.FreeRTOS.org/training - Investing in training allows your team to
48     be as productive as possible as early as possible.  Now you can receive
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
50     Ltd, and the world's leading authority on the world's leading RTOS.
51
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.
55
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
58
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
61     licenses offer ticketed support, indemnification and commercial middleware.
62
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
64     engineered and independently SIL3 certified version for use in safety and
65     mission critical applications that require provable dependability.
66
67     1 tab == 4 spaces!
68 */
69
70 /*
71  * Creates eight tasks, each of which loops continuously performing a floating
72  * point calculation.
73  *
74  * All the tasks run at the idle priority and never block or yield.  This causes
75  * all eight tasks to time slice with the idle task.  Running at the idle
76  * priority means that these tasks will get pre-empted any time another task is
77  * ready to run or a time slice occurs.  More often than not the pre-emption
78  * will occur mid calculation, creating a good test of the schedulers context
79  * switch mechanism - a calculation producing an unexpected result could be a
80  * symptom of a corruption in the context of a task.
81  */
82
83 /* Standard includes. */
84 #include <stdlib.h>
85 #include <math.h>
86
87 /* Scheduler include files. */
88 #include "FreeRTOS.h"
89 #include "task.h"
90
91 /* Demo program include files. */
92 #include "flop.h"
93
94 #ifndef mathSTACK_SIZE
95         #define mathSTACK_SIZE          configMINIMAL_STACK_SIZE
96 #endif
97
98 #define mathNUMBER_OF_TASKS  ( 4 )
99
100 /* Four tasks, each of which performs a different floating point calculation.
101 Each of the four is created twice. */
102 static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
103 static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
104 static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
105 static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
106
107 /* These variables are used to check that all the tasks are still running.  If a
108 task gets a calculation wrong it will stop setting its check variable. */
109 static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
110
111 /*-----------------------------------------------------------*/
112
113 void vStartMathTasks( UBaseType_t uxPriority )
114 {
115         xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
116         xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
117         xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
118         xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
119 }
120 /*-----------------------------------------------------------*/
121
122 static portTASK_FUNCTION( vCompetingMathTask1, pvParameters )
123 {
124 volatile portDOUBLE d1, d2, d3, d4;
125 volatile uint16_t *pusTaskCheckVariable;
126 volatile portDOUBLE dAnswer;
127 short sError = pdFALSE;
128
129         /* Some ports require that tasks that use a hardware floating point unit
130         tell the kernel that they require a floating point context before any
131         floating point instructions are executed. */
132         portTASK_USES_FLOATING_POINT();
133
134         d1 = 123.4567;
135         d2 = 2345.6789;
136         d3 = -918.222;
137
138         dAnswer = ( d1 + d2 ) * d3;
139
140         /* The variable this task increments to show it is still running is passed in
141         as the parameter. */
142         pusTaskCheckVariable = ( uint16_t * ) pvParameters;
143
144         /* Keep performing a calculation and checking the result against a constant. */
145         for(;;)
146         {
147                 d1 = 123.4567;
148                 d2 = 2345.6789;
149                 d3 = -918.222;
150
151                 d4 = ( d1 + d2 ) * d3;
152
153                 #if configUSE_PREEMPTION == 0
154                         taskYIELD();
155                 #endif
156
157                 /* If the calculation does not match the expected constant, stop the
158                 increment of the check variable. */
159                 if( fabs( d4 - dAnswer ) > 0.001 )
160                 {
161                         sError = pdTRUE;
162                 }
163
164                 if( sError == pdFALSE )
165                 {
166                         /* If the calculation has always been correct then set set the check
167                         variable.  The check variable will get set to pdFALSE each time
168                         xAreMathsTaskStillRunning() is executed. */
169                         ( *pusTaskCheckVariable ) = pdTRUE;
170                 }
171
172                 #if configUSE_PREEMPTION == 0
173                         taskYIELD();
174                 #endif
175
176         }
177 }
178 /*-----------------------------------------------------------*/
179
180 static portTASK_FUNCTION( vCompetingMathTask2, pvParameters )
181 {
182 volatile portDOUBLE d1, d2, d3, d4;
183 volatile uint16_t *pusTaskCheckVariable;
184 volatile portDOUBLE dAnswer;
185 short sError = pdFALSE;
186
187         /* Some ports require that tasks that use a hardware floating point unit
188         tell the kernel that they require a floating point context before any
189         floating point instructions are executed. */
190         portTASK_USES_FLOATING_POINT();
191
192         d1 = -389.38;
193         d2 = 32498.2;
194         d3 = -2.0001;
195
196         dAnswer = ( d1 / d2 ) * d3;
197
198
199         /* The variable this task increments to show it is still running is passed in
200         as the parameter. */
201         pusTaskCheckVariable = ( uint16_t * ) pvParameters;
202
203         /* Keep performing a calculation and checking the result against a constant. */
204         for( ;; )
205         {
206                 d1 = -389.38;
207                 d2 = 32498.2;
208                 d3 = -2.0001;
209
210                 d4 = ( d1 / d2 ) * d3;
211
212                 #if configUSE_PREEMPTION == 0
213                         taskYIELD();
214                 #endif
215
216                 /* If the calculation does not match the expected constant, stop the
217                 increment of the check variable. */
218                 if( fabs( d4 - dAnswer ) > 0.001 )
219                 {
220                         sError = pdTRUE;
221                 }
222
223                 if( sError == pdFALSE )
224                 {
225                         /* If the calculation has always been correct then set set the check
226                         variable.  The check variable will get set to pdFALSE each time
227                         xAreMathsTaskStillRunning() is executed. */
228                         ( *pusTaskCheckVariable ) = pdTRUE;
229                 }
230
231                 #if configUSE_PREEMPTION == 0
232                         taskYIELD();
233                 #endif
234         }
235 }
236 /*-----------------------------------------------------------*/
237
238 static portTASK_FUNCTION( vCompetingMathTask3, pvParameters )
239 {
240 volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;
241 volatile uint16_t *pusTaskCheckVariable;
242 const size_t xArraySize = 10;
243 size_t xPosition;
244 short sError = pdFALSE;
245
246         /* Some ports require that tasks that use a hardware floating point unit
247         tell the kernel that they require a floating point context before any
248         floating point instructions are executed. */
249         portTASK_USES_FLOATING_POINT();
250
251         /* The variable this task increments to show it is still running is passed in
252         as the parameter. */
253         pusTaskCheckVariable = ( uint16_t * ) pvParameters;
254
255         pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
256
257         /* Keep filling an array, keeping a running total of the values placed in the
258         array.  Then run through the array adding up all the values.  If the two totals
259         do not match, stop the check variable from incrementing. */
260         for( ;; )
261         {
262                 dTotal1 = 0.0;
263                 dTotal2 = 0.0;
264
265                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )
266                 {
267                         pdArray[ xPosition ] = ( portDOUBLE ) xPosition + 5.5;
268                         dTotal1 += ( portDOUBLE ) xPosition + 5.5;
269                 }
270
271                 #if configUSE_PREEMPTION == 0
272                         taskYIELD();
273                 #endif
274
275                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )
276                 {
277                         dTotal2 += pdArray[ xPosition ];
278                 }
279
280                 dDifference = dTotal1 - dTotal2;
281                 if( fabs( dDifference ) > 0.001 )
282                 {
283                         sError = pdTRUE;
284                 }
285
286                 #if configUSE_PREEMPTION == 0
287                         taskYIELD();
288                 #endif
289
290                 if( sError == pdFALSE )
291                 {
292                         /* If the calculation has always been correct then set set the check
293                         variable.  The check variable will get set to pdFALSE each time
294                         xAreMathsTaskStillRunning() is executed. */
295                         ( *pusTaskCheckVariable ) = pdTRUE;
296                 }
297         }
298 }
299 /*-----------------------------------------------------------*/
300
301 static portTASK_FUNCTION( vCompetingMathTask4, pvParameters )
302 {
303 volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference;
304 volatile uint16_t *pusTaskCheckVariable;
305 const size_t xArraySize = 10;
306 size_t xPosition;
307 short sError = pdFALSE;
308
309         /* Some ports require that tasks that use a hardware floating point unit
310         tell the kernel that they require a floating point context before any
311         floating point instructions are executed. */
312         portTASK_USES_FLOATING_POINT();
313
314         /* The variable this task increments to show it is still running is passed in
315         as the parameter. */
316         pusTaskCheckVariable = ( uint16_t * ) pvParameters;
317
318         pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
319
320         /* Keep filling an array, keeping a running total of the values placed in the
321         array.  Then run through the array adding up all the values.  If the two totals
322         do not match, stop the check variable from incrementing. */
323         for( ;; )
324         {
325                 dTotal1 = 0.0;
326                 dTotal2 = 0.0;
327
328                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )
329                 {
330                         pdArray[ xPosition ] = ( portDOUBLE ) xPosition * 12.123;
331                         dTotal1 += ( portDOUBLE ) xPosition * 12.123;
332                 }
333
334                 #if configUSE_PREEMPTION == 0
335                         taskYIELD();
336                 #endif
337
338                 for( xPosition = 0; xPosition < xArraySize; xPosition++ )
339                 {
340                         dTotal2 += pdArray[ xPosition ];
341                 }
342
343                 dDifference = dTotal1 - dTotal2;
344                 if( fabs( dDifference ) > 0.001 )
345                 {
346                         sError = pdTRUE;
347                 }
348
349                 #if configUSE_PREEMPTION == 0
350                         taskYIELD();
351                 #endif
352
353                 if( sError == pdFALSE )
354                 {
355                         /* If the calculation has always been correct then set set the check
356                         variable.  The check variable will get set to pdFALSE each time
357                         xAreMathsTaskStillRunning() is executed. */
358                         ( *pusTaskCheckVariable ) = pdTRUE;
359                 }
360         }
361 }
362 /*-----------------------------------------------------------*/
363
364 /* This is called to check that all the created tasks are still running. */
365 BaseType_t xAreMathsTaskStillRunning( void )
366 {
367 BaseType_t xReturn = pdPASS, xTask;
368
369         /* Check the maths tasks are still running by ensuring their check variables
370         have been set to pdPASS. */
371         for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
372         {
373                 if( usTaskCheck[ xTask ] != pdTRUE )
374                 {
375                         /* The check has not been set so the associated task has either
376                         stalled or detected an error. */
377                         xReturn = pdFAIL;
378                 }
379                 else
380                 {
381                         /* Reset the variable so it can be checked again the next time this
382                         function is executed. */
383                         usTaskCheck[ xTask ] = pdFALSE;
384                 }
385         }
386
387         return xReturn;
388 }
389
390
391