This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Little help regarding MessageQ?

As I am a newbie in IPC domain and facing tons of issues. I have gone through examples and I have learned a lot. There is problem when I try to run my own code I face lot of issues. At present I am stuck at a issue. I can't comprehend what I am doing wrong . But I couldn't find any thing

My work flow is as:

ARM side

1- Create messageq with name HOSTQ

while(1)

{

3-declare Message1,Message2

4-alloc Message1

5- Put Message1 to DSPQ

6- get Message2 from HOSTQ

7- free Message2

}

DSP side

1- Create messageq with name DSPQ

while(1)

{

3-declare Message1,Message2

4- get Message2 from DSPQ

5- free Message2

6- alloc Message1

7- Put Message1 to HOSTQ

}

When I load DSP program using mpmcl utility to all dsps.

then I run ARM side code on linux.

I am able to see only ones message coming from DSP0. after one message No other messages are recieved while It should keep sending and receving messages.

Similar situation is on ARM side.

What could be wrong in this scenario.

Please help me in this regard.

Can somebody say something other than running example codes.

I am attaching code here by.

DSP Code

void create_messageQ()
{
	MessageQ_Handle   messageQDSP0;
	MessageQ_Params   messageQParamsDSP0;
    char QueueName[64];
    MessageQ_QueueId ARMQ_Id;
	Int status;
	int flag =0;
	int counter = 0;

    System_sprintf(QueueName, "%s_%s", "SLAVE_DDR",
                   MultiProc_getName(MultiProc_self()));
	// Create MessageQ with name DSP0Q
	MessageQ_Params_init(&messageQParamsDSP0);
	System_printf("Parameter Done \n");

	messageQDSP0 = MessageQ_create(QueueName, &messageQParamsDSP0);
	if (messageQDSP0 == NULL)
	{
		System_abort("MessageQ_create failed\n");
	}

    System_printf("created MessageQ with QueueID: 0x%x\n",MessageQ_getQueueId(messageQDSP0));



	while(1)
	{
		if(MultiProc_self() == 1){

		// getting Message from ARM
		 System_printf("Waiting for ARM to send  \n");
		MessageQ_Msg   MsgDSP0, MsgDSP1;
		 System_printf("Number of messages in Queue are  %d  \n", MessageQ_count(messageQDSP0));

		do{
			Task_sleep(1);
			status = MessageQ_get(messageQDSP0, &MsgDSP0, MessageQ_FOREVER);
			//System_printf("Queue Empty \n");
		}

	    while(status != MessageQ_S_SUCCESS);


		System_printf("Message has info of 0x%x \n", (( MsgObj*)MsgDSP0)->info );


		// replying to ARM

		if(flag == 0)
		{
			do
			{
				System_sprintf(QueueName, "%s_%d", "HOST_DDR",MultiProc_self());
				status= MessageQ_open (QueueName, &ARMQ_Id);
				System_printf("Failed due to ERROR: %d \n", status);
			}
			while (status != MessageQ_S_SUCCESS);
			System_printf("Opened MessageQ with QueueID: 0x%x\n", ARMQ_Id);
	        flag = 1;
		}

		Task_sleep(500*MultiProc_self());
		MsgDSP1 = MessageQ_alloc(0, sizeof(MsgObj));
		if(MsgDSP1 == NULL)
		{
			System_abort("Failed to Allocate Message on Heap \n");

		}

		((MsgObj*)MsgDSP1)->DSP = MultiProc_self();
		((MsgObj*)MsgDSP1)->info  = counter++;
		MessageQ_setReplyQueue	(messageQDSP0, MsgDSP1);
		if(MessageQ_put(MessageQ_getReplyQueue(MsgDSP0), MsgDSP1) < 0)
			System_abort("Failed to Put Message on HOST_DRR MessageQ\n");
		status = MessageQ_free((MessageQ_Msg)MsgDSP0);

	}
}

}

ARM side Code

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ti/ipc/Std.h>
#include <ti/ipc/Ipc.h>
#include <ti/ipc/MessageQ.h>
#include <pthread.h>
#include <ti/ipc/interfaces/INetworkTransport.h>
#include <ti/ipc/interfaces/ITransport.h>
#include <ti/ipc/transports/TransportRpmsg.h>

/*
 *Message Structure for MessageQ
 */
typedef struct MsgObj {
    MessageQ_MsgHeader header;
    int8_t DSP;
    int    info;
} MsgObj;

/*
 *Globals
 */
  MessageQ_Params     msgParams;
  MessageQ_Handle     g_ddrMsgHandle;
  Int    status;
  MessageQ_QueueId    g_remoteQueueId_temp = (MessageQ_QueueId)0x10080; 
  int  counter =0;
  char HostQName [50]; 


void func_1()
{
 /*while(1)
  {*/
	sleep(1);
 	MessageQ_Msg msg = (MessageQ_Msg) NULL;  		
  	msg = MessageQ_alloc(0, sizeof(MsgObj));

  	if (msg == NULL)
  	{
  		printf("<P>Cannot Alloc message from HEAP \n "); 
  		Ipc_stop();
  		exit(EXIT_FAILURE);
  	}
   
  	((MsgObj*)msg)->info  = 0xc000000 + counter*0x1000; // Alloc
  	((MsgObj*)msg)->DSP = 0;
  	counter++;
  	MessageQ_setMsgId(msg, 0);
  	MessageQ_setReplyQueue(g_ddrMsgHandle, msg);
  	if(MessageQ_put(g_remoteQueueId_temp , msg) != 0 )   
  		printf("<P>Message Put Failed with info %d\n ", ((MsgObj*)msg)->info);

  //}
}

/*
 *Reader Thread for ARM
 */

void func_2(void* CoreNum)
{
 
  /* Create the local Message Queue for receiving. */
  MessageQ_Params_init(&msgParams);
  sprintf(HostQName, "HOST_DDR_%d", (*((int*)CoreNum)));
  g_ddrMsgHandle = MessageQ_create(HostQName, &msgParams);
  if (g_ddrMsgHandle == NULL)
  {
  	printf("Error in MessageQ_create\n");
  	pthread_exit(-1);
  }
  printf("MessageQ ARM is created with ID 0x%x \n", MessageQ_getQueueId(g_ddrMsgHandle));
  
  while(1)
  {
	func_1();	
	sleep(1);
  	MessageQ_Msg   MsgDSP0;
  	status = MessageQ_get(g_ddrMsgHandle, &MsgDSP0, MessageQ_FOREVER);
  	if(status != MessageQ_S_SUCCESS)
 		 printf("Message get failed \n");

  	printf("Message has info of %d  from DSP %d\n", (( MsgObj*)MsgDSP0)->info, (( MsgObj*)MsgDSP0)->DSP );
  
  	g_remoteQueueId_temp = MessageQ_getReplyQueue(MsgDSP0);
  	status = MessageQ_free((MessageQ_Msg)MsgDSP0);
  	if(status != 0)
  	printf("Message free failed \n");
 

   }

}

/*
 *Writer Thread for ARM
 */



/*
 *Main Entry Point
 */

int main(void)
{

  int iret1,iret2;
  int32_t status;
  pthread_t thread[8];
  pthread_attr_t attr;
  int i[8] = {1,2,3,4,5,6,7,8};

  Ipc_transportConfig(&TransportRpmsg_Factory);
  do
  {
  	printf("<P1>Starting IPC \n ");
  	status = Ipc_start();
  }
  while (status < 0);
  printf("<P2>Started IPC \n ");

 
 
 func_2(&i[0]);

}































  • Hi Rao,
    We will get back to you with our suggestions. Thank you for the post.
  • Hi Rao,

    Actually speaking, community members may not have bandwidth to review your code and correct them. However, let me give an attempt.

    The idea of releasing the IPC examples is to ease the development of customers and reducing the development time from scratch. Usually, customers will also start from something which already works. I mean, they will try to run the examples and customize/modify/ enhance to meet their project requirements.

    Already you have created multiple posts and I have posted lot of steps on building / running those examples.
    You may have to compare the correct code flow of the working example with your source code.
  • Hello Rao,

    We have spent a lot of time on Message Q implementation, but unfortunately have not gotten to test our implementation yet, but I do see some differences between what we plan on doing and what you are doing above.

    First, on the DSP side I do not see a call to IpcMgr_ipcStartup(); I understand this is required before Message Q can be used.

    We then create the slave queue like you do and wait for a message from the host. However, I don't believe you need the do { sleep() } while(); around the MessgeQ_get as MessageQ_get is a blocking function that already waits for the message. You can check the status afterwards and print an error if needed.

    Now, is where we diverge quite a bit. In our code when we get the first message from the host we call

    this->Module.hostQueId = MessageQ_getReplyQueue(msg);

    This is supposed to allow the slave to reply to the host without having to create another queue. The reply works like this

    MessageQ_put(this->Module.hostQueId, (MessageQ_Msg)msg);

    At that point we declare the MessageQ is up and ready and we create a task for message Rx.

    Any time we want to send a message to the host we do a MessageQ_alloc then a MessageQ_put(Module.hostQueId,(MessageQ_Msg)msg);. The host frees the buffer.

    The receive task waits for a message from the host

    int status = MessageQ_get(msgQRx->Module.slaveQue, (MessageQ_Msg *)&msg, MessageQ_FOREVER);

    copies out the payload and frees the message

    MessageQ_free((MessageQ_Msg)msg);


    The other very confusing part of this was the setup of the resource table. Hopefully you have already worked on that. The default table is rsc_table_vayu_dsp.h. This table defines the memory used by the ARM and the DSP for everything, MessageQ, shared peripherals, external memory, etc. I think this is what is going to really make or break our implementation.

    Hope this helps.
  • Thanks Chris,
    1- IpcMgr_ipcStartup() is called in .cfg file as
    BIOS.addUserStartupFunction('&IpcMgr_ipcStartup');

    2- Initially I didn't had sleep() in this code but a post suggested the same issues is removed by adding sleep() in coded to avoid race condition.
    e2e.ti.com/.../1385088 Nevertheless result is same with/without sleep().

    3- Correct me if I am wrong .
    Are you saying there is no need to create MessageQ on HOST side. I couldn't comprehend that. As far As I understand MessageQ_getReplyQueue() requires MessageQ_setReplyQueue() on host side and this requires MessageQ to be created. Please comment on that.

    4- I am using CFG file of Image Processing Demo. I have not worked with resource table. What should I do specifically for Resource table to accommodate above scenario.

    5- I have successfully built and ran some custom MessageQ codes. i.e. Host sends infinite number of messages Messages to All DSPs.
  • Rao,

    I'll do my best to answer your questions....

    1)  I am planning to use the same DSP code on each processor, thus we have only 1 cfg file. Thus, we use null in the following command,

    MultiProc.setConfig(null, ["HOST", "IPU2", "IPU1", "DSP2", "DSP1"]);

    and we set the processor name later in run time.  When you do that you don't do the IpcMgr_ipcStartup setup in the config file.  So, that is a difference from how we are configured I guess. 

    2)  Glad this does not appear to be a race condition.

    3)  No, you still need the create MessageQ in the host side.  What you don't really need is the MessageQ_open on the slave side, if you use the reply queue id.  You also don't need the MessageQ_alloc if you can always reply to received messages 1-1.  You just reuse the buffer sent to you from the host.  One thing that I found interesting about MessageQ is that any buffer which was alloc'ed can be freed on from either side. 

    4)  Here is a thread I participated in about the resource table. 

    https://e2e.ti.com/support/arm/sitara_arm/f/791/t/503515

    I think this is the thread that started it.

    https://e2e.ti.com/support/arm/sitara_arm/f/791/p/500457/1822502

    Perhaps since you are using an example code as a baseline you already have the default resource table.  I suppose since you are passing messages already it must be fundamentally working.  But, the resource table is what defines the shared memory between the ARM and DSP. 

    I guess I was just showing an alternative implementation with using getReplyQueue if you wanted to try something different. 

  • ,

    Your support is very much appreciated. Thank you so much for your contribution to e2e.