3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
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.
22 * http://www.FreeRTOS.org
23 * http://aws.amazon.com/freertos
29 * Tests the use of queue sets.
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.
42 /* Standard includes. */
46 /* Kernel includes. */
55 #if ( configUSE_QUEUE_SETS == 1 ) /* Remove the tests if queue sets are not defined. */
58 /* The number of queues that are created and added to the queue set. */
59 #define queuesetNUM_QUEUES_IN_SET 3
61 /* The length of each created queue. */
62 #define queuesetQUEUE_LENGTH 3
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
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
73 /* The priorities used in this demo. */
74 #define queuesetLOW_PRIORITY ( tskIDLE_PRIORITY )
75 #define queuesetMEDIUM_PRIORITY ( queuesetLOW_PRIORITY + 1 )
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 )
81 /* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */
82 #define queuesetISR_TX_PERIOD ( 100UL )
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 )
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
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 )
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;
107 * The task that periodically sends to the queue set.
109 static void prvQueueSetSendingTask( void * pvParameters );
112 * The task that reads from the queue set.
114 static void prvQueueSetReceivingTask( void * pvParameters );
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
122 static void prvCheckReceivedValue( uint32_t ulReceived );
125 * For purposes of test coverage, functions that read from and write to a
126 * queue set from an ISR respectively.
128 static void prvReceiveFromQueueInSetFromISR( void );
129 static void prvSendToQueueInSetFromISR( void );
132 * Create the queues and add them to a queue set before resuming the Tx
135 static void prvSetupTest( void );
138 * Checks a value received from a queue falls within the range of expected
141 static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived,
142 uint32_t ulExpectedReceived );
145 * Increase test coverage by occasionally change the priorities of the two tasks
146 * relative to each other.
148 static void prvChangeRelativePriorities( void );
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
155 static void prvTestQueueOverwriteWithQueueSet( void );
158 * Test the case where two queues within a set are written to with
161 static void prvTestQueueOverwriteOnTwoQueusInQueueSet( void );
162 static void prvTestQueueOverwriteFromISROnTwoQueusInQueueSet( void );
165 * Local pseudo random number seed and return functions. Used to avoid calls
166 * to the standard library.
168 static size_t prvRand( void );
169 static void prvSRand( size_t uxSeed );
171 /*-----------------------------------------------------------*/
173 /* The queues that are added to the set. */
174 static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
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 };
180 /* The handle of the queue set to which the queues are added. */
181 static QueueSetHandle_t xQueueSet;
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;
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;
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;
198 /* The value sent to the queue from the ISR is file scope so the
199 * xAreQueeuSetTasksStillRunning() function can check it is incrementing as
201 static volatile uint32_t ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
203 /* Used by the pseudo random number generator. */
204 static size_t uxNextRand = 0;
206 /* The task handles are stored so their priorities can be changed. */
207 TaskHandle_t xQueueSetSendingTask, xQueueSetReceivingTask;
209 /*-----------------------------------------------------------*/
211 void vStartQueueSetTasks( void )
213 /* Create the tasks. */
214 xTaskCreate( prvQueueSetSendingTask, "SetTx", configMINIMAL_STACK_SIZE, NULL, queuesetMEDIUM_PRIORITY, &xQueueSetSendingTask );
216 if( xQueueSetSendingTask != NULL )
218 xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask );
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 );
228 /*-----------------------------------------------------------*/
230 BaseType_t xAreQueueSetTasksStillRunning( void )
232 static uint32_t ulLastCycleCounter, ulLastISRTxValue = 0;
233 static uint32_t ulLastQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
234 BaseType_t xReturn = pdPASS, x;
236 if( ulLastCycleCounter == ulCycleCounter )
238 /* The cycle counter is no longer being incremented. Either one of the
239 * tasks is stalled or an error has been detected. */
243 ulLastCycleCounter = ulCycleCounter;
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++ )
250 if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] )
255 ulLastQueueUsedCounter[ x ] = ulQueueUsedCounter[ x ];
258 /* Check the global status flag. */
259 if( xQueueSetTasksStatus != pdPASS )
264 /* Check that the ISR is still sending values to the queues too. */
265 if( ulISRTxValue == ulLastISRTxValue )
271 ulLastISRTxValue = ulISRTxValue;
276 /*-----------------------------------------------------------*/
278 static void prvQueueSetSendingTask( void * pvParameters )
280 uint32_t ulTaskTxValue = 0;
281 size_t uxQueueToWriteTo;
282 QueueHandle_t xQueueInUse;
284 /* Remove compiler warning about the unused parameter. */
285 ( void ) pvParameters;
287 /* Seed mini pseudo random number generator. */
288 prvSRand( ( size_t ) &ulTaskTxValue );
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 ];
296 /* Note which index is being written to to ensure all the queues are
298 ( ulQueueUsedCounter[ uxQueueToWriteTo ] )++;
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 )
304 /* The send should always pass as an infinite block time was
306 xQueueSetTasksStatus = pdFAIL;
309 #if ( configUSE_PREEMPTION == 0 )
315 /* If the Tx value has reached the range used by the ISR then set it
317 if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE )
322 /* Increase test coverage by occasionally change the priorities of the
323 * two tasks relative to each other. */
324 prvChangeRelativePriorities();
327 /*-----------------------------------------------------------*/
329 static void prvChangeRelativePriorities( void )
331 static UBaseType_t ulLoops = 0;
332 static eRelativePriorities ePriorities = eEqualPriority;
334 /* Occasionally change the task priority relative to the priority of
335 * the receiving task. */
338 if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS )
342 switch( ePriorities )
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;
353 case eTxHigherPriority:
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;
363 case eTxLowerPriority:
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;
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 );
379 /*-----------------------------------------------------------*/
381 static void prvQueueSetReceivingTask( void * pvParameters )
384 QueueHandle_t xActivatedQueue;
385 TickType_t xBlockTime;
387 /* Remove compiler warnings. */
388 ( void ) pvParameters;
390 /* Create the queues and add them to the queue set before resuming the Tx
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 )
405 xBlockTime = portMAX_DELAY;
408 /* Wait for a message to arrive on one of the queues in the set. */
409 xActivatedQueue = xQueueSelectFromSet( xQueueSet, portMAX_DELAY );
411 if( xActivatedQueue == NULL )
413 if( xBlockTime != 0 )
415 /* This should not happen as an infinite delay was used. */
416 xQueueSetTasksStatus = pdFAIL;
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 )
426 xQueueSetTasksStatus = pdFAIL;
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();
434 prvCheckReceivedValue( ulReceived );
438 if( xQueueSetTasksStatus == pdPASS )
445 /*-----------------------------------------------------------*/
447 void vQueueSetAccessQueueSetFromISR( void )
449 static uint32_t ulCallCount = 0;
451 /* xSetupComplete is set to pdTRUE when the queues have been created and
452 * are available for use. */
453 if( xSetupComplete == pdTRUE )
455 /* It is intended that this function is called from the tick hook
456 * function, so each call is one tick period apart. */
459 if( ulCallCount > queuesetISR_TX_PERIOD )
463 /* First attempt to read from the queue set. */
464 prvReceiveFromQueueInSetFromISR();
466 /* Then write to the queue set. */
467 prvSendToQueueInSetFromISR();
471 /*-----------------------------------------------------------*/
473 static void prvCheckReceivedValue( uint32_t ulReceived )
475 static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
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. */
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 )
490 /* The value was sent from the ISR. */
491 if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY )
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. */
496 else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY )
498 /* The value received is at the higher limit of the expected range.
499 * Don't test it and expect to wrap soon. */
503 /* Check the value against its expected value range. */
504 if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromISR ) != pdPASS )
506 xQueueSetTasksStatus = pdFAIL;
510 configASSERT( xQueueSetTasksStatus );
512 /* It is expected to receive an incrementing number. */
513 ulExpectedReceivedFromISR++;
515 if( ulExpectedReceivedFromISR == 0 )
517 ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
522 /* The value was sent from the Tx task. */
523 if( ulReceived < queuesetIGNORED_BOUNDARY )
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. */
528 else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY )
530 /* The value received is at the higher limit of the expected range.
531 * Don't test it and expect to wrap soon. */
535 /* Check the value against its expected value range. */
536 if( prvCheckReceivedValueWithinExpectedRange( ulReceived, ulExpectedReceivedFromTask ) != pdPASS )
538 xQueueSetTasksStatus = pdFAIL;
542 configASSERT( xQueueSetTasksStatus );
544 /* It is expected to receive an incrementing number. */
545 ulExpectedReceivedFromTask++;
547 if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )
549 ulExpectedReceivedFromTask = 0;
553 /*-----------------------------------------------------------*/
555 static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived,
556 uint32_t ulExpectedReceived )
558 BaseType_t xReturn = pdPASS;
560 if( ulReceived > ulExpectedReceived )
562 configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
564 if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION )
571 configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
573 if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION )
581 /*-----------------------------------------------------------*/
583 static void prvReceiveFromQueueInSetFromISR( void )
585 QueueSetMemberHandle_t xActivatedQueue;
588 /* See if any of the queues in the set contain data. */
589 xActivatedQueue = xQueueSelectFromSetFromISR( xQueueSet );
591 if( xActivatedQueue != NULL )
593 /* Reading from the queue for test purposes only. */
594 if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS )
596 /* Data should have been available as the handle was returned from
597 * xQueueSelectFromSetFromISR(). */
598 xQueueSetTasksStatus = pdFAIL;
601 /* Ensure the value received was the value expected. */
602 prvCheckReceivedValue( ulReceived );
605 /*-----------------------------------------------------------*/
607 static void prvSendToQueueInSetFromISR( void )
609 static BaseType_t xQueueToWriteTo = 0;
610 uint32_t ulTxValueSnapshot = ulISRTxValue;
612 if( xQueueSendFromISR( xQueues[ xQueueToWriteTo ], ( void * ) &ulTxValueSnapshot, NULL ) == pdPASS )
616 /* If the Tx value has wrapped then set it back to its initial value. */
617 if( ulISRTxValue == 0UL )
619 ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
622 /* Use a different queue next time. */
625 if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET )
631 /*-----------------------------------------------------------*/
633 static void prvTestQueueOverwriteWithQueueSet( void )
635 uint32_t ulValueToSend = 0, ulValueReceived = 0;
636 QueueHandle_t xQueueHandle = NULL, xReceivedHandle = NULL;
637 const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
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 );
644 if( xQueueHandle != NULL )
646 xQueueAddToSet( xQueueHandle, xQueueSet );
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 );
653 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
655 /* Expected one item in the queue set. */
656 xQueueSetTasksStatus = pdFAIL;
659 xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
661 if( xReceivedHandle != xQueueHandle )
663 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
664 * held in the queue set. */
665 xQueueSetTasksStatus = pdFAIL;
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
672 xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
674 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
676 /* Still expected one item in the queue set. */
677 xQueueSetTasksStatus = pdFAIL;
680 xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
682 if( xReceivedHandle != xQueueHandle )
684 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
685 * held in the queue set. */
686 xQueueSetTasksStatus = pdFAIL;
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 );
693 if( ulValueReceived != ulValueToSend )
695 /* Unexpected value received from the queue. */
696 xQueueSetTasksStatus = pdFAIL;
699 /* Should be anything in the queue set now. */
700 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
702 xQueueSetTasksStatus = pdFAIL;
705 xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
707 if( xReceivedHandle != NULL )
709 xQueueSetTasksStatus = pdFAIL;
713 xQueueRemoveFromSet( xQueueHandle, xQueueSet );
714 vQueueDelete( xQueueHandle );
717 /*-----------------------------------------------------------*/
719 static void prvTestQueueOverwriteOnTwoQueusInQueueSet( void )
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;
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 );
732 if( ( xQueueHandle1 != NULL ) && ( xQueueHandle2 != NULL ) )
734 /* Add both queues to the queue set. */
735 xQueueAddToSet( xQueueHandle1, xQueueSet );
736 xQueueAddToSet( xQueueHandle2, xQueueSet );
738 /* Add an item using the first queue. */
739 xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend1 );
741 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
743 /* Expected one item in the queue set. */
744 xQueueSetTasksStatus = pdFAIL;
747 xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
749 if( xReceivedHandle != xQueueHandle1 )
751 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
752 * held in the queue set. */
753 xQueueSetTasksStatus = pdFAIL;
756 /* Next add an item to the second queue. */
757 xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend2 );
759 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
761 /* Expected two items in the queue set. */
762 xQueueSetTasksStatus = pdFAIL;
765 /* The head of the queue set should not have changed though. */
766 xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
768 if( xReceivedHandle != xQueueHandle1 )
770 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
771 * held in the queue set. */
772 xQueueSetTasksStatus = pdFAIL;
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 );
781 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
783 /* Still expected two items in the queue set. */
784 xQueueSetTasksStatus = pdFAIL;
787 xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
789 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
791 /* Still expected two items in the queue set. */
792 xQueueSetTasksStatus = pdFAIL;
795 /* Repeat the above to ensure the queue set state doesn't change. */
796 xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend2 );
798 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
800 /* Still expected two items in the queue set. */
801 xQueueSetTasksStatus = pdFAIL;
804 xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
806 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
808 /* Still expected two items in the queue set. */
809 xQueueSetTasksStatus = pdFAIL;
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 );
819 if( xReceivedHandle != xQueueHandle1 )
821 /* Wrote to xQueueHandle1 first so expected that handle to be read from
823 xQueueSetTasksStatus = pdFAIL;
826 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
828 /* One value was read from the set, so now only expect a single value
830 xQueueSetTasksStatus = pdFAIL;
833 xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
835 if( ulValueReceived != ulValueToSend2 )
837 /* Unexpected value received from the queue. ulValueToSend1 was written
838 * first, but then overwritten with ulValueToSend2; */
839 xQueueSetTasksStatus = pdFAIL;
842 xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
844 if( xReceivedHandle != xQueueHandle2 )
846 /* xQueueHandle1 has already been removed from the set so expect only
847 * xQueueHandle2 to be left. */
848 xQueueSetTasksStatus = pdFAIL;
851 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
853 /* The last value was read from the set so don't expect any more. */
854 xQueueSetTasksStatus = pdFAIL;
857 xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
859 if( ulValueReceived != ulValueToSend1 )
861 /* Unexpected value received from the queue. ulValueToSend2 was written
862 * first, but then overwritten with ulValueToSend1. */
863 xQueueSetTasksStatus = pdFAIL;
866 /* Should be anything in the queue set now. */
867 xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
869 if( xReceivedHandle != NULL )
871 xQueueSetTasksStatus = pdFAIL;
875 xQueueRemoveFromSet( xQueueHandle1, xQueueSet );
876 xQueueRemoveFromSet( xQueueHandle2, xQueueSet );
877 vQueueDelete( xQueueHandle1 );
878 vQueueDelete( xQueueHandle2 );
881 /*-----------------------------------------------------------*/
883 static void prvTestQueueOverwriteFromISROnTwoQueusInQueueSet( void )
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;
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 );
896 if( ( xQueueHandle1 != NULL ) && ( xQueueHandle2 != NULL ) )
898 /* Add both queues to the queue set. */
899 xQueueAddToSet( xQueueHandle1, xQueueSet );
900 xQueueAddToSet( xQueueHandle2, xQueueSet );
902 /* Add an item using the first queue using the 'FromISR' version of the
903 * overwrite function. */
904 xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend1, NULL );
906 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
908 /* Expected one item in the queue set. */
909 xQueueSetTasksStatus = pdFAIL;
912 xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
914 if( xReceivedHandle != xQueueHandle1 )
916 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
917 * held in the queue set. */
918 xQueueSetTasksStatus = pdFAIL;
921 /* Next add an item to the second queue using the 'FromISR' version of the
922 * overwrite function. */
923 xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend2, NULL );
925 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
927 /* Expected two items in the queue set. */
928 xQueueSetTasksStatus = pdFAIL;
931 /* The head of the queue set should not have changed though. */
932 xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
934 if( xReceivedHandle != xQueueHandle1 )
936 /* Wrote to xQueueHandle so expected xQueueHandle to be the handle
937 * held in the queue set. */
938 xQueueSetTasksStatus = pdFAIL;
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 );
947 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
949 /* Still expected two items in the queue set. */
950 xQueueSetTasksStatus = pdFAIL;
953 xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
955 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
957 /* Still expected two items in the queue set. */
958 xQueueSetTasksStatus = pdFAIL;
961 /* Repeat the above to ensure the queue set state doesn't change. */
962 xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend2, NULL );
964 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
966 /* Still expected two items in the queue set. */
967 xQueueSetTasksStatus = pdFAIL;
970 xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
972 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
974 /* Still expected two items in the queue set. */
975 xQueueSetTasksStatus = pdFAIL;
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 );
985 if( xReceivedHandle != xQueueHandle1 )
987 /* Wrote to xQueueHandle1 first so expected that handle to be read from
989 xQueueSetTasksStatus = pdFAIL;
992 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
994 /* One value was read from the set, so now only expect a single value
996 xQueueSetTasksStatus = pdFAIL;
999 xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
1001 if( ulValueReceived != ulValueToSend2 )
1003 /* Unexpected value received from the queue. ulValueToSend1 was written
1004 * first, but then overwritten with ulValueToSend2; */
1005 xQueueSetTasksStatus = pdFAIL;
1008 xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
1010 if( xReceivedHandle != xQueueHandle2 )
1012 /* xQueueHandle1 has already been removed from the set so expect only
1013 * xQueueHandle2 to be left. */
1014 xQueueSetTasksStatus = pdFAIL;
1017 if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
1019 /* The last value was read from the set so don't expect any more. */
1020 xQueueSetTasksStatus = pdFAIL;
1023 xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
1025 if( ulValueReceived != ulValueToSend1 )
1027 /* Unexpected value received from the queue. ulValueToSend2 was written
1028 * first, but then overwritten with ulValueToSend1. */
1029 xQueueSetTasksStatus = pdFAIL;
1032 /* Should be anything in the queue set now. */
1033 xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
1035 if( xReceivedHandle != NULL )
1037 xQueueSetTasksStatus = pdFAIL;
1041 xQueueRemoveFromSet( xQueueHandle1, xQueueSet );
1042 xQueueRemoveFromSet( xQueueHandle2, xQueueSet );
1043 vQueueDelete( xQueueHandle1 );
1044 vQueueDelete( xQueueHandle2 );
1047 /*-----------------------------------------------------------*/
1049 static void prvSetupTest( void )
1052 uint32_t ulValueToSend = 0;
1054 /* Ensure the queues are created and the queue set configured before the
1055 * sending task is unsuspended.
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 );
1061 for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
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 ] );
1068 if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS )
1070 xQueueSetTasksStatus = pdFAIL;
1074 /* The queue has now been added to the queue set and cannot be added to
1076 if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL )
1078 xQueueSetTasksStatus = pdFAIL;
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 )
1087 /* It is not possible to successfully remove a queue from a queue
1088 * set it does not belong to. */
1089 xQueueSetTasksStatus = pdFAIL;
1092 /* Attempt to remove a queue from the queue set it does belong to. */
1093 if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
1095 /* It should be possible to remove the queue from the queue set it
1096 * does belong to. */
1097 xQueueSetTasksStatus = pdFAIL;
1100 /* Add an item to the queue before attempting to add it back into the
1102 xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 );
1104 if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL )
1106 /* Should not be able to add a non-empty queue to a set. */
1107 xQueueSetTasksStatus = pdFAIL;
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 );
1114 if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
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;
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 )
1125 xQueueSetTasksStatus = pdFAIL;
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();
1133 /* Test the case where two queues within a set are written to with
1134 * xQueueOverwrite(). */
1135 prvTestQueueOverwriteOnTwoQueusInQueueSet();
1136 prvTestQueueOverwriteFromISROnTwoQueusInQueueSet();
1138 /* In case any of the above have already indicated a failure. */
1139 configASSERT( xQueueSetTasksStatus != pdFAIL );
1141 /* Resume the task that writes to the queues. */
1142 vTaskResume( xQueueSetSendingTask );
1144 /* Let the ISR access the queues also. */
1145 xSetupComplete = pdTRUE;
1147 /*-----------------------------------------------------------*/
1149 static size_t prvRand( void )
1151 uxNextRand = ( uxNextRand * ( size_t ) 1103515245 ) + ( size_t ) 12345;
1152 return ( uxNextRand / ( size_t ) 65536 ) % ( size_t ) 32768;
1154 /*-----------------------------------------------------------*/
1156 static void prvSRand( size_t uxSeed )
1158 uxNextRand = uxSeed;
1161 #endif /* ( configUSE_QUEUE_SETS == 1 ) */