Skip to end of metadata
Go to start of metadata

Message queues allow your application to send messages between tasks.

Creating and Deleting

Before using a message queue, it must first be created with OSQCreate(). A message queue can be deleted with OSQDel(). For examples of both, see the example below.

OS_Q  App_MessageQ;
              :
              :
void  App_SomeTask (void  *p_arg)
{
    RTOS_ERR    err;
    OS_OBJ_QTY  qty;
              :
              :
                                       /* Create the message queue.                           */
    OSQCreate(&App_MessageQ,           /*   Pointer to user-allocated message queue.          */
              "App MessageQ",          /*   Name used for debugging.                          */
               10,                     /*   Queue will have 10 messages maximum.              */
              &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on message queue create. */
    }
              :
              :
              :
                                       /* Delete the message queue.                           */
    qty = OSQDel(&App_MessageQ,        /*   Pointer to user-allocated message queue.          */
                  OS_OPT_DEL_NO_PEND,  /*   Option: delete if 0 tasks are pending.            */
                 &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on message queue delete. */
    }
              :
              :
}
Listing - Example of call to OSQCreate() and OSQDel()

 

Using Message Queues

A task can wait for a message to be added to the queue by calling OSQPend(). Tasks can send messages by calling OSQPost(). The example below shows one task waiting for a message, while another task posts a message.

Note: The content of the message is allocated in the sending task's stack. Only a pointer to the message is sent to the waiting task, rather than the message itself.

typedef struct app_message {
    CPU_INT08U   type;
    CPU_INT08U  *p_buf;
} APP_MESSAGE;
              :
              :
OS_Q  App_MessageQ;
              :
              :
void  App_SomeTask (void  *p_arg)
{
    RTOS_ERR      err;
    void         *p_raw_msg;
    OS_MSG_SIZE   msg_size;
    APP_MESSAGE  *p_msg;
              :
              :
                                                /* Wait until task receives a message.        */
    p_raw_msg = OSQPend(&App_MessageQ,          /*   Pointer to user-allocated message queue. */
                         100,                   /*   Wait for 100 OS Ticks maximum.           */
                         OS_OPT_PEND_BLOCKING,  /*   Task will block.                         */
                        &msg_size,              /*   Will contain size of message in bytes.   */
                         DEF_NULL,              /*   Timestamp is not used.                   */
                        &err);
    if (err.Code == RTOS_ERR_NONE) {
        /* Got message, handle. */
        p_msg = (APP_MESSAGE *)p_raw_msg;
    } else {
        /* Handle error on message queue pend. */
    }
              :
              :
}
 
void  App_SomeOtherTask (void  *p_arg)
{
    RTOS_ERR     err;
    APP_MESSAGE  msg;
              :
              :
                                          /* Fill test message.                               */
    msg.type  = 42;
    msg.p_buf = "Test Message";
                                          /* Send message to the waiting task.                */
    OSQPost(&App_MessageQ,                /*   Pointer to user-allocated message queue.       */
            (void *)&msg,                 /*   The message is a pointer to the APP_MESSAGE.   */
            (OS_MSG_SIZE)sizeof(void *),  /*   Size of the message is the size of a pointer.  */
             OS_OPT_POST_FIFO,            /*   Add message at the end of the queue.           */
            &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on message queue post. */
    }
              :
              :
}
Listing - Example of call to OSQPend() and OSQPost()

If the kernel configuration allows it, the wait for a message can be aborted with OSQPendAbort().

OS_Q  App_MessageQ;
              :
              :
void  App_SomeTask (void  *p_arg)
{
    RTOS_ERR    err;
    OS_OBJ_QTY  qty;
              :
              :
                                              /* Abort the highest-priority task's pend.      */
    qty = OSQPendAbort(&App_MessageQ,         /*   Pointer to user-allocated message queue.   */
                        OS_OPT_PEND_ABORT_1,  /*   Only abort the HP task's pend.             */
                       &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on message queue pend abort. */
    }
              :
              :
}
Listing - Example of call to OSQPendAbort()

An application can remove all messages from a message queue by using OSQFlush().

OS_Q  App_MessageQ;
              :
              :
void  App_SomeTask (void  *p_arg)
{
    RTOS_ERR    err;
    OS_MSG_QTY  qty;
              :
              :
                                   /* Flush (empty) the message queue.                        */
    qty = OSQFlush(&App_MessageQ,
                   &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on message queue flush. */
    }
              :
              :
}
Listing - Example of call to OSQFlush()

Using Task Message Queues

Since message queues are often used to send messages to a single task, a task can have its own built-in message queue. The example call OSTaskCreate() in Task Management Kernel Services shows how to create a task which can have up to 10 messages pending. 

A task can wait on its built-in message queue by calling OSTaskQPend(). Another task can send a message to the waiting task by calling OSTaskQPost().

typedef struct app_message {
    CPU_INT08U   type;
    CPU_INT08U  *p_buf;
} APP_MESSAGE;
              :
              :
OS_TCB  App_SomeTaskTCB;
              :
              :
void  App_SomeTask (void  *p_arg)
{
    RTOS_ERR      err;
    void         *p_raw_msg;
    OS_MSG_SIZE   msg_size;
    APP_MESSAGE  *p_msg;
              :
              :
                                                   /* Wait until task receives a message.     */
    p_raw_msg = OSTaskQPend( 100,                  /*   Wait for 100 OS Ticks maximum.        */
                             OS_OPT_PEND_BLOCKING, /*   Task will block.                      */
                            &msg_size,             /*   Will contain size of message in bytes.*/
                             DEF_NULL,             /*   Timestamp is not used.                */
                            &err);
    if (err.Code == RTOS_ERR_NONE) {
        /* Got message, handle. */
        p_msg = (APP_MESSAGE *)p_raw_msg;
    } else {
        /* Handle error on task message queue pend. */
    }
              :
              :
}
 
void  App_SomeOtherTask (void  *p_arg)
{
    RTOS_ERR     err;
    APP_MESSAGE  msg;
              :
              :
                                              /* Fill test message.                           */
    msg.type  = 42;
    msg.p_buf = "Test Message";
                                              /* Send message to the waiting task.            */
    OSTaskQPost(&App_SomeTaskTCB,             /*   Pointer to pending task's TCB.             */
                (void *)&msg,                 /*   Message is a pointer to the APP_MESSAGE.   */
                (OS_MSG_SIZE)sizeof(void *),  /*   Size of message is the size of a pointer.  */
                 OS_OPT_POST_FIFO,            /*   Add message at the end of the queue.       */
                &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on task message queue post. */
    }
              :
              :
}
Listing - Example of call to OSTaskQPend() and OSTaskQPost()

If the kernel configuration allows it, the wait for a message can be aborted with OSTaskQPendAbort().

OS_TCB  App_SomeTaskTCB;
              :
              :
void  App_SomeOtherTask (void  *p_arg)
{
    RTOS_ERR     err;
    CPU_BOOLEAN  aborted;
              :
              :
                                                   /* Abort the task's pend.                  */
    aborted = OSTaskQPendAbort(&App_SomeTaskTCB,   /*   Pointer to pending task's TCB.        */
                                OS_OPT_POST_NONE,  /*   No special options.                   */
                               &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on task message queue pend abort. */
    }
              :
              :
}
Listing - Example of call to OSTaskQPendAbort()

Your application can remove all messages from a task message queue by using OSTaskQFlush().

OS_TCB  App_SomeTaskTCB;
              :
              :
void  App_SomeOtherTask (void  *p_arg)
{
    RTOS_ERR    err;
    OS_MSG_QTY  qty;
              :
              :
                                          /* Flush (empty) the message queue.                 */
    qty = OSTaskQFlush(&App_SomeTaskTCB,  /*   Pointer to pending task's TCB.                 */
                       &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* Handle error on task message queue flush. */
    }
              :
              :
}
Listing - Example of call to OSTaskQFlush()

  • No labels