]> begriffs open source - cmsis-freertos/blob - Demo/Common/Full/integer.c
Updated pack to FreeRTOS 10.4.4
[cmsis-freertos] / Demo / Common / Full / integer.c
1 /*
2  * FreeRTOS V202107.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  * Changes from V1.2.3
30  *
31  + The created tasks now include calls to tskYIELD(), allowing them to be used
32  +    with the cooperative scheduler.
33  */
34
35 /**
36  * This does the same as flop. c, but uses variables of type long instead of
37  * type double.
38  *
39  * As with flop. c, the tasks created in this file are a good test of the
40  * scheduler context switch mechanism.  The processor has to access 32bit
41  * variables in two or four chunks (depending on the processor).  The low
42  * priority of these tasks means there is a high probability that a context
43  * switch will occur mid calculation.  See the flop. c documentation for
44  * more information.
45  *
46  * \page IntegerC integer.c
47  * \ingroup DemoFiles
48  * <HR>
49  */
50
51 /*
52  * Changes from V1.2.1
53  *
54  + The constants used in the calculations are larger to ensure the
55  +    optimiser does not truncate them to 16 bits.
56  */
57
58 #include <stdlib.h>
59
60 /* Scheduler include files. */
61 #include "FreeRTOS.h"
62 #include "task.h"
63 #include "print.h"
64
65 /* Demo program include files. */
66 #include "integer.h"
67
68 #define intgSTACK_SIZE         ( ( unsigned short ) 256 )
69 #define intgNUMBER_OF_TASKS    ( 8 )
70
71 /* Four tasks, each of which performs a different calculation on four byte
72  * variables.  Each of the four is created twice. */
73 static void vCompeteingIntMathTask1( void * pvParameters );
74 static void vCompeteingIntMathTask2( void * pvParameters );
75 static void vCompeteingIntMathTask3( void * pvParameters );
76 static void vCompeteingIntMathTask4( void * pvParameters );
77
78 /* These variables are used to check that all the tasks are still running.  If a
79 * task gets a calculation wrong it will stop incrementing its check variable. */
80 static volatile unsigned short usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
81 /*-----------------------------------------------------------*/
82
83 void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority )
84 {
85     xTaskCreate( vCompeteingIntMathTask1, "IntMath1", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL );
86     xTaskCreate( vCompeteingIntMathTask2, "IntMath2", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL );
87     xTaskCreate( vCompeteingIntMathTask3, "IntMath3", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL );
88     xTaskCreate( vCompeteingIntMathTask4, "IntMath4", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL );
89     xTaskCreate( vCompeteingIntMathTask1, "IntMath5", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL );
90     xTaskCreate( vCompeteingIntMathTask2, "IntMath6", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL );
91     xTaskCreate( vCompeteingIntMathTask3, "IntMath7", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL );
92     xTaskCreate( vCompeteingIntMathTask4, "IntMath8", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL );
93 }
94 /*-----------------------------------------------------------*/
95
96 static void vCompeteingIntMathTask1( void * pvParameters )
97 {
98     long l1, l2, l3, l4;
99     short sError = pdFALSE;
100     volatile unsigned short * pusTaskCheckVariable;
101     const long lAnswer = ( ( long ) 74565L + ( long ) 1234567L ) * ( long ) -918L;
102     const char * const pcTaskStartMsg = "Integer math task 1 started.\r\n";
103     const char * const pcTaskFailMsg = "Integer math task 1 failed.\r\n";
104
105     /* Queue a message for printing to say the task has started. */
106     vPrintDisplayMessage( &pcTaskStartMsg );
107
108     /* The variable this task increments to show it is still running is passed in
109      * as the parameter. */
110     pusTaskCheckVariable = ( unsigned short * ) pvParameters;
111
112     /* Keep performing a calculation and checking the result against a constant. */
113     for( ; ; )
114     {
115         l1 = ( long ) 74565L;
116         l2 = ( long ) 1234567L;
117         l3 = ( long ) -918L;
118
119         l4 = ( l1 + l2 ) * l3;
120
121         taskYIELD();
122
123         /* If the calculation does not match the expected constant, stop the
124          * increment of the check variable. */
125         if( l4 != lAnswer )
126         {
127             vPrintDisplayMessage( &pcTaskFailMsg );
128             sError = pdTRUE;
129         }
130
131         if( sError == pdFALSE )
132         {
133             /* If the calculation has always been correct, increment the check
134              * variable so we know      this task is still running okay. */
135             ( *pusTaskCheckVariable )++;
136         }
137     }
138 }
139 /*-----------------------------------------------------------*/
140
141 static void vCompeteingIntMathTask2( void * pvParameters )
142 {
143     long l1, l2, l3, l4;
144     short sError = pdFALSE;
145     volatile unsigned short * pusTaskCheckVariable;
146     const long lAnswer = ( ( long ) -389000L / ( long ) 329999L ) * ( long ) -89L;
147     const char * const pcTaskStartMsg = "Integer math task 2 started.\r\n";
148     const char * const pcTaskFailMsg = "Integer math task 2 failed.\r\n";
149
150     /* Queue a message for printing to say the task has started. */
151     vPrintDisplayMessage( &pcTaskStartMsg );
152
153     /* The variable this task increments to show it is still running is passed in
154      * as the parameter. */
155     pusTaskCheckVariable = ( unsigned short * ) pvParameters;
156
157     /* Keep performing a calculation and checking the result against a constant. */
158     for( ; ; )
159     {
160         l1 = -389000L;
161         l2 = 329999L;
162         l3 = -89L;
163
164         l4 = ( l1 / l2 ) * l3;
165
166         taskYIELD();
167
168         /* If the calculation does not match the expected constant, stop the
169          * increment of the check variable. */
170         if( l4 != lAnswer )
171         {
172             vPrintDisplayMessage( &pcTaskFailMsg );
173             sError = pdTRUE;
174         }
175
176         if( sError == pdFALSE )
177         {
178             /* If the calculation has always been correct, increment the check
179              * variable so we know this task is still running okay. */
180             ( *pusTaskCheckVariable )++;
181         }
182     }
183 }
184 /*-----------------------------------------------------------*/
185
186 static void vCompeteingIntMathTask3( void * pvParameters )
187 {
188     long * plArray, lTotal1, lTotal2;
189     short sError = pdFALSE;
190     volatile unsigned short * pusTaskCheckVariable;
191     const unsigned short usArraySize = ( unsigned short ) 250;
192     unsigned short usPosition;
193     const char * const pcTaskStartMsg = "Integer math task 3 started.\r\n";
194     const char * const pcTaskFailMsg = "Integer math task 3 failed.\r\n";
195
196     /* Queue a message for printing to say the task has started. */
197     vPrintDisplayMessage( &pcTaskStartMsg );
198
199     /* The variable this task increments to show it is still running is passed in
200      * as the parameter. */
201     pusTaskCheckVariable = ( unsigned short * ) pvParameters;
202
203     /* Create the array we are going to use for our check calculation. */
204     plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
205
206     /* Keep filling the array, keeping a running total of the values placed in the
207      * array.  Then run through the array adding up all the values.  If the two totals
208      * do not match, stop the check variable from incrementing. */
209     for( ; ; )
210     {
211         lTotal1 = ( long ) 0;
212         lTotal2 = ( long ) 0;
213
214         for( usPosition = 0; usPosition < usArraySize; usPosition++ )
215         {
216             plArray[ usPosition ] = ( long ) usPosition + ( long ) 5;
217             lTotal1 += ( long ) usPosition + ( long ) 5;
218         }
219
220         taskYIELD();
221
222         for( usPosition = 0; usPosition < usArraySize; usPosition++ )
223         {
224             lTotal2 += plArray[ usPosition ];
225         }
226
227         if( lTotal1 != lTotal2 )
228         {
229             vPrintDisplayMessage( &pcTaskFailMsg );
230             sError = pdTRUE;
231         }
232
233         taskYIELD();
234
235         if( sError == pdFALSE )
236         {
237             /* If the calculation has always been correct, increment the check
238              * variable so we know      this task is still running okay. */
239             ( *pusTaskCheckVariable )++;
240         }
241     }
242 }
243 /*-----------------------------------------------------------*/
244
245 static void vCompeteingIntMathTask4( void * pvParameters )
246 {
247     long * plArray, lTotal1, lTotal2;
248     short sError = pdFALSE;
249     volatile unsigned short * pusTaskCheckVariable;
250     const unsigned short usArraySize = 250;
251     unsigned short usPosition;
252     const char * const pcTaskStartMsg = "Integer math task 4 started.\r\n";
253     const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
254
255     /* Queue a message for printing to say the task has started. */
256     vPrintDisplayMessage( &pcTaskStartMsg );
257
258     /* The variable this task increments to show it is still running is passed in
259      * as the parameter. */
260     pusTaskCheckVariable = ( unsigned short * ) pvParameters;
261
262     /* Create the array we are going to use for our check calculation. */
263     plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
264
265     /* Keep filling the array, keeping a running total of the values placed in the
266      * array.  Then run through the array adding up all the values.  If the two totals
267      * do not match, stop the check variable from incrementing. */
268     for( ; ; )
269     {
270         lTotal1 = ( long ) 0;
271         lTotal2 = ( long ) 0;
272
273         for( usPosition = 0; usPosition < usArraySize; usPosition++ )
274         {
275             plArray[ usPosition ] = ( long ) usPosition * ( long ) 12;
276             lTotal1 += ( long ) usPosition * ( long ) 12;
277         }
278
279         taskYIELD();
280
281         for( usPosition = 0; usPosition < usArraySize; usPosition++ )
282         {
283             lTotal2 += plArray[ usPosition ];
284         }
285
286         if( lTotal1 != lTotal2 )
287         {
288             vPrintDisplayMessage( &pcTaskFailMsg );
289             sError = pdTRUE;
290         }
291
292         taskYIELD();
293
294         if( sError == pdFALSE )
295         {
296             /* If the calculation has always been correct, increment the check
297              * variable so we know      this task is still running okay. */
298             ( *pusTaskCheckVariable )++;
299         }
300     }
301 }
302 /*-----------------------------------------------------------*/
303
304 /* This is called to check that all the created tasks are still running. */
305 portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )
306 {
307 /* Keep a history of the check variables so we know if they have been incremented
308  * since the last call. */
309     static unsigned short usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
310     portBASE_TYPE xReturn = pdTRUE, xTask;
311
312     /* Check the maths tasks are still running by ensuring their check variables
313      * are still incrementing. */
314     for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ )
315     {
316         if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
317         {
318             /* The check has not incremented so an error exists. */
319             xReturn = pdFALSE;
320         }
321
322         usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ];
323     }
324
325     return xReturn;
326 }