Beruflich Dokumente
Kultur Dokumente
8
INTER-TASK COMMUNICATION USING MESSAGE QUEUE
Date:
AIM
To create multiple tasks and make them to share the information between them using
message queue.
APPARATUS REQUIRED
DOSBOX,
Micrium ii operating system..
DESCRIPTION
A message queue is used to send one or more messages to a task. A message queue
is basically an array of mailboxes. Through a service provided by the kernel, a task or an ISR
can deposit a message (the pointer) into a message queue. Similarly, one or more tasks can
receive messages through a service provided by the kernel. Both the sending task and
receiving task or tasks have to agree as to what the pointer is actually pointing to. Generally,
the first message inserted in the queue will be the first message extracted from the queue
(FIFO). In addition, to extract messages in a FIFO fashion, µC/OS-II allows a task to get
messages Last-In-First-Out (LIFO). “Queue” is one of the Inter-task communication method
which is used as a shared memory location used to send one or more messages to a task. It
is an array of mailboxes. Through a service provided by the kernel, a task or an ISR can
deposit a message into a message queue. One or more tasks can receive messages through
a service provided by the kernel. Both the sender and receiving task have to agree as to what
the pointer is actually pointing to. The first message inserted in the queue is the first message
extracted from the queue (FIFO). In addition, to extract messages in a FIFO, it allows a task
to get messages Last-In-First-Out (LIFO). A waiting list is associated with each message
queue, in case more than one task is to receive messages through the queue. The kernel
allows the task waiting for a message to specify a timeout. If a message is not received before
the timeout expires, the requesting task is made ready to run, and an error code (indicating a
timeout has occurred) is returned to it. A task desiring a message from an empty queue is
suspended and placed on the waiting list until a message is received. When a message is
deposited into the queue, either the highest priority task, or the first task to wait for the
message is given the message.
Fig.8.1. task depositing message into message queue
Fig.8.1. shows depositing a message into a queue. The “10” indicates the number of
messages that can accumulate in the queue. A “0” next to the hourglass indicates that the
task will wait forever for a message to arrive.
OSQAccept()
This function is used to obtain a message from the queue without putting a task to
sleep if the queue is empty. It is done by calling the OSQAccept(). If a message is
available, the oldest message (FIFO order) is retrieved from the queue and copied to
the local pointer msg and the number of entries in the queue is decreased by one to
reflect the extraction. OSQAccept() then adjust the circular queue pointer by moving
the pointer to the next entry. If there were no entries in the queue, the local pointer is
set to NULL.
Syntax
OSQAccept (OS_EVENT *pevent)
OSQQuery()
It is used to obtain the status of the message queue. It takes a “snapshot” of an task
control block that is used as a queue. It needs to allocate a variable of
type OS_Q_DATA that will be used to receive the information about desired queue.
Syntax
OSQQuery (OS_EVENT *pevent, OS_Q_DATA *pdata)
OSQFlush()
OSQFlush() allows you to remove all the messages posted to a queue and basically
start with a fresh queue.
Syntax
OSQFlush (OS_EVENT *pevent)
PROGRAM
#include "includes.h"
#include "OS_CFG.H"
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* VARIABLES
*********************************************************************************************************
*/
OS_STK Task1Stk[TASK_STK_SIZE]; /* Task #1 task stack */
OS_STK Task2Stk[TASK_STK_SIZE];
OS_STK Task3Stk[TASK_STK_SIZE];
OS_STK Task4Stk[TASK_STK_SIZE];
OS_STK Task5Stk[TASK_STK_SIZE];
OS_STK Task6Stk[TASK_STK_SIZE];
OS_STK Task7Stk[TASK_STK_SIZE];
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
void Task1(void *data);
void Task2(void *data);
void Task3(void *data);
void Task4(void *data);
void Task5(void *data);
void Task6(void *data);
void Task7(void *data);
/*$PAGE*/
/*
*********************************************************************************************************
* MAIN
*********************************************************************************************************
*/
OS_EVENT *msg;
OS_Q_DATA *p;
void *a[5];
int choice;
int count;
void main (void)
{
OSInit(); /* Initialize uC/OS-II */
PC_VectSet(uCOS,OSCtxSw);
msg=OSQCreate(a[5],5);
OSTaskCreate(Task1,(void *)1,&Task1Stk[TASK_STK_SIZE - 1],1);
OSTaskCreate(Task2,(void *)2,&Task2Stk[TASK_STK_SIZE - 1],2);
OSTaskCreate(Task3,(void *)3,&Task3Stk[TASK_STK_SIZE - 1],3);
OSTaskCreate(Task4,(void *)4,&Task4Stk[TASK_STK_SIZE - 1],4);
OSTaskCreate(Task5,(void *)5,&Task5Stk[TASK_STK_SIZE - 1],5);
OSTaskCreate(Task6,(void *)6,&Task6Stk[TASK_STK_SIZE - 1],6);
INT8U err;
pdata=pdata;
OSTaskSuspend(2);
OSTaskSuspend(3);
printf("\n\t\t***Task 1***");
for(;;)
{
printf("\nchoose option for \n1.FIFO\n2.LIFO");
printf("\nchoice = ");
scanf("%d",&choice);
if(choice==1)
OSTaskResume(2);
else if(choice==2)
OSTaskResume(3);
printf("\n\t\tSuspending TASK1");
OSTaskSuspend(OS_PRIO_SELF);
}
}
/*
*********************************************************************************************************
* TASK #2
*********************************************************************************************************
*/
void Task2 (void *pdata)
{
INT8U err;
int i;
char **n;
int a;
pdata=pdata;
printf("\n\t\t***Task 2***");
for(i=0;i<a;i++)
{
n[i] = malloc(sizeof(char) * 50);
scanf("%s",n[i]);
OSQPost(msg,n[i]);
}
printf("\n\t\tSuspending TASK2");
OSTaskSuspend(OS_PRIO_SELF);
/*
*********************************************************************************************************
* TASK #3
*********************************************************************************************************
*/
void Task3 (void *pdata)
{
INT8U err;
int i;
int a;
char **n;
pdata=pdata;
printf("\n\t\t***Task 3***");
n = malloc(sizeof(char*) * a);
for(i=0;i<a;i++)
{
n[i] = malloc(sizeof(char) * 50);
scanf("%s",n[i]);
OSQPostFront(msg,n[i]);
}
printf("\n\t\tSuspending TASK3");
OSTaskSuspend(OS_PRIO_SELF);
/*
*********************************************************************************************************
* TASK #4
*********************************************************************************************************
*/
void Task4 (void *pdata)
{
INT8U *err;
char *str;
int j;
pdata=pdata;
printf("\n\t\t***Task 4***");
OSQQuery(msg,p);
printf("\nQueue details after flushing.....\nSize:%d\nNo. of entries:%d\n",p->OSQSize,p-
>OSNMsgs);
printf("\n\t\tSuspending TASK4");
OSTaskSuspend(OS_PRIO_SELF);
}
/*
*********************************************************************************************************
* TASK #5
*********************************************************************************************************
*/
void Task5 (void *pdata)
{
INT8U err;
pdata=pdata;
printf("\n\t\t***Task 5***");
for (;;)
{
printf("\n..................Flushing queue..................");
OSQFlush(msg);
OSQQuery(msg,p);
printf("\nQueue details after flushing.....\nSize:%d\nNo. of entries:%d\n",p->OSQSize,p-
>OSNMsgs);
printf("\nStart entering data a new data");
OSTaskResume(1);
OSTaskResume(4);
printf("\n\t\tSuspending TASK5");
OSTaskSuspend(OS_PRIO_SELF);
}
}
/*
*********************************************************************************************************
* TASK #6
*********************************************************************************************************
*/
void Task6 (void *pdata)
{
INT8U *err;
pdata=pdata;
printf("\n\t\t***Task 6***");
for (;;)
{
OSQDel(msg,OS_DEL_NO_PEND,err);
if(*err==OS_NO_ERR)
{
printf("\nMessage Queue DELETED");
}
printf("\n\t\tSuspending TASK6");
OSTaskSuspend(OS_PRIO_SELF);
}
}
OBSERVATIONS
Input data
FIFO ORDER
LIFO ORDER
Fig.8.2. shows message queue of size 5 is created before the start of execution of
tasks. Task 1 asks for the manner in which message needs to be extracted from the message
queue i.e.,FIFO(First-In-First-Out) or LIFO(Last-In-First-Out). Depending on the choice ,task
2 or task 3 is executed. Task 2 for posting of message in FIFO fashion and task 3 for posting
of message in LIFO fashion. Task 4 extracts the message from queue based on which
order(FIFO or LIFO) they were posted and prints them. OSQQuery() is used to get the details
about the queue like the size of queue and number of entries in queue. On execution of task
5, the queue is flushed i.e. all the entries in the queue are deleted by the OSQFlush()
command. Previously FIFO order was used to enter data, after flushing of queue the data is
posted in LIFO fashion as shown in Fig.8.2. Task 6 then deletes the queue after checking that
the queue to be deleted is empty.
RESULT
Thus, the inter-task communication between the multiple tasks using message queue
is done by using various Message queue APIs with Micrium ii OS and the desired outcome is
achieved.