]> begriffs open source - cmsis-freertos/blob - Demo/WIN32-MingW/code_coverage_additions.c
Updated pack to FreeRTOS 10.4.6
[cmsis-freertos] / Demo / WIN32-MingW / code_coverage_additions.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  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26
27 /*
28  * Contains sundry tests to exercise code that is not touched by the standard
29  * demo tasks (which are predominantly test tasks).  Some tests are included
30  * here because they can only be executed when configASSERT() is not defined.
31  */
32
33 #include "FreeRTOS.h"
34 #include "task.h"
35 #include "timers.h"
36 #include "event_groups.h"
37 #include "semphr.h"
38 #include "stream_buffer.h"
39 #include "message_buffer.h"
40
41 /*-----------------------------------------------------------*/
42
43 /*
44  * Try creating static objects with one of the mandatory parameters set to NULL.
45  * This can't be done in the standard demos as asserts() will get hit.
46  */
47 static BaseType_t prvStaticAllocationsWithNullBuffers( void );
48
49 /*
50  * Code coverage analysis is performed with tracing turned off, so this
51  * function executes the trace specific utility functions that would not
52  * otherwise be executed..
53  */
54 static BaseType_t prvTraceUtils( void );
55
56 /*
57  * The queue peek standard demo does not cover the case where an attempt to peek
58  * times out, so test that case.
59  */
60 static BaseType_t prvPeekTimeout( void );
61
62 /*
63  * Calls various interrupt safe functions designed to query the state of a
64  * queue.
65  */
66 static BaseType_t prvQueueQueryFromISR( void );
67
68 /*
69  * Hits a few paths in tasks state and status query functions not otherwise hit
70  * by standard demo and test files.
71  */
72 static BaseType_t prvTaskQueryFunctions( void );
73
74 /*
75  * None of the standard demo tasks use the task tags - exercise them here.
76  */
77 static BaseType_t prvTaskTags( void );
78
79 /*
80  * Exercises a few of the query functions that are not otherwise exercised in
81  * the standard demo and test functions.
82  */
83 static BaseType_t prvTimerQuery( void );
84
85 /*-----------------------------------------------------------*/
86
87 static BaseType_t prvStaticAllocationsWithNullBuffers( void )
88 {
89 uint32_t ulReturned = 0;
90 BaseType_t xReturn = pdPASS;
91 UBaseType_t uxDummy = 10;
92
93         /* Don't expect to create any of the objects as a NULL parameter is always
94         passed in place of a required buffer.  Hence if all passes then none of the
95         |= will be against 0, and ulReturned will still be zero at the end of this
96         function. */
97         ulReturned |= ( uint32_t ) xEventGroupCreateStatic( NULL );
98
99         /* Try creating a task twice, once with puxStackBuffer NULL, and once with
100         pxTaskBuffer NULL. */
101         ulReturned |= ( uint32_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
102                                                                                                   "Dummy", /* Task name. */
103                                                                                                   configMINIMAL_STACK_SIZE,
104                                                                                                   NULL,
105                                                                                                   tskIDLE_PRIORITY,
106                                                                                                   NULL,
107                                                                                                   ( StaticTask_t * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
108
109         ulReturned |= ( uint32_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
110                                                                                                   "Dummy", /* Task name. */
111                                                                                                   configMINIMAL_STACK_SIZE,
112                                                                                                   NULL,
113                                                                                                   tskIDLE_PRIORITY,
114                                                                                                   ( StackType_t  * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
115                                                                                                   NULL );
116
117         ulReturned |= ( uint32_t ) xQueueCreateStatic( uxDummy,
118                                                                                                    uxDummy,
119                                                                                                    ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
120                                                                                                    NULL );
121
122         /* Try creating a stream buffer twice, once with pucStreamBufferStorageArea
123         set to NULL, and once with pxStaticStreamBuffer set to NULL. */
124         ulReturned |= ( uint32_t ) xStreamBufferCreateStatic( uxDummy,
125                                                                                                                   uxDummy,
126                                                                                                                   NULL,
127                                                                                                                   ( StaticStreamBuffer_t  * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
128
129         ulReturned |= ( uint32_t ) xStreamBufferCreateStatic( uxDummy,
130                                                                                                                   uxDummy,
131                                                                                                                   ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
132                                                                                                                   NULL );
133
134         /* Try to create a task with a stack that is too large to be allocated. */
135         if( xTaskCreate( NULL, "TooLarge", configTOTAL_HEAP_SIZE, NULL, tskIDLE_PRIORITY, NULL ) != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY )
136         {
137                 xReturn = pdFAIL;
138         }
139
140         if( ulReturned != 0 )
141         {
142                 /* Something returned a non-NULL value. */
143                 xReturn = pdFAIL;
144         }
145
146         return xReturn;
147 }
148 /*-----------------------------------------------------------*/
149
150 static BaseType_t prvTraceUtils( void )
151 {
152 EventGroupHandle_t xEventGroup;
153 QueueHandle_t xQueue;
154 BaseType_t xReturn = pdPASS;
155 const UBaseType_t xNumber = ( UBaseType_t ) 100, xQueueLength = ( UBaseType_t ) 1;
156 UBaseType_t uxValue;
157 TaskHandle_t xTaskHandle;
158 StreamBufferHandle_t xStreamBuffer;
159 MessageBufferHandle_t xMessageBuffer;
160
161         /* Exercise the event group trace utilities. */
162         xEventGroup = xEventGroupCreate();
163
164         if( xEventGroup != NULL )
165         {
166                 vEventGroupSetNumber( xEventGroup, xNumber );
167                 if( uxEventGroupGetNumber( NULL ) != 0 )
168                 {
169                         xReturn = pdFAIL;
170                 }
171                 if( uxEventGroupGetNumber( xEventGroup ) != xNumber )
172                 {
173                         xReturn = pdFAIL;
174                 }
175
176                 vEventGroupDelete( xEventGroup );
177         }
178         else
179         {
180                 xReturn = pdFAIL;
181         }
182
183         /* Exercise the queue trace utilities. */
184         xQueue = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( uxValue ) );
185         if( xQueue != NULL )
186         {
187                 vQueueSetQueueNumber( xQueue, xNumber );
188                 if( uxQueueGetQueueNumber( xQueue ) != xNumber )
189                 {
190                         xReturn = pdFAIL;
191                 }
192                 if( ucQueueGetQueueType( xQueue ) != queueQUEUE_TYPE_BASE )
193                 {
194                         xReturn = pdFAIL;
195                 }
196
197                 vQueueDelete( xQueue );
198         }
199         else
200         {
201                 xReturn = pdFAIL;
202         }
203
204         /* Exercise the task trace utilities.  Value of 100 is arbitrary, just want
205         to check the value that is set is also read back. */
206         uxValue = 100;
207         xTaskHandle = xTaskGetCurrentTaskHandle();
208         vTaskSetTaskNumber( xTaskHandle, uxValue );
209         if( uxTaskGetTaskNumber( xTaskHandle ) != uxValue )
210         {
211                 xReturn = pdFAIL;
212         }
213         if( uxTaskGetTaskNumber( NULL ) != 0 )
214         {
215                 xReturn = pdFAIL;
216         }
217
218         /* Timer trace util functions are exercised in prvTimerQuery(). */
219
220
221         /* Exercise the stream buffer utilities.  Try creating with a trigger level
222         of 0, it should then get capped to 1. */
223         xStreamBuffer = xStreamBufferCreate( sizeof( uint32_t ), 0 );
224         if( xStreamBuffer != NULL )
225         {
226                 vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxValue );
227                 if( uxStreamBufferGetStreamBufferNumber( xStreamBuffer ) != uxValue )
228                 {
229                         xReturn = pdFALSE;
230                 }
231                 if( ucStreamBufferGetStreamBufferType( xStreamBuffer ) != 0 )
232                 {
233                         /* "Is Message Buffer" flag should have been 0. */
234                         xReturn = pdFALSE;
235                 }
236
237                 vStreamBufferDelete( xStreamBuffer );
238         }
239         else
240         {
241                 xReturn = pdFALSE;
242         }
243
244         xMessageBuffer = xMessageBufferCreate( sizeof( uint32_t ) );
245         if( xMessageBuffer != NULL )
246         {
247                 if( ucStreamBufferGetStreamBufferType( xMessageBuffer ) == 0 )
248                 {
249                         /* "Is Message Buffer" flag should have been 1. */
250                         xReturn = pdFALSE;
251                 }
252
253                 vMessageBufferDelete( xMessageBuffer );
254         }
255         else
256         {
257                 xReturn = pdFALSE;
258         }
259
260         return xReturn;
261 }
262 /*-----------------------------------------------------------*/
263
264 static BaseType_t prvPeekTimeout( void )
265 {
266 QueueHandle_t xHandle;
267 const UBaseType_t xQueueLength = 1;
268 BaseType_t xReturn = pdPASS;
269 TickType_t xBlockTime = ( TickType_t ) 2;
270 UBaseType_t uxReceived;
271
272         /* Create the queue just to try peeking it while it is empty. */
273         xHandle = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( xQueueLength ) );
274
275         if( xHandle != NULL )
276         {
277                 if( uxQueueMessagesWaiting( xHandle ) != 0 )
278                 {
279                         xReturn = pdFAIL;
280                 }
281
282                 /* Ensure peeking from the queue times out as the queue is empty. */
283                 if( xQueuePeek( xHandle, &uxReceived, xBlockTime ) != pdFALSE )
284                 {
285                         xReturn = pdFAIL;
286                 }
287
288                 vQueueDelete( xHandle );
289         }
290         else
291         {
292                 xReturn = pdFAIL;
293         }
294
295         return xReturn;
296 }
297 /*-----------------------------------------------------------*/
298
299 static BaseType_t prvQueueQueryFromISR( void )
300 {
301 BaseType_t xReturn = pdPASS, xValue = 1;
302 const UBaseType_t xISRQueueLength = ( UBaseType_t ) 1;
303 const char *pcISRQueueName = "ISRQueue";
304 QueueHandle_t xISRQueue = NULL;
305
306         xISRQueue = xQueueCreate( xISRQueueLength, ( UBaseType_t ) sizeof( BaseType_t ) );
307
308         if( xISRQueue != NULL )
309         {
310                 vQueueAddToRegistry( xISRQueue, pcISRQueueName );
311                 if( strcmp( pcQueueGetName( xISRQueue ), pcISRQueueName ) )
312                 {
313                         xReturn = pdFAIL;
314                 }
315
316                 /* Expect the queue to be empty here. */
317                 if(     uxQueueMessagesWaitingFromISR( xISRQueue ) != 0 )
318                 {
319                         xReturn = pdFAIL;
320                 }
321
322                 if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdTRUE )
323                 {
324                         xReturn = pdFAIL;
325                 }
326
327                 if( xQueueIsQueueFullFromISR( xISRQueue ) != pdFALSE )
328                 {
329                         xReturn = pdFAIL;
330                 }
331
332                 /* Now fill the queue - it only has one space. */
333                 if( xQueueSendFromISR( xISRQueue, &xValue, NULL ) != pdPASS )
334                 {
335                         xReturn = pdFAIL;
336                 }
337
338                 /* Check it now reports as full. */
339                 if(     uxQueueMessagesWaitingFromISR( xISRQueue ) != 1 )
340                 {
341                         xReturn = pdFAIL;
342                 }
343
344                 if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdFALSE )
345                 {
346                         xReturn = pdFAIL;
347                 }
348
349                 if( xQueueIsQueueFullFromISR( xISRQueue ) != pdTRUE )
350                 {
351                         xReturn = pdFAIL;
352                 }
353
354                 vQueueDelete( xISRQueue );
355         }
356         else
357         {
358                 xReturn = pdFAIL;
359         }
360
361         return xReturn;
362 }
363 /*-----------------------------------------------------------*/
364
365 static BaseType_t prvTaskQueryFunctions( void )
366 {
367 static TaskStatus_t xStatus, *pxStatusArray;
368 TaskHandle_t xTimerTask, xIdleTask;
369 BaseType_t xReturn = pdPASS;
370 UBaseType_t uxNumberOfTasks, uxReturned, ux;
371 uint32_t ulTotalRunTime1, ulTotalRunTime2;
372 const uint32_t ulRunTimeTollerance = ( uint32_t ) 0xfff;
373
374         /* Obtain task status with the stack high water mark and without the
375         state. */
376         vTaskGetInfo( NULL, &xStatus, pdTRUE, eRunning );
377
378         if( uxTaskGetStackHighWaterMark( NULL ) != xStatus.usStackHighWaterMark )
379         {
380                 xReturn = pdFAIL;
381         }
382
383         if( uxTaskGetStackHighWaterMark2( NULL ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
384         {
385                 xReturn = pdFAIL;
386         }
387
388         /* Now obtain a task status without the high water mark but with the state,
389         which in the case of the idle task should be Read. */
390         xTimerTask = xTimerGetTimerDaemonTaskHandle();
391         vTaskSuspend( xTimerTask ); /* Should never suspend Timer task normally!. */
392         vTaskGetInfo( xTimerTask, &xStatus, pdFALSE, eInvalid );
393         if( xStatus.eCurrentState != eSuspended )
394         {
395                 xReturn = pdFAIL;
396         }
397         if( xStatus.uxBasePriority != uxTaskPriorityGetFromISR( xTimerTask ) )
398         {
399                 xReturn = pdFAIL;
400         }
401         if( xStatus.uxBasePriority != ( configMAX_PRIORITIES - 1 ) )
402         {
403                 xReturn = pdFAIL;
404         }
405         xTaskResumeFromISR( xTimerTask );
406         vTaskGetInfo( xTimerTask, &xStatus, pdTRUE, eInvalid );
407         if( ( xStatus.eCurrentState != eReady ) && ( xStatus.eCurrentState != eBlocked ) )
408         {
409                 xReturn = pdFAIL;
410         }
411         if( uxTaskGetStackHighWaterMark( xTimerTask ) != xStatus.usStackHighWaterMark )
412         {
413                 xReturn = pdFAIL;
414         }
415         if( uxTaskGetStackHighWaterMark2( xTimerTask ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
416         {
417                 xReturn = pdFAIL;
418         }
419
420         /* Attempting to abort a delay in the idle task should be guaranteed to
421         fail as the idle task should never block. */
422         xIdleTask = xTaskGetIdleTaskHandle();
423         if( xTaskAbortDelay( xIdleTask ) != pdFAIL )
424         {
425                 xReturn = pdFAIL;
426         }
427
428         /* Create an array of task status objects large enough to hold information
429         on the number of tasks at this time - note this may change at any time if
430         higher priority tasks are executing and creating tasks. */
431         uxNumberOfTasks = uxTaskGetNumberOfTasks();
432         pxStatusArray = ( TaskStatus_t * ) pvPortMalloc( uxNumberOfTasks * sizeof( TaskStatus_t ) );
433
434         if( pxStatusArray != NULL )
435         {
436                 /* Pass part of the array into uxTaskGetSystemState() to ensure it doesn't
437                 try using more space than there is available. */
438                 uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks / ( UBaseType_t ) 2, NULL );
439                 if( uxReturned != ( UBaseType_t ) 0 )
440                 {
441                         xReturn = pdFAIL;
442                 }
443
444                 /* Now do the same but passing in the complete array size, this is done
445                 twice to check for a difference in the total run time. */
446                 uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime1 );
447                 memset( ( void * ) pxStatusArray, 0xaa, uxNumberOfTasks * sizeof( TaskStatus_t ) );
448                 uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime2 );
449                 if( ( ulTotalRunTime2 - ulTotalRunTime1 ) > ulRunTimeTollerance )
450                 {
451                         xReturn = pdFAIL;
452                 }
453
454                 /* Basic santity check of array contents. */
455                 for( ux = 0; ux < uxReturned; ux++ )
456                 {
457                         if( pxStatusArray[ ux ].eCurrentState >= ( UBaseType_t ) eInvalid )
458                         {
459                                 xReturn = pdFAIL;
460                         }
461                         if( pxStatusArray[ ux ].uxCurrentPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
462                         {
463                                 xReturn = pdFAIL;
464                         }
465                 }
466
467                 vPortFree( pxStatusArray );
468         }
469         else
470         {
471                 xReturn = pdFAIL;
472         }
473
474         return xReturn;
475 }
476 /*-----------------------------------------------------------*/
477
478 static BaseType_t prvDummyTagFunction( void *pvParameter )
479 {
480         return ( BaseType_t ) pvParameter;
481 }
482 /*-----------------------------------------------------------*/
483
484 static BaseType_t prvTaskTags( void )
485 {
486 BaseType_t xReturn = pdPASS, xParameter = ( BaseType_t ) 0xDEADBEEF;
487 TaskHandle_t xTask;
488
489         /* First try with the handle of a different task.  Use the timer task for
490         convenience. */
491         xTask = xTimerGetTimerDaemonTaskHandle();
492
493         vTaskSetApplicationTaskTag( xTask, prvDummyTagFunction );
494         if( xTaskGetApplicationTaskTag( xTask ) != prvDummyTagFunction )
495         {
496                 xReturn = pdFAIL;
497         }
498         else
499         {
500                 if( xTaskCallApplicationTaskHook( xTask, ( void * ) xParameter ) != xParameter )
501                 {
502                         xReturn = pdFAIL;
503                 }
504                 if( xTaskCallApplicationTaskHook( xTask, ( void * ) NULL ) != pdFAIL )
505                 {
506                         xReturn = pdFAIL;
507                 }
508         }
509
510         /* Try FromISR version too. */
511         if( xTaskGetApplicationTaskTagFromISR( xTask ) != prvDummyTagFunction )
512         {
513                 xReturn = pdFAIL;
514         }
515
516         /* Now try with a NULL handle, so using this task. */
517         vTaskSetApplicationTaskTag( NULL, NULL );
518         if( xTaskGetApplicationTaskTag( NULL ) != NULL )
519         {
520                 xReturn = pdFAIL;
521         }
522         if( xTaskGetApplicationTaskTagFromISR( NULL ) != NULL )
523         {
524                 xReturn = pdFAIL;
525         }
526
527         vTaskSetApplicationTaskTag( NULL, prvDummyTagFunction );
528         if( xTaskGetApplicationTaskTag( NULL ) != prvDummyTagFunction )
529         {
530                 xReturn = pdFAIL;
531         }
532         else
533         {
534                 if( xTaskCallApplicationTaskHook( NULL, ( void * ) xParameter ) != xParameter )
535                 {
536                         xReturn = pdFAIL;
537                 }
538                 if( xTaskCallApplicationTaskHook( NULL, ( void * ) NULL ) != pdFAIL )
539                 {
540                         xReturn = pdFAIL;
541                 }
542         }
543
544         /* Try FromISR version too. */
545         if( xTaskGetApplicationTaskTagFromISR( NULL ) != prvDummyTagFunction )
546         {
547                 xReturn = pdFAIL;
548         }
549
550         vTaskSetApplicationTaskTag( NULL, NULL );
551         if( xTaskGetApplicationTaskTag( NULL ) != NULL )
552         {
553                 xReturn = pdFAIL;
554         }
555
556         return xReturn;
557 }
558 /*-----------------------------------------------------------*/
559
560 static BaseType_t prvTimerQuery( void )
561 {
562 TimerHandle_t xTimer;
563 BaseType_t xReturn = pdPASS;
564 const char *pcTimerName = "TestTimer";
565 const TickType_t xTimerPeriod = ( TickType_t ) 100;
566 const UBaseType_t uxTimerNumber = ( UBaseType_t ) 55;
567
568         xTimer = xTimerCreate(  pcTimerName,
569                                                         xTimerPeriod,
570                                                         pdFALSE,
571                                                         ( void * ) xTimerPeriod,
572                                                         NULL ); /* Not actually going to start timer so NULL callback is ok. */
573
574         if( xTimer != NULL )
575         {
576                 if( xTimerGetPeriod( xTimer ) != xTimerPeriod )
577                 {
578                         xReturn = pdFAIL;
579                 }
580
581                 if( strcmp( pcTimerGetName( xTimer ), pcTimerName ) != 0 )
582                 {
583                         xReturn = pdFAIL;
584                 }
585
586                 vTimerSetTimerNumber( xTimer, uxTimerNumber );
587                 if( uxTimerGetTimerNumber( xTimer ) != uxTimerNumber )
588                 {
589                         xReturn = pdFAIL;
590                 }
591
592                 xTimerDelete( xTimer, portMAX_DELAY );
593         }
594         else
595         {
596                 xReturn = pdFAIL;
597         }
598
599         return xReturn;
600 }
601 /*-----------------------------------------------------------*/
602
603 BaseType_t xRunCodeCoverageTestAdditions( void )
604 {
605 BaseType_t xReturn = pdPASS;
606
607         xReturn &= prvStaticAllocationsWithNullBuffers();
608         xReturn &= prvTraceUtils();
609         xReturn &= prvPeekTimeout();
610         xReturn &= prvQueueQueryFromISR();
611         xReturn &= prvTaskQueryFunctions();
612         xReturn &= prvTaskTags();
613         xReturn &= prvTimerQuery();
614
615         return xReturn;
616 }
617 /*-----------------------------------------------------------*/
618