]> begriffs open source - cmsis-freertos/blob - Demo/Common/Minimal/QueueSet.c
Updated pack to FreeRTOS 10.4.6
[cmsis-freertos] / Demo / Common / Minimal / QueueSet.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  * Tests the use of queue sets.
30  *
31  * A receive task creates a number of queues and adds them to a queue set before
32  * blocking on the queue set receive.  A transmit task and (optionally) an
33  * interrupt repeatedly unblocks the receive task by sending messages to the
34  * queues in a pseudo random order.  The receive task removes the messages from
35  * the queues and flags an error if the received message does not match that
36  * expected.  The task sends values in the range 0 to
37  * queuesetINITIAL_ISR_TX_VALUE, and the ISR sends value in the range
38  * queuesetINITIAL_ISR_TX_VALUE to ULONG_MAX.
39  */
40
41
42 /* Standard includes. */
43 #include <stdlib.h>
44 #include <limits.h>
45
46 /* Kernel includes. */
47 #include "FreeRTOS.h"
48 #include "task.h"
49 #include "queue.h"
50
51 /* Demo includes. */
52 #include "QueueSet.h"
53
54
55 #if ( configUSE_QUEUE_SETS == 1 ) /* Remove the tests if queue sets are not defined. */
56
57
58 /* The number of queues that are created and added to the queue set. */
59     #define queuesetNUM_QUEUES_IN_SET         3
60
61 /* The length of each created queue. */
62     #define queuesetQUEUE_LENGTH              3
63
64 /* Block times used in this demo.  A block time or 0 means "don't block". */
65     #define queuesetSHORT_DELAY               200
66     #define queuesetDONT_BLOCK                0
67
68 /* Messages are sent in incrementing order from both a task and an interrupt.
69  * The task sends values in the range 0 to 0xfffe, and the interrupt sends values
70  * in the range of 0xffff to ULONG_MAX. */
71     #define queuesetINITIAL_ISR_TX_VALUE      0xffffUL
72
73 /* The priorities used in this demo. */
74     #define queuesetLOW_PRIORITY              ( tskIDLE_PRIORITY )
75     #define queuesetMEDIUM_PRIORITY           ( queuesetLOW_PRIORITY + 1 )
76
77 /* For test purposes the priority of the sending task is changed after every
78  * queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */
79     #define queuesetPRIORITY_CHANGE_LOOPS     ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 )
80
81 /* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */
82     #define queuesetISR_TX_PERIOD             ( 100UL )
83
84 /* A delay inserted when the Tx task changes its priority to be above the idle
85  * task priority to ensure the idle priority tasks get some CPU time before the
86  * next iteration of the queue set Tx task. */
87     #define queuesetTX_LOOP_DELAY             pdMS_TO_TICKS( ( TickType_t ) 200 )
88
89 /* The allowable maximum deviation between a received value and the expected
90  * received value.  A deviation will occur when data is received from a queue
91  * inside an ISR in between a task receiving from a queue and the task checking
92  * the received value. */
93     #define queuesetALLOWABLE_RX_DEVIATION    3
94
95 /* Ignore values that are at the boundaries of allowable values to make the
96  * testing of limits easier (don't have to deal with wrapping values). */
97     #define queuesetIGNORED_BOUNDARY          ( queuesetALLOWABLE_RX_DEVIATION * 2 )
98
99     typedef enum
100     {
101         eEqualPriority = 0, /* Tx and Rx tasks have the same priority. */
102         eTxHigherPriority,  /* The priority of the Tx task is above that of the Rx task. */
103         eTxLowerPriority    /* The priority of the Tx task is below that of the Rx task. */
104     } eRelativePriorities;
105
106 /*
107  * The task that periodically sends to the queue set.
108  */
109     static void prvQueueSetSendingTask( void * pvParameters );
110
111 /*
112  * The task that reads from the queue set.
113  */
114     static void prvQueueSetReceivingTask( void * pvParameters );
115
116 /*
117  * Check the value received from a queue is the expected value.  Some values
118  * originate from the send task, some values originate from the ISR, with the
119  * range of the value being used to distinguish between the two message
120  * sources.
121  */
122     static void prvCheckReceivedValue( uint32_t ulReceived );
123
124 /*
125  * For purposes of test coverage, functions that read from and write to a
126  * queue set from an ISR respectively.
127  */
128     static void prvReceiveFromQueueInSetFromISR( void );
129     static void prvSendToQueueInSetFromISR( void );
130
131 /*
132  * Create the queues and add them to a queue set before resuming the Tx
133  * task.
134  */
135     static void prvSetupTest( void );
136
137 /*
138  * Checks a value received from a queue falls within the range of expected
139  * values.
140  */
141     static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived,
142                                                                 uint32_t ulExpectedReceived );
143
144 /*
145  * Increase test coverage by occasionally change the priorities of the two tasks
146  * relative to each other.
147  */
148     static void prvChangeRelativePriorities( void );
149
150 /*
151  * Queue overwrites can only be performed on queues of length of one, requiring
152  * a special test function so a queue of length 1 can temporarily be added to a
153  * set.
154  */
155     static void prvTestQueueOverwriteWithQueueSet( void );
156
157 /*
158  * Test the case where two queues within a set are written to with
159  * xQueueOverwrite().
160  */
161     static void prvTestQueueOverwriteOnTwoQueusInQueueSet( void );
162     static void prvTestQueueOverwriteFromISROnTwoQueusInQueueSet( void );
163
164 /*
165  * Local pseudo random number seed and return functions.  Used to avoid calls
166  * to the standard library.
167  */
168     static size_t prvRand( void );
169     static void prvSRand( size_t uxSeed );
170
171 /*-----------------------------------------------------------*/
172
173 /* The queues that are added to the set. */
174     static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
175
176 /* Counts how many times each queue in the set is used to ensure all the
177  * queues are used. */
178     static uint32_t ulQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
179
180 /* The handle of the queue set to which the queues are added. */
181     static QueueSetHandle_t xQueueSet;
182
183 /* If the prvQueueSetReceivingTask() task has not detected any errors then
184  * it increments ulCycleCounter on each iteration.
185  * xAreQueueSetTasksStillRunning() returns pdPASS if the value of
186  * ulCycleCounter has changed between consecutive calls, and pdFALSE if
187  * ulCycleCounter has stopped incrementing (indicating an error condition). */
188     static volatile uint32_t ulCycleCounter = 0UL;
189
190 /* Set to pdFAIL if an error is detected by any queue set task.
191  * ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */
192     static volatile BaseType_t xQueueSetTasksStatus = pdPASS;
193
194 /* Just a flag to let the function that writes to a queue from an ISR know that
195  * the queues are setup and can be used. */
196     static volatile BaseType_t xSetupComplete = pdFALSE;
197
198 /* The value sent to the queue from the ISR is file scope so the
199  * xAreQueeuSetTasksStillRunning() function can check it is incrementing as
200  * expected. */
201     static volatile uint32_t ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
202
203 /* Used by the pseudo random number generator. */
204     static size_t uxNextRand = 0;
205
206 /* The task handles are stored so their priorities can be changed. */
207     TaskHandle_t xQueueSetSendingTask, xQueueSetReceivingTask;
208
209 /*-----------------------------------------------------------*/
210
211     void vStartQueueSetTasks( void )
212     {
213         /* Create the tasks. */
214         xTaskCreate( prvQueueSetSendingTask, "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask );
215
216         if( xQueueSetSendingTask != NULL )
217         {
218             xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask );
219
220             /* It is important that the sending task does not attempt to write to a
221              * queue before the queue has been created.  It is therefore placed into
222              * the suspended state before the scheduler has started.  It is resumed by
223              * the receiving task after the receiving task has created the queues and
224              * added the queues to the queue set. */
225             vTaskSuspend( xQueueSetSendingTask );
226         }
227     }
228 /*-----------------------------------------------------------*/
229
230     BaseType_t xAreQueueSetTasksStillRunning( void )
231     {
232         static uint32_t ulLastCycleCounter, ulLastISRTxValue = 0;
233         static uint32_t ulLastQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
234         BaseType_t xReturn = pdPASS, x;
235
236         if( ulLastCycleCounter == ulCycleCounter )
237         {
238             /* The cycle counter is no longer being incremented.  Either one of the
239              * tasks is stalled or an error has been detected. */
240             xReturn = pdFAIL;
241         }
242
243         ulLastCycleCounter = ulCycleCounter;
244
245         /* Ensure that all the queues in the set have been used.  This ensures the
246          * test is working as intended and guards against the rand() in the Tx task
247          * missing some values. */
248         for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
249         {
250             if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] )
251             {
252                 xReturn = pdFAIL;
253             }
254
255             ulLastQueueUsedCounter[ x ] = ulQueueUsedCounter[ x ];
256         }
257
258         /* Check the global status flag. */
259         if( xQueueSetTasksStatus != pdPASS )
260         {
261             xReturn = pdFAIL;
262         }
263
264         /* Check that the ISR is still sending values to the queues too. */
265         if( ulISRTxValue == ulLastISRTxValue )
266         {
267             xReturn = pdFAIL;
268         }
269         else
270         {
271             ulLastISRTxValue = ulISRTxValue;
272         }
273
274         return xReturn;
275     }
276 /*-----------------------------------------------------------*/
277
278     static void prvQueueSetSendingTask( void * pvParameters )
279     {
280         uint32_t ulTaskTxValue = 0;
281         size_t uxQueueToWriteTo;
282         QueueHandle_t xQueueInUse;
283
284         /* Remove compiler warning about the unused parameter. */
285         ( void ) pvParameters;
286
287         /* Seed mini pseudo random number generator. */
288         prvSRand( ( size_t ) &ulTaskTxValue );
289
290         for( ; ; )
291         {
292             /* Generate the index for the queue to which a value is to be sent. */
293             uxQueueToWriteTo = prvRand() % queuesetNUM_QUEUES_IN_SET;
294             xQueueInUse = xQueues[ uxQueueToWriteTo ];
295
296             /* Note which index is being written to to ensure all the queues are
297              * used. */
298             ( ulQueueUsedCounter[ uxQueueToWriteTo ] )++;
299
300             /* Send to the queue to unblock the task that is waiting for data to
301              * arrive on a queue within the queue set to which this queue belongs. */
302             if( xQueueSendToBack( xQueueInUse, &ulTaskTxValue, portMAX_DELAY ) != pdPASS )
303             {
304                 /* The send should always pass as an infinite block time was
305                  * used. */
306                 xQueueSetTasksStatus = pdFAIL;
307             }
308
309             #if ( configUSE_PREEMPTION == 0 )
310                 taskYIELD();
311             #endif
312
313             ulTaskTxValue++;
314
315             /* If the Tx value has reached the range used by the ISR then set it
316              * back to 0. */
317             if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE )
318             {
319                 ulTaskTxValue = 0;
320             }
321
322             /* Increase test coverage by occasionally change the priorities of the
323              * two tasks relative to each other. */
324             prvChangeRelativePriorities();
325         }
326     }
327 /*-----------------------------------------------------------*/
328
329     static void prvChangeRelativePriorities( void )
330     {
331         static UBaseType_t ulLoops = 0;
332         static eRelativePriorities ePriorities = eEqualPriority;
333
334         /* Occasionally change the task priority relative to the priority of
335          * the receiving task. */
336         ulLoops++;
337
338         if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS )
339         {
340             ulLoops = 0;
341
342             switch( ePriorities )
343             {
344                 case eEqualPriority:
345
346                     /* Both tasks are running with medium priority.  Now lower the
347                      * priority of the receiving task so the Tx task has the higher
348                      * relative priority. */
349                     vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY );
350                     ePriorities = eTxHigherPriority;
351                     break;
352
353                 case eTxHigherPriority:
354
355                     /* The Tx task is running with a higher priority than the Rx
356                      * task.  Switch the priorities around so the Rx task has the
357                      * higher relative priority. */
358                     vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY );
359                     vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY );
360                     ePriorities = eTxLowerPriority;
361                     break;
362
363                 case eTxLowerPriority:
364
365                     /* The Tx task is running with a lower priority than the Rx
366                      * task.  Make the priorities equal again. */
367                     vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY );
368                     ePriorities = eEqualPriority;
369
370                     /* When both tasks are using a non-idle priority the queue set
371                      * tasks will starve idle priority tasks of execution time - so
372                      * relax a bit before the next iteration to minimise the impact. */
373                     vTaskDelay( queuesetTX_LOOP_DELAY );
374
375                     break;
376             }
377         }
378     }
379 /*-----------------------------------------------------------*/
380
381     static void prvQueueSetReceivingTask( void * pvParameters )
382     {
383         uint32_t ulReceived;
384         QueueHandle_t xActivatedQueue;
385         TickType_t xBlockTime;
386
387         /* Remove compiler warnings. */
388         ( void ) pvParameters;
389
390         /* Create the queues and add them to the queue set before resuming the Tx
391          * task. */
392         prvSetupTest();
393
394         for( ; ; )
395         {
396             /* For test coverage reasons, the block time is dependent on the
397              * priority of this task - which changes during the test.  When the task
398              * is at the idle priority it polls the queue set. */
399             if( uxTaskPriorityGet( NULL ) == tskIDLE_PRIORITY )
400             {
401                 xBlockTime = 0;
402             }
403             else
404             {
405                 xBlockTime = portMAX_DELAY;
406             }
407
408             /* Wait for a message to arrive on one of the queues in the set. */
409             xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );
410
411             if( xActivatedQueue == NULL )
412             {
413                 if( xBlockTime != 0 )
414                 {
415                     /* This should not happen as an infinite delay was used. */
416                     xQueueSetTasksStatus = pdFAIL;
417                 }
418             }
419             else
420             {
421                 /* Reading from the queue should pass with a zero block time as
422                  * this task will only run when something has been posted to a task
423                  * in the queue set. */
424                 if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS )
425                 {
426                     xQueueSetTasksStatus = pdFAIL;
427                 }
428
429                 /* Ensure the value received was the value expected.  This function
430                  * manipulates file scope data and is also called from an ISR, hence
431                  * the critical section. */
432                 taskENTER_CRITICAL();
433                 {
434                     prvCheckReceivedValue( ulReceived );
435                 }
436                 taskEXIT_CRITICAL();
437
438                 if( xQueueSetTasksStatus == pdPASS )
439                 {
440                     ulCycleCounter++;
441                 }
442             }
443         }
444     }
445 /*-----------------------------------------------------------*/
446
447     void vQueueSetAccessQueueSetFromISR( void )
448     {
449         static uint32_t ulCallCount = 0;
450
451         /* xSetupComplete is set to pdTRUE when the queues have been created and
452          * are available for use. */
453         if( xSetupComplete == pdTRUE )
454         {
455             /* It is intended that this function is called from the tick hook
456              * function, so each call is one tick period apart. */
457             ulCallCount++;
458
459             if( ulCallCount > queuesetISR_TX_PERIOD )
460             {
461                 ulCallCount = 0;
462
463                 /* First attempt to read from the queue set. */
464                 prvReceiveFromQueueInSetFromISR();
465
466                 /* Then write to the queue set. */
467                 prvSendToQueueInSetFromISR();
468             }
469         }
470     }
471 /*-----------------------------------------------------------*/
472
473     static void prvCheckReceivedValue( uint32_t ulReceived )
474     {
475         static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
476
477         /* Values are received in tasks and interrupts.  It is likely that the
478          * receiving task will sometimes get preempted by the receiving interrupt
479          * between reading a value from the queue and calling this function.  When
480          * that happens, if the receiving interrupt calls this function the values
481          * will get passed into this function slightly out of order.  For that
482          * reason the value passed in is tested against a small range of expected
483          * values, rather than a single absolute value.  To make the range testing
484          * easier values in the range limits are ignored. */
485
486         /* If the received value is equal to or greater than
487          * queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */
488         if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE )
489         {
490             /* The value was sent from the ISR. */
491             if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY )
492             {
493                 /* The value received is at the lower limit of the expected range.
494                  * Don't test it and expect to receive one higher next time. */
495             }
496             else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY )
497             {
498                 /* The value received is at the higher limit of the expected range.
499                  * Don't test it and expect to wrap soon. */
500             }
501             else
502             {
503                 /* Check the value against its expected value range. */
504                 if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromISR ) != pdPASS )
505                 {
506                     xQueueSetTasksStatus = pdFAIL;
507                 }
508             }
509
510             configASSERT( xQueueSetTasksStatus );
511
512             /* It is expected to receive an incrementing number. */
513             ulExpectedReceivedFromISR++;
514
515             if( ulExpectedReceivedFromISR == 0 )
516             {
517                 ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
518             }
519         }
520         else
521         {
522             /* The value was sent from the Tx task. */
523             if( ulReceived < queuesetIGNORED_BOUNDARY )
524             {
525                 /* The value received is at the lower limit of the expected range.
526                  * Don't test it, and expect to receive one higher next time. */
527             }
528             else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY )
529             {
530                 /* The value received is at the higher limit of the expected range.
531                  * Don't test it and expect to wrap soon. */
532             }
533             else
534             {
535                 /* Check the value against its expected value range. */
536                 if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS )
537                 {
538                     xQueueSetTasksStatus = pdFAIL;
539                 }
540             }
541
542             configASSERT( xQueueSetTasksStatus );
543
544             /* It is expected to receive an incrementing number. */
545             ulExpectedReceivedFromTask++;
546
547             if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )
548             {
549                 ulExpectedReceivedFromTask = 0;
550             }
551         }
552     }
553 /*-----------------------------------------------------------*/
554
555     static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived,
556                                                                 uint32_t ulExpectedReceived )
557     {
558         BaseType_t xReturn = pdPASS;
559
560         if( ulReceived > ulExpectedReceived )
561         {
562             configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
563
564             if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION )
565             {
566                 xReturn = pdFALSE;
567             }
568         }
569         else
570         {
571             configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
572
573             if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION )
574             {
575                 xReturn = pdFALSE;
576             }
577         }
578
579         return xReturn;
580     }
581 /*-----------------------------------------------------------*/
582
583     static void prvReceiveFromQueueInSetFromISR( void )
584     {
585         QueueSetMemberHandle_t xActivatedQueue;
586         uint32_t ulReceived;
587
588         /* See if any of the queues in the set contain data. */
589         xActivatedQueue = xQueueSelectFromSetFromISR( xQueueSet );
590
591         if( xActivatedQueue != NULL )
592         {
593             /* Reading from the queue for test purposes only. */
594             if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS )
595             {
596                 /* Data should have been available as the handle was returned from
597                  * xQueueSelectFromSetFromISR(). */
598                 xQueueSetTasksStatus = pdFAIL;
599             }
600
601             /* Ensure the value received was the value expected. */
602             prvCheckReceivedValue( ulReceived );
603         }
604     }
605 /*-----------------------------------------------------------*/
606
607     static void prvSendToQueueInSetFromISR( void )
608     {
609         static BaseType_t xQueueToWriteTo = 0;
610         uint32_t ulTxValueSnapshot = ulISRTxValue;
611
612         if( xQueueSendFromISR( xQueues[ xQueueToWriteTo ], ( void * ) &ulTxValueSnapshot, NULL ) == pdPASS )
613         {
614             ulISRTxValue++;
615
616             /* If the Tx value has wrapped then set it back to its initial value. */
617             if( ulISRTxValue == 0UL )
618             {
619                 ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
620             }
621
622             /* Use a different queue next time. */
623             xQueueToWriteTo++;
624
625             if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET )
626             {
627                 xQueueToWriteTo = 0;
628             }
629         }
630     }
631 /*-----------------------------------------------------------*/
632
633     static void prvTestQueueOverwriteWithQueueSet( void )
634     {
635         uint32_t ulValueToSend = 0, ulValueReceived = 0;
636         QueueHandle_t xQueueHandle = NULL, xReceivedHandle = NULL;
637         const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
638
639         /* Create a queue that has a length of one - a requirement in order to call
640          * xQueueOverwrite.  This will get deleted again when this test completes. */
641         xQueueHandle = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
642         configASSERT( xQueueHandle );
643
644         if( xQueueHandle != NULL )
645         {
646             xQueueAddToSet( xQueueHandle, xQueueSet );
647
648             /* Add an item to the queue then ensure the queue set correctly
649              * indicates that one item is available, and that item is indeed the
650              * queue written to. */
651             xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
652
653             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
654             {
655                 /* Expected one item in the queue set. */
656                 xQueueSetTasksStatus = pdFAIL;
657             }
658
659             xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
660
661             if( xReceivedHandle != xQueueHandle )
662             {
663                 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
664                  * held in the queue set. */
665                 xQueueSetTasksStatus = pdFAIL;
666             }
667
668             /* Now overwrite the value in the queue and ensure the queue set state
669              * doesn't change as the number of items in the queues within the set have
670              * not changed. */
671             ulValueToSend++;
672             xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
673
674             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
675             {
676                 /* Still expected one item in the queue set. */
677                 xQueueSetTasksStatus = pdFAIL;
678             }
679
680             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
681
682             if( xReceivedHandle != xQueueHandle )
683             {
684                 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
685                  * held in the queue set. */
686                 xQueueSetTasksStatus = pdFAIL;
687             }
688
689             /* Also ensure the value received from the queue is the overwritten
690              * value, not the value originally written. */
691             xQueueReceive( xQueueHandle, &ulValueReceived, queuesetDONT_BLOCK );
692
693             if( ulValueReceived != ulValueToSend )
694             {
695                 /* Unexpected value received from the queue. */
696                 xQueueSetTasksStatus = pdFAIL;
697             }
698
699             /* Should be anything in the queue set now. */
700             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
701             {
702                 xQueueSetTasksStatus = pdFAIL;
703             }
704
705             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
706
707             if( xReceivedHandle != NULL )
708             {
709                 xQueueSetTasksStatus = pdFAIL;
710             }
711
712             /* Clean up. */
713             xQueueRemoveFromSet( xQueueHandle, xQueueSet );
714             vQueueDelete( xQueueHandle );
715         }
716     }
717 /*-----------------------------------------------------------*/
718
719     static void prvTestQueueOverwriteOnTwoQueusInQueueSet( void )
720     {
721         uint32_t ulValueToSend1 = 1, ulValueToSend2 = 2UL, ulValueReceived = 0;
722         QueueHandle_t xQueueHandle1 = NULL, xQueueHandle2 = NULL, xReceivedHandle = NULL;
723         const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
724
725         /* Create two queues that have a length of one - a requirement in order to call
726          * xQueueOverwrite.  These will get deleted again when this test completes. */
727         xQueueHandle1 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
728         configASSERT( xQueueHandle1 );
729         xQueueHandle2 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
730         configASSERT( xQueueHandle2 );
731
732         if( ( xQueueHandle1 != NULL ) && ( xQueueHandle2 != NULL ) )
733         {
734             /* Add both queues to the queue set. */
735             xQueueAddToSet( xQueueHandle1, xQueueSet );
736             xQueueAddToSet( xQueueHandle2, xQueueSet );
737
738             /* Add an item using the first queue. */
739             xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend1 );
740
741             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
742             {
743                 /* Expected one item in the queue set. */
744                 xQueueSetTasksStatus = pdFAIL;
745             }
746
747             xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
748
749             if( xReceivedHandle != xQueueHandle1 )
750             {
751                 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
752                  * held in the queue set. */
753                 xQueueSetTasksStatus = pdFAIL;
754             }
755
756             /* Next add an item to the second queue. */
757             xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend2 );
758
759             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
760             {
761                 /* Expected two items in the queue set. */
762                 xQueueSetTasksStatus = pdFAIL;
763             }
764
765             /* The head of the queue set should not have changed though. */
766             xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
767
768             if( xReceivedHandle != xQueueHandle1 )
769             {
770                 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
771                  * held in the queue set. */
772                 xQueueSetTasksStatus = pdFAIL;
773             }
774
775             /* Now overwrite the value in the queue and ensure the queue set state
776              * doesn't change as the number of items in the queues within the set have
777              * not changed.  NOTE:  after this queue 1 should hold ulValueToSend2 and queue
778              * 2 should hold the value ulValueToSend1. */
779             xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend2 );
780
781             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
782             {
783                 /* Still expected two items in the queue set. */
784                 xQueueSetTasksStatus = pdFAIL;
785             }
786
787             xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
788
789             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
790             {
791                 /* Still expected two items in the queue set. */
792                 xQueueSetTasksStatus = pdFAIL;
793             }
794
795             /* Repeat the above to ensure the queue set state doesn't change. */
796             xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend2 );
797
798             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
799             {
800                 /* Still expected two items in the queue set. */
801                 xQueueSetTasksStatus = pdFAIL;
802             }
803
804             xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
805
806             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
807             {
808                 /* Still expected two items in the queue set. */
809                 xQueueSetTasksStatus = pdFAIL;
810             }
811
812             /* Now when reading from the queue set we expect the handle to the first
813              * queue to be received first, and for that queue to hold ulValueToSend2 as the
814              * originally written value was overwritten.  Likewise the second handle received
815              * from the set should be that of the second queue, and that queue should hold
816              * ulValueToSend1 as the originally written value was overwritten. */
817             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
818
819             if( xReceivedHandle != xQueueHandle1 )
820             {
821                 /* Wrote to xQueueHandle1 first so expected that handle to be read from
822                  * the set first. */
823                 xQueueSetTasksStatus = pdFAIL;
824             }
825
826             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
827             {
828                 /* One value was read from the set, so now only expect a single value
829                  * in the set. */
830                 xQueueSetTasksStatus = pdFAIL;
831             }
832
833             xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
834
835             if( ulValueReceived != ulValueToSend2 )
836             {
837                 /* Unexpected value received from the queue.  ulValueToSend1 was written
838                  * first, but then overwritten with ulValueToSend2; */
839                 xQueueSetTasksStatus = pdFAIL;
840             }
841
842             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
843
844             if( xReceivedHandle != xQueueHandle2 )
845             {
846                 /* xQueueHandle1 has already been removed from the set so expect only
847                  * xQueueHandle2 to be left. */
848                 xQueueSetTasksStatus = pdFAIL;
849             }
850
851             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
852             {
853                 /* The last value was read from the set so don't expect any more. */
854                 xQueueSetTasksStatus = pdFAIL;
855             }
856
857             xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
858
859             if( ulValueReceived != ulValueToSend1 )
860             {
861                 /* Unexpected value received from the queue.  ulValueToSend2 was written
862                  * first, but then overwritten with ulValueToSend1. */
863                 xQueueSetTasksStatus = pdFAIL;
864             }
865
866             /* Should be anything in the queue set now. */
867             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
868
869             if( xReceivedHandle != NULL )
870             {
871                 xQueueSetTasksStatus = pdFAIL;
872             }
873
874             /* Clean up. */
875             xQueueRemoveFromSet( xQueueHandle1, xQueueSet );
876             xQueueRemoveFromSet( xQueueHandle2, xQueueSet );
877             vQueueDelete( xQueueHandle1 );
878             vQueueDelete( xQueueHandle2 );
879         }
880     }
881 /*-----------------------------------------------------------*/
882
883     static void prvTestQueueOverwriteFromISROnTwoQueusInQueueSet( void )
884     {
885         uint32_t ulValueToSend1 = 1, ulValueToSend2 = 2UL, ulValueReceived = 0;
886         QueueHandle_t xQueueHandle1 = NULL, xQueueHandle2 = NULL, xReceivedHandle = NULL;
887         const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
888
889         /* Create two queues that have a length of one - a requirement in order to call
890          * xQueueOverwrite.  These will get deleted again when this test completes. */
891         xQueueHandle1 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
892         configASSERT( xQueueHandle1 );
893         xQueueHandle2 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
894         configASSERT( xQueueHandle2 );
895
896         if( ( xQueueHandle1 != NULL ) && ( xQueueHandle2 != NULL ) )
897         {
898             /* Add both queues to the queue set. */
899             xQueueAddToSet( xQueueHandle1, xQueueSet );
900             xQueueAddToSet( xQueueHandle2, xQueueSet );
901
902             /* Add an item using the first queue using the 'FromISR' version of the
903              * overwrite function. */
904             xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend1, NULL );
905
906             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
907             {
908                 /* Expected one item in the queue set. */
909                 xQueueSetTasksStatus = pdFAIL;
910             }
911
912             xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
913
914             if( xReceivedHandle != xQueueHandle1 )
915             {
916                 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
917                  * held in the queue set. */
918                 xQueueSetTasksStatus = pdFAIL;
919             }
920
921             /* Next add an item to the second queue using the 'FromISR' version of the
922              * overwrite function. */
923             xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend2, NULL );
924
925             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
926             {
927                 /* Expected two items in the queue set. */
928                 xQueueSetTasksStatus = pdFAIL;
929             }
930
931             /* The head of the queue set should not have changed though. */
932             xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
933
934             if( xReceivedHandle != xQueueHandle1 )
935             {
936                 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
937                  * held in the queue set. */
938                 xQueueSetTasksStatus = pdFAIL;
939             }
940
941             /* Now overwrite the value in the queue and ensure the queue set state
942              * doesn't change as the number of items in the queues within the set have
943              * not changed.  NOTE:  after this queue 1 should hold ulValueToSend2 and queue
944              * 2 should hold the value ulValueToSend1. */
945             xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend2, NULL );
946
947             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
948             {
949                 /* Still expected two items in the queue set. */
950                 xQueueSetTasksStatus = pdFAIL;
951             }
952
953             xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
954
955             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
956             {
957                 /* Still expected two items in the queue set. */
958                 xQueueSetTasksStatus = pdFAIL;
959             }
960
961             /* Repeat the above to ensure the queue set state doesn't change. */
962             xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend2, NULL );
963
964             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
965             {
966                 /* Still expected two items in the queue set. */
967                 xQueueSetTasksStatus = pdFAIL;
968             }
969
970             xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
971
972             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
973             {
974                 /* Still expected two items in the queue set. */
975                 xQueueSetTasksStatus = pdFAIL;
976             }
977
978             /* Now when reading from the queue set we expect the handle to the first
979              * queue to be received first, and for that queue to hold ulValueToSend2 as the
980              * originally written value was overwritten.  Likewise the second handle received
981              * from the set should be that of the second queue, and that queue should hold
982              * ulValueToSend1 as the originally written value was overwritten. */
983             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
984
985             if( xReceivedHandle != xQueueHandle1 )
986             {
987                 /* Wrote to xQueueHandle1 first so expected that handle to be read from
988                  * the set first. */
989                 xQueueSetTasksStatus = pdFAIL;
990             }
991
992             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
993             {
994                 /* One value was read from the set, so now only expect a single value
995                  * in the set. */
996                 xQueueSetTasksStatus = pdFAIL;
997             }
998
999             xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
1000
1001             if( ulValueReceived != ulValueToSend2 )
1002             {
1003                 /* Unexpected value received from the queue.  ulValueToSend1 was written
1004                  * first, but then overwritten with ulValueToSend2; */
1005                 xQueueSetTasksStatus = pdFAIL;
1006             }
1007
1008             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
1009
1010             if( xReceivedHandle != xQueueHandle2 )
1011             {
1012                 /* xQueueHandle1 has already been removed from the set so expect only
1013                  * xQueueHandle2 to be left. */
1014                 xQueueSetTasksStatus = pdFAIL;
1015             }
1016
1017             if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
1018             {
1019                 /* The last value was read from the set so don't expect any more. */
1020                 xQueueSetTasksStatus = pdFAIL;
1021             }
1022
1023             xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
1024
1025             if( ulValueReceived != ulValueToSend1 )
1026             {
1027                 /* Unexpected value received from the queue.  ulValueToSend2 was written
1028                  * first, but then overwritten with ulValueToSend1. */
1029                 xQueueSetTasksStatus = pdFAIL;
1030             }
1031
1032             /* Should be anything in the queue set now. */
1033             xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
1034
1035             if( xReceivedHandle != NULL )
1036             {
1037                 xQueueSetTasksStatus = pdFAIL;
1038             }
1039
1040             /* Clean up. */
1041             xQueueRemoveFromSet( xQueueHandle1, xQueueSet );
1042             xQueueRemoveFromSet( xQueueHandle2, xQueueSet );
1043             vQueueDelete( xQueueHandle1 );
1044             vQueueDelete( xQueueHandle2 );
1045         }
1046     }
1047 /*-----------------------------------------------------------*/
1048
1049     static void prvSetupTest( void )
1050     {
1051         BaseType_t x;
1052         uint32_t ulValueToSend = 0;
1053
1054         /* Ensure the queues are created and the queue set configured before the
1055          * sending task is unsuspended.
1056          *
1057          * First Create the queue set such that it will be able to hold a message for
1058          * every space in every queue in the set. */
1059         xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH );
1060
1061         for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
1062         {
1063             /* Create the queue and add it to the set.  The queue is just holding
1064              * uint32_t value. */
1065             xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( uint32_t ) );
1066             configASSERT( xQueues[ x ] );
1067
1068             if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS )
1069             {
1070                 xQueueSetTasksStatus = pdFAIL;
1071             }
1072             else
1073             {
1074                 /* The queue has now been added to the queue set and cannot be added to
1075                  * another. */
1076                 if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL )
1077                 {
1078                     xQueueSetTasksStatus = pdFAIL;
1079                 }
1080             }
1081         }
1082
1083         /* Attempt to remove a queue from a queue set it does not belong
1084          * to (NULL being passed as the queue set in this case). */
1085         if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL )
1086         {
1087             /* It is not possible to successfully remove a queue from a queue
1088              * set it does not belong to. */
1089             xQueueSetTasksStatus = pdFAIL;
1090         }
1091
1092         /* Attempt to remove a queue from the queue set it does belong to. */
1093         if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
1094         {
1095             /* It should be possible to remove the queue from the queue set it
1096              * does belong to. */
1097             xQueueSetTasksStatus = pdFAIL;
1098         }
1099
1100         /* Add an item to the queue before attempting to add it back into the
1101          * set. */
1102         xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 );
1103
1104         if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL )
1105         {
1106             /* Should not be able to add a non-empty queue to a set. */
1107             xQueueSetTasksStatus = pdFAIL;
1108         }
1109
1110         /* Remove the item from the queue before adding the queue back into the
1111          * set so the dynamic tests can begin. */
1112         xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 );
1113
1114         if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
1115         {
1116             /* If the queue was successfully removed from the queue set then it
1117              * should be possible to add it back in again. */
1118             xQueueSetTasksStatus = pdFAIL;
1119         }
1120
1121         /* The task that sends to the queues is not running yet, so attempting to
1122          * read from the queue set should fail. */
1123         if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL )
1124         {
1125             xQueueSetTasksStatus = pdFAIL;
1126         }
1127
1128         /* Testing the behaviour of queue sets when a queue overwrite operation is
1129          * performed on a set member requires a special test as overwrites can only
1130          * be performed on queues that have a length of 1. */
1131         prvTestQueueOverwriteWithQueueSet();
1132
1133         /* Test the case where two queues within a set are written to with
1134          * xQueueOverwrite(). */
1135         prvTestQueueOverwriteOnTwoQueusInQueueSet();
1136         prvTestQueueOverwriteFromISROnTwoQueusInQueueSet();
1137
1138         /* In case any of the above have already indicated a failure. */
1139         configASSERT( xQueueSetTasksStatus != pdFAIL );
1140
1141         /* Resume the task that writes to the queues. */
1142         vTaskResume( xQueueSetSendingTask );
1143
1144         /* Let the ISR access the queues also. */
1145         xSetupComplete = pdTRUE;
1146     }
1147 /*-----------------------------------------------------------*/
1148
1149     static size_t prvRand( void )
1150     {
1151         uxNextRand = ( uxNextRand * ( size_t ) 1103515245 ) + ( size_t ) 12345;
1152         return ( uxNextRand / ( size_t ) 65536 ) % ( size_t ) 32768;
1153     }
1154 /*-----------------------------------------------------------*/
1155
1156     static void prvSRand( size_t uxSeed )
1157     {
1158         uxNextRand = uxSeed;
1159     }
1160
1161 #endif /* ( configUSE_QUEUE_SETS == 1 ) */