Queues¶
The TI-RTOS Queue module provides a thread-safe unidirectional message passing module operating in a first in, first out (FIFO) basis. Queues are commonly used to allow high priority threads to pass messages to lower priority tasks for deferred processing; therefore allowing low priority tasks to block until necessary to run.
In Figure 18. a queue is configured for unidirectional communication from task A to task B. Task A “puts” messages into the queue and task B “gets” messages from the queue.
Functional Example “”“”“”“”“”“”“”“”“” Figure 19. and Figure 20. illustrate how a queue is used to enqueue a button press message from a Hwi to a Swi to be post-processed within a task context.
With interrupts enabled, a pin interrupt can occur asynchronously within a
Hwi context. To keep interrupts as short as possible, the work
associated to the interrupt is deferred to tasks for processing. In the
some example applications, pin interrupts are abstracted
via the Board Key module. This module notifies registered functions via a
Swi callback. In this case, Application_keyChangeHandler
is the registered callback function.
Step 1 in Figure 19. shows the callback to
Application_keyChangeHandler
when a key is pressed. This event is
placed into the application’s queue for processing.
1 2 3 4 | void Application_keyChangeHandler(uint8 keys)
{
Application_enqueueMsg(APP_KEY_CHANGE_EVT, keys, NULL);
}
|
Step 2 in Figure 19. shows how this key press is enqueued for the application task. Here, memory is allocated so the message can be added to the queue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | static uint8_t Application_enqueueMsg(uint8_t event, uint8_t state, uint8_t *pData)
{
qEvt_t *pMsg = malloc(sizeof(qEvt_t));
// Create dynamic pointer to message.
if (pMsg)
{
pMsg->hdr.event = event;
pMsg->hdr.state = state;
pMsg->pData = pData;
// Enqueue the message.
return Queue_put(appMsgQueue,pMsg->_elem);
}
return (false);
}
|
Step 3 in Figure 20., the application is unblocked by the posted event where it proceeds to check if messages have been placed in the queue for processing.
1 2 3 4 5 6 7 8 9 10 11 12 13 | // If RTOS queue is not empty, process app message
if (events & APP_QUEUE_EVT)
{
scEvt_t *pMsg;
while (pMsg = (scEvt_t *)Queue_get(appMsgQueue))
{
// Process message
Application_processAppMsg(pMsg);
// Free the space from the message
free(pMsg);
}
}
|
Step 4 in Figure 20., the application takes the dequeued message and processes it.
1 2 3 4 5 6 7 8 9 10 | static void Application_processAppMsg(sbcEvt_t *pMsg)
{
switch (pMsg->hdr.event)
{
case APP_KEY_CHANGE_EVT:
Application_handleKeys(pMsg->hdr.state);
break;
//...
}
}
|
Step 5 in Figure 20., the application can now free the memory allocated in Step 2.