Example 12. Using a Queue Set. FreeRTOS Real Time Kernel
Oglas
Oglas
Table 25. xQueueSelectFromSet() parameters and return value
Parameter Name Description
Return Value A return value that is not NULL will be the handle of a queue or semaphore that is known to contain data. If a block time was specified (xTicksToWait was not zero), then it is possible that the calling task was placed into the Blocked state to wait for data to become available from a queue or semaphore in the set, but a handle was successfully read from the queue set before the block time expired. Handles are returned as a QueueSetMemberHandle_t type, which can be cast to either a QueueHandle_t type or
SemaphoreHandle_t type.
If the return value is NULL then a handle could not be read from the queue set. If a block time was specified (xTicksToWait was not zero) then the calling task will have been placed into the Blocked state to wait for another task or interrupt to send data to a queue or semaphore in the set, but the block time expired before that happened.
Example 12. Using a Queue Set
This example creates two sending tasks and one receiving task. The sending tasks send data to the receiving task on two separate queues, one queue for each task. The two queues are added to a queue set, and the receiving task reads from the queue set to determine which of the two queues contain data.
The tasks, queues, and the queue set, are all created in main()—see Listing 63 for its
implementation.
137
161204 Pre-release for FreeRTOS V8.x.x. See http://www.FreeRTOS.org/FreeRTOS-V9.html
for information about FreeRTOS
V9.x.x. Use http://www.FreeRTOS.org/contact to provide feedback, corrections, and check for updates.
/* Declare two variables of type QueueHandle_t. Both queues are added to the same queue set. */ static QueueHandle_t xQueue1 = NULL, xQueue2 = NULL;
/* Declare a variable of type QueueSetHandle_t. This is the queue set to which the two queues are added. */ static QueueSetHandle_t xQueueSet = NULL; int main( void )
{
/* Create the two queues, both of which send character pointers. The priority
of the receiving task is above the priority of the sending tasks, so the queues
will never have more than one item in them at any one time*/
xQueue1 = xQueueCreate( 1, sizeof( char * ) );
xQueue2 = xQueueCreate( 1, sizeof( char * ) );
/* Create the queue set. Two queues will be added to the set, each of which can
contain 1 item, so the maximum number of queue handles the queue set will ever
have to hold at one time is 2 (2 queues multiplied by 1 item per queue). */
xQueueSet = xQueueCreateSet( 1 * 2 );
/* Add the two queues to the set. */
xQueueAddToSet( xQueue1, xQueueSet );
xQueueAddToSet( xQueue2, xQueueSet );
/* Create the tasks that send to the queues. */
xTaskCreate( vSenderTask1, "Sender1", 1000, NULL, 1, NULL );
xTaskCreate( vSenderTask2, "Sender2", 1000, NULL, 1, NULL );
/* Create the task that reads from the queue set to determine which of the two
queues contain data. */
xTaskCreate( vReceiverTask, "Receiver", 1000, NULL, 2, NULL );
/* Start the scheduler so the created tasks start executing. */
vTaskStartScheduler();
/* As normal, vTaskStartScheduler() should not return, so the following lines
Will never execute. */
for( ;; );
return 0;
}
Listing 63. Implementation of main() for Example 12
The first sending task uses xQueue1 to send a character pointer to the receiving task every
100 milliseconds. The second sending task uses xQueue2 to send a character pointer to the receiving task every 200 milliseconds. The character pointers are set to point to a string that
identifies the sending task. The implementation of both sending tasks is shown in Listing 64.
138
void vSenderTask1( void *pvParameters )
{ const TickType_t xBlockTime = pdMS_TO_TICKS( 100 ); const char * const pcMessage = "Message from vSenderTask1\r\n";
/* As per most tasks, this task is implemented within an infinite loop. */
for( ;; )
{
/* Block for 100ms. */
vTaskDelay( xBlockTime );
/* Send this task's string to xQueue1. It is not necessary to use a block
time, even though the queue can only hold one item. This is because the
priority of the task that reads from the queue is higher than the priority of
this task; as soon as this task writes to the queue it will be pre-empted by
the task that reads from the queue, so the queue will already be empty again
by the time the call to xQueueSend() returns. The block time is set to 0. */
xQueueSend( xQueue1, &pcMessage, 0 );
}
}
/*-----------------------------------------------------------*/ void vSenderTask2( void *pvParameters )
{ const TickType_t xBlockTime = pdMS_TO_TICKS( 200 ); const char * const pcMessage = "Message from vSenderTask2\r\n";
/* As per most tasks, this task is implemented within an infinite loop. */
for( ;; )
{
/* Block for 200ms. */
vTaskDelay( xBlockTime );
/* Send this task's string to xQueue2. It is not necessary to use a block
time, even though the queue can only hold one item. This is because the
priority of the task that reads from the queue is higher than the priority of
this task; as soon as this task writes to the queue it will be pre-empted by
the task that reads from the queue, so the queue will already be empty again
by the time the call to xQueueSend() returns. The block time is set to 0. */
xQueueSend( xQueue2, &pcMessage, 0 );
}
}
Listing 64. The sending tasks used in Example 12
The queues that are written to by the sending tasks are members of the same queue set.
Each time a task sends to one of the queues, the handle of the queue is sent to the queue set.
The receiving task calls xQueueSelectFromSet() to read the queue handles from the queue set. After the receiving task has received a queue handle from the set, it knows the queue referenced by the received handle contains data, so reads the data from the queue directly.
The data it reads from the queue is a pointer to a string, which the receiving task prints out.
If a call to xQueueSelectFromSet() times out, then it will return NULL. In Example 12, xQueueSelectFromSet() is called with an indefinite block time, so will never time out, and can
139
161204 Pre-release for FreeRTOS V8.x.x. See http://www.FreeRTOS.org/FreeRTOS-V9.html
for information about FreeRTOS
V9.x.x. Use http://www.FreeRTOS.org/contact to provide feedback, corrections, and check for updates. only return a valid queue handle. Therefore, the receiving task does not need to check to see if xQueueSelectFromSet() returned NULL before the return value is used. xQueueSelectFromSet() will only return a queue handle if the queue referenced by the handle contains data, so it is not necessary to use a block time when reading from the queue.
The implementation of the receive task is shown in Listing 65.
void vReceiverTask( void *pvParameters )
{
QueueHandle_t xQueueThatContainsData; char *pcReceivedString;
/* As per most tasks, this task is implemented within an infinite loop. */
for( ;; )
{
/* Block on the queue set to wait for one of the queues in the set to contain data.
Cast the QueueSetMemberHandle_t value returned from xQueueSelectFromSet() to a
QueueHandle_t, as it is known all the members of the set are queues (the queue set
does not contain any semaphores). */
xQueueThatContainsData = ( QueueHandle_t ) xQueueSelectFromSet( xQueueSet,
portMAX_DELAY );
/* An indefinite block time was used when reading from the queue set, so
xQueueSelectFromSet() will not have returned unless one of the queues in the set
contained data, and xQueueThatContainsData cannot be NULL. Read from the queue. It
is not necessary to specify a block time because it is known the queue contains
data. The block time is set to 0. */
xQueueReceive( xQueueThatContainsData, &pcReceivedString, 0 );
/* Print the string received from the queue. */
vPrintString( pcReceivedString );
}
}
Listing 65. The receive task used in Example 12
Figure 37 shows the output produced by Example 12. It can be seen that the receiving task
receives strings from both sending tasks. The block time used by vSenderTask1() is half of the block time used by vSenderTask2(), causing the strings sent by vSenderTask1() to be printed out twice as often as those sent by vSenderTask2().
140
Preuzimanje
Oglas