Note: While it is sometimes necessary to block (pend) on more than one queue if you are integrating FreeRTOS with third party of legacy code, designs that are free from such restrictions can normally achieve the same functionality in a more efficient way using the alternative design pattern that is documented at the bottom of this page.
Queue sets can contain queues and semaphores, which together are known as queue set members. API function parameters and return values that can take either a queue handle or a semaphore handle use the QueueSetMemberHandle_t type. Variables of type QueueHandle_t and SemaphoreHandle_t can normally be implicitly converted to an QueueSetMemberHandle_t parameter or return value without compiler warnings being generated (explicit casting to and from the QueueSetMemberHandle_t type is not normally required).
| Creating a queue set |
Before a queue set can be used it must be created using the
xQueueCreateSet() API function.
Once created the queue set is referenced by a variable of type
QueueSetHandle_t.
|
| Adding a member to a queue set |
The xQueueAddToSet() API function
is used to add a queue or semaphore to a queue set.
|
| Blocking (pending) on a queue set |
The xQueueSelectFromSet() API function is
used to test whether any of the set members are ready for
reading - where reading means 'receiving' when the member is a queue, and 'taking'
when the member is a semaphore.
Just like when using the xQueueReceive() and xSemaphoreTake() API functions, xQueueSelectFromSet() allows the calling task to optionally block until a member of the queue set is ready for reading. NULL is returned if a call to xQueueSelectFromSet() times out. Otherwise xQueueSelectFromSet() returns the handle of the queue set member that is ready for reading, allowing the calling task to immediately call xQueueReceive() or xSemaphoreTake() (on a queue handle or semaphore handle respectively) with the guarantee that the operation will succeed.
|
The standard demo/test file called QueueSet.c (located in the FreeRTOS/Demo/Common/Minimal/ directory of the main FreeRTOS zip file download) contains a comprehensive example.
The structure definition is shown below.
typedef struct IP_TASK_COMMANDS
{
eIPEvent_t eEventType; /* Tells the receiving task what the event is. */
void *pvData; /* Holds or points to any data associated with the event. */
} xIPStackEvent_t;
Examples of how this structure is used:
The UDP/IP task processes events using a simple loop:
/* The variable used to receive from the queue. */
xIPStackEvent_t xReceivedEvent;
for( ;; )
{
/* Wait until there is something to do. */
xQueueReceive( xNetworkEventQueue, &xReceivedEvent, portMAX_DELAY );
/* Perform a different action for each event type. */
switch( xReceivedEvent.eEventType )
{
case eNetworkDownEvent :
prvProcessNetworkDownEvent();
break;
case eEthernetRxEvent :
prvProcessEthernetFrame( xReceivedEvent.pvData );
break;
case eARPTimerEvent :
prvAgeARPCache();
break;
case eStackTxEvent :
prvProcessGeneratedPacket( xReceivedEvent.pvData );
break;
case eDHCPEvent:
vDHCPProcess();
break;
default :
/* Should not get here. */
break;
}
}