]> begriffs open source - cmsis-freertos/blob - Demo/Common/Minimal/flop.c
Update README.md - branch main is now the base branch
[cmsis-freertos] / Demo / Common / Minimal / flop.c
1 /*
2  * FreeRTOS V202111.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /*
29  * Creates eight tasks, each of which loops continuously performing a floating
30  * point calculation.
31  *
32  * All the tasks run at the idle priority and never block or yield.  This causes
33  * all eight tasks to time slice with the idle task.  Running at the idle
34  * priority means that these tasks will get pre-empted any time another task is
35  * ready to run or a time slice occurs.  More often than not the pre-emption
36  * will occur mid calculation, creating a good test of the schedulers context
37  * switch mechanism - a calculation producing an unexpected result could be a
38  * symptom of a corruption in the context of a task.
39  */
40
41 /* Standard includes. */
42 #include <stdlib.h>
43 #include <math.h>
44
45 /* Scheduler include files. */
46 #include "FreeRTOS.h"
47 #include "task.h"
48
49 /* Demo program include files. */
50 #include "flop.h"
51
52 #ifndef mathSTACK_SIZE
53     #define mathSTACK_SIZE     configMINIMAL_STACK_SIZE
54 #endif
55
56 #define mathNUMBER_OF_TASKS    ( 4 )
57
58 /* Four tasks, each of which performs a different floating point calculation.
59  * Each of the four is created twice. */
60 static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
61 static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
62 static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
63 static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
64
65 /* These variables are used to check that all the tasks are still running.  If a
66  * task gets a calculation wrong it will stop setting its check variable. */
67 static uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
68
69 /*-----------------------------------------------------------*/
70
71 void vStartMathTasks( UBaseType_t uxPriority )
72 {
73     xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
74     xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
75     xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
76     xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
77 }
78 /*-----------------------------------------------------------*/
79
80 static portTASK_FUNCTION( vCompetingMathTask1, pvParameters )
81 {
82     volatile portDOUBLE d1, d2, d3, d4;
83     volatile uint16_t * pusTaskCheckVariable;
84     volatile portDOUBLE dAnswer;
85     short sError = pdFALSE;
86
87     /* Some ports require that tasks that use a hardware floating point unit
88      * tell the kernel that they require a floating point context before any
89      * floating point instructions are executed. */
90     portTASK_USES_FLOATING_POINT();
91
92     d1 = 123.4567;
93     d2 = 2345.6789;
94     d3 = -918.222;
95
96     dAnswer = ( d1 + d2 ) * d3;
97
98     /* The variable this task increments to show it is still running is passed in
99      * as the parameter. */
100     pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
101
102     /* Keep performing a calculation and checking the result against a constant. */
103     for( ; ; )
104     {
105         d1 = 123.4567;
106         d2 = 2345.6789;
107         d3 = -918.222;
108
109         d4 = ( d1 + d2 ) * d3;
110
111         #if configUSE_PREEMPTION == 0
112             taskYIELD();
113         #endif
114
115         /* If the calculation does not match the expected constant, stop the
116          * increment of the check variable. */
117         if( fabs( d4 - dAnswer ) > 0.001 )
118         {
119             sError = pdTRUE;
120         }
121
122         if( sError == pdFALSE )
123         {
124             /* If the calculation has always been correct then set set the check
125              * variable.  The check variable will get set to pdFALSE each time
126              * xAreMathsTaskStillRunning() is executed. */
127             ( *pusTaskCheckVariable ) = pdTRUE;
128         }
129
130         #if configUSE_PREEMPTION == 0
131             taskYIELD();
132         #endif
133     }
134 }
135 /*-----------------------------------------------------------*/
136
137 static portTASK_FUNCTION( vCompetingMathTask2, pvParameters )
138 {
139     volatile portDOUBLE d1, d2, d3, d4;
140     volatile uint16_t * pusTaskCheckVariable;
141     volatile portDOUBLE dAnswer;
142     short sError = pdFALSE;
143
144     /* Some ports require that tasks that use a hardware floating point unit
145      * tell the kernel that they require a floating point context before any
146      * floating point instructions are executed. */
147     portTASK_USES_FLOATING_POINT();
148
149     d1 = -389.38;
150     d2 = 32498.2;
151     d3 = -2.0001;
152
153     dAnswer = ( d1 / d2 ) * d3;
154
155
156     /* The variable this task increments to show it is still running is passed in
157      * as the parameter. */
158     pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
159
160     /* Keep performing a calculation and checking the result against a constant. */
161     for( ; ; )
162     {
163         d1 = -389.38;
164         d2 = 32498.2;
165         d3 = -2.0001;
166
167         d4 = ( d1 / d2 ) * d3;
168
169         #if configUSE_PREEMPTION == 0
170             taskYIELD();
171         #endif
172
173         /* If the calculation does not match the expected constant, stop the
174          * increment of the check variable. */
175         if( fabs( d4 - dAnswer ) > 0.001 )
176         {
177             sError = pdTRUE;
178         }
179
180         if( sError == pdFALSE )
181         {
182             /* If the calculation has always been correct then set set the check
183              * variable.  The check variable will get set to pdFALSE each time
184              * xAreMathsTaskStillRunning() is executed. */
185             ( *pusTaskCheckVariable ) = pdTRUE;
186         }
187
188         #if configUSE_PREEMPTION == 0
189             taskYIELD();
190         #endif
191     }
192 }
193 /*-----------------------------------------------------------*/
194
195 static portTASK_FUNCTION( vCompetingMathTask3, pvParameters )
196 {
197     volatile portDOUBLE * pdArray, dTotal1, dTotal2, dDifference;
198     volatile uint16_t * pusTaskCheckVariable;
199     const size_t xArraySize = 10;
200     size_t xPosition;
201     short sError = pdFALSE;
202
203     /* Some ports require that tasks that use a hardware floating point unit
204      * tell the kernel that they require a floating point context before any
205      * floating point instructions are executed. */
206     portTASK_USES_FLOATING_POINT();
207
208     /* The variable this task increments to show it is still running is passed in
209      * as the parameter. */
210     pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
211
212     pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
213
214     /* Keep filling an array, keeping a running total of the values placed in the
215      * array.  Then run through the array adding up all the values.  If the two totals
216      * do not match, stop the check variable from incrementing. */
217     for( ; ; )
218     {
219         dTotal1 = 0.0;
220         dTotal2 = 0.0;
221
222         for( xPosition = 0; xPosition < xArraySize; xPosition++ )
223         {
224             pdArray[ xPosition ] = ( portDOUBLE ) xPosition + 5.5;
225             dTotal1 += ( portDOUBLE ) xPosition + 5.5;
226         }
227
228         #if configUSE_PREEMPTION == 0
229             taskYIELD();
230         #endif
231
232         for( xPosition = 0; xPosition < xArraySize; xPosition++ )
233         {
234             dTotal2 += pdArray[ xPosition ];
235         }
236
237         dDifference = dTotal1 - dTotal2;
238
239         if( fabs( dDifference ) > 0.001 )
240         {
241             sError = pdTRUE;
242         }
243
244         #if configUSE_PREEMPTION == 0
245             taskYIELD();
246         #endif
247
248         if( sError == pdFALSE )
249         {
250             /* If the calculation has always been correct then set set the check
251              * variable.  The check variable will get set to pdFALSE each time
252              * xAreMathsTaskStillRunning() is executed. */
253             ( *pusTaskCheckVariable ) = pdTRUE;
254         }
255     }
256 }
257 /*-----------------------------------------------------------*/
258
259 static portTASK_FUNCTION( vCompetingMathTask4, pvParameters )
260 {
261     volatile portDOUBLE * pdArray, dTotal1, dTotal2, dDifference;
262     volatile uint16_t * pusTaskCheckVariable;
263     const size_t xArraySize = 10;
264     size_t xPosition;
265     short sError = pdFALSE;
266
267     /* Some ports require that tasks that use a hardware floating point unit
268      * tell the kernel that they require a floating point context before any
269      * floating point instructions are executed. */
270     portTASK_USES_FLOATING_POINT();
271
272     /* The variable this task increments to show it is still running is passed in
273      * as the parameter. */
274     pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
275
276     pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
277
278     /* Keep filling an array, keeping a running total of the values placed in the
279      * array.  Then run through the array adding up all the values.  If the two totals
280      * do not match, stop the check variable from incrementing. */
281     for( ; ; )
282     {
283         dTotal1 = 0.0;
284         dTotal2 = 0.0;
285
286         for( xPosition = 0; xPosition < xArraySize; xPosition++ )
287         {
288             pdArray[ xPosition ] = ( portDOUBLE ) xPosition * 12.123;
289             dTotal1 += ( portDOUBLE ) xPosition * 12.123;
290         }
291
292         #if configUSE_PREEMPTION == 0
293             taskYIELD();
294         #endif
295
296         for( xPosition = 0; xPosition < xArraySize; xPosition++ )
297         {
298             dTotal2 += pdArray[ xPosition ];
299         }
300
301         dDifference = dTotal1 - dTotal2;
302
303         if( fabs( dDifference ) > 0.001 )
304         {
305             sError = pdTRUE;
306         }
307
308         #if configUSE_PREEMPTION == 0
309             taskYIELD();
310         #endif
311
312         if( sError == pdFALSE )
313         {
314             /* If the calculation has always been correct then set set the check
315              * variable.  The check variable will get set to pdFALSE each time
316              * xAreMathsTaskStillRunning() is executed. */
317             ( *pusTaskCheckVariable ) = pdTRUE;
318         }
319     }
320 }
321 /*-----------------------------------------------------------*/
322
323 /* This is called to check that all the created tasks are still running. */
324 BaseType_t xAreMathsTaskStillRunning( void )
325 {
326     BaseType_t xReturn = pdPASS, xTask;
327
328     /* Check the maths tasks are still running by ensuring their check variables
329      * have been set to pdPASS. */
330     for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
331     {
332         if( usTaskCheck[ xTask ] != pdTRUE )
333         {
334             /* The check has not been set so the associated task has either
335              * stalled or detected an error. */
336             xReturn = pdFAIL;
337         }
338         else
339         {
340             /* Reset the variable so it can be checked again the next time this
341              * function is executed. */
342             usTaskCheck[ xTask ] = pdFALSE;
343         }
344     }
345
346     return xReturn;
347 }