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.

ipc_start() failed

Hi, all. I am developing on an EVMK2H. I am trying to build an IPC example that sends a simple message from DSP0 to DSP1 using messageQ with SharedMemory L2SRAM. I am setting the ipc to IPC_ProcSync_ALL. However, the Ipc_start() call failed on both of the cores. Same thing happened when I was set Ipc to IPC_ProcSync_Pair. Ipc_attach() failed too. I am attaching the zipped project. I am attaching the main function and the .cfg file down below. Thank you

/*
 *  ======== main.c ========
 */

#include <xdc/std.h>

#include <xdc/runtime/System.h>

#include <ti/sysbios/BIOS.h>
#include <xdc/runtime/Log.h>
#include <ti/sysbios/knl/Task.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/Diags.h>
#include <xdc/runtime/Error.h>
// ipc headers
#include <ti/ipc/Ipc.h>
#include <ti/sdo/utils/MultiProc.h>
//#include <ti/sdo/ipc/MessageQ.h>
//#include <ti/ipc/SharedRegion.h>
#include <ti/ipc/MessageQ.h>
#include <ti/ipc/SharedRegion.h>

#include "msg.h"

#define Heap_ID 2
#define size = sizeof(MessageQ_MsgHeader) + 5
/*
 *  ======== taskFxn ========
 */
Void taskFxn();
Void msgWriter();
Void msgReader();

/*
 *  ======== main ========
 */


Int main()
{ 
    /*
     * use ROV->SysMin to view the characters in the circular buffer
     */
	System_printf("enter main()\n");
     //UInt16 CORE_ID = MultiProc_self();
	Error_Block eb;
	Task_Params taskParams;
	System_printf("enter main()\n");
	Task_Params_init(&taskParams);
	taskParams.instance->name = "taskFxn";

	taskParams.stackSize = 0x1000;
	Error_init(&eb);

	Task_create(taskFxn, &taskParams, &eb);

    if (Error_check(&eb)) {
        System_abort("main: failed to create application thread");
    }
   BIOS_start();    /* does not return */
    return(0);
}

Void taskFxn()
{	System_printf("enter task function");
	UInt16 coreID = MultiProc_self();
		if (coreID == (UInt16)1)
		{
			msgWriter();
			}

		else{
			msgReader();
		}

}


Void msgWriter(Void) {

  System_printf("enter writer function");
  Int status = Ipc_start();
  if (status < 0) {
  	      System_abort("Ipc_start failed\n");
  	  }
  System_printf("IPC ready");
/*
  do {
	  UInt16 id = MultiProc_getId("CORE1");
	  status = Ipc_attach(id);
  }  while (status == Ipc_E_NOTREADY);
*/
  // allocate a message

  Ptr heap;
  heap = SharedRegion_getHeap(0);
  MessageQ_registerHeap(heap,Heap_ID);
  app_msg *msg;
  MessageQ_QueueId qid;

  do {
	status =MessageQ_open("myQ",&qid);
  }  while (status == MessageQ_E_NOTFOUND  );
  System_printf("messageQ opened succesfully");
		  while (1)
		  {
			 msg = (app_msg * ) MessageQ_alloc(Heap_ID,sizeof(app_msg));
			 char payload[] ="hello";
			 (*msg).msg = payload;
			 MessageQ_put (qid, (MessageQ_Msg) msg);

		  }
}

Void msgReader (Void) {

	System_printf("enter reader function");

	Int status = Ipc_start();
	if (status < 0) {
	      System_abort("Ipc_start failed\n");
	  }
		System_printf( "App_taskFxn: ipc ready");
		/*
		do {
			UInt16 id =MultiProc_getId("CORE1");
			status = Ipc_attach(id);
		} while (status == Ipc_E_NOTREADY );
		System_printf("ipc to dsp core 1 ready ");
	*/
		Ptr heap = SharedRegion_getHeap(0);
		   	MessageQ_Handle que;
		   	app_msg *msg;
		   	MessageQ_registerHeap(heap,Heap_ID);
		   	que = MessageQ_create("myQ", NULL);
       while(1)
       {

    	  MessageQ_get(que,(MessageQ_Msg *)&msg,MessageQ_FOREVER);
    	  char *payload = msg->msg;
    	  System_printf("the payload is %s\n",payload);
    	  MessageQ_free((MessageQ_Msg) msg);
       }

}

Configuration file :

var Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var LoggerBuf = xdc.useModule('xdc.runtime.LoggerBuf');
var Main = xdc.useModule('xdc.runtime.Main');
var SysMin = xdc.useModule('xdc.runtime.SysMin');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');
var Program = xdc.useModule('xdc.cfg.Program');
var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
var Task = xdc.useModule('ti.sysbios.knl.Task');
var SysStd = xdc.useModule('xdc.runtime.SysStd'); 

//var Program = xdc.useModule('xdc.cfg.Program');

//var cfgA4rgs = Program.build.cfgArgs;
//var RB = (cfgArgs.profile == "release" ? true : false);
/*
 * Uncomment this line to globally disable Asserts.
 * All modules inherit the default from the 'Defaults' module.  You
 * can override these defaults on a per-module basis using Module.common$.
 * Disabling Asserts will save code space and improve runtime performance.
Defaults.common$.diags_ASSERT = Diags.ALWAYS_OFF;
 */

/*
 * Uncomment this line to keep module names from being loaded on the target.
 * The module name strings are placed in the .const section. Setting this
 * parameter to false will save space in the .const section.  Error and
 * Assert messages will contain an "unknown module" prefix instead
 * of the actual module name.
 */
Defaults.common$.namedModule = false;

/*
 * Minimize exit handler array in System.  The System module includes
 * an array of functions that are registered with System_atexit() to be
 * called by System_exit().
 */
System.maxAtexitHandlers = 4;

/*
 * Uncomment this line to disable the Error print function.
 * We lose error information when this is disabled since the errors are
 * not printed.  Disabling the raiseHook will save some code space if
 * your app is not using System_printf() since the Error_print() function
 * calls System_printf().
Error.raiseHook = null;
 */

/*
 * Uncomment this line to keep Error, Assert, and Log strings from being
 * loaded on the target.  These strings are placed in the .const section.
 * Setting this parameter to false will save space in the .const section.
 * Error, Assert and Log message will print raw ids and args instead of
 * a formatted message.
 */
Text.isLoaded = false;

/*
 * Uncomment this line to disable the output of characters by SysMin
 * when the program exits.  SysMin writes characters to a circular buffer.
 * This buffer can be viewed using the SysMin Output view in ROV.
 */
SysMin.flushAtExit = false;

/*
 * The BIOS module will create the default heap for the system.
 * Specify the size of this default heap.
 */
BIOS.heapSize = 0xA000;

/* System stack size (used by ISRs and Swis) */
Program.stack = 0x1000;

/* Circular buffer size for System_printf() */
SysMin.bufSize = 128;

/*
 * Create and install logger for the whole system
 */
var loggerBufParams = new LoggerBuf.Params();
loggerBufParams.numEntries = 4;
var logger0 = LoggerBuf.create(loggerBufParams);
Defaults.common$.logger = logger0;
Main.common$.diags_INFO = Diags.ALWAYS_ON;

System.SupportProxy = SysStd;

/*
 * Build a custom BIOS library.  The custom library will be smaller than the
 * pre-built "instrumented" (default) and "non-instrumented" libraries.
 *
 * The BIOS.logsEnabled parameter specifies whether the Logging is enabled
 * within BIOS for this custom build.  These logs are used by the RTA and
 * UIA analysis tools.
 *
 * The BIOS.assertsEnabled parameter specifies whether BIOS code will
 * include Assert() checks.  Setting this parameter to 'false' will generate
 * smaller and faster code, but having asserts enabled is recommended for
 * early development as the Assert() checks will catch lots of programming
 * errors (invalid parameters, etc.)
 */
BIOS.libType = BIOS.LibType_Custom;
BIOS.logsEnabled = false;
BIOS.assertsEnabled = true;






/* ipc configuration 		*/
/* root of the configuration object model */
//Program.stack = 0x1000;

   
   
/*    ipc setup			*/
	var Ipc = xdc.useModule('ti.sdo.ipc.Ipc');
Ipc.procSync = Ipc.ProcSync_ALL;
Ipc.sr0MemorySetup = true;
   //Needd to use Ipc_Attach later in run time
   
   
/*      messageQ setup  */

var MesaageQ = xdc.useModule('ti.sdo.ipc.MessageQ');



/*      multiProc setup            */
  
  var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
  var procNameAry = [ "CORE0", "CORE1", "CORE2", "CORE3", "CORE4", "CORE5",
        "CORE6", "CORE7" ,"HOST"];
     MultiProc.setConfig("CORE1", procNameAry);
        
        
/*  sharedRegion setup */
	var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
	var L2SRAM = Program.cpu.memoryMap["L2SRAM"];
    print("L2SRAM info ");
	print(L2SRAM.base.toString(16));
	print(L2SRAM.len.toString(16));

	SharedRegion.setEntryMeta(0,
   		 new SharedRegion.Entry({base:  0x800000,
       	 name:           "L2SRAM_shared",
    	
       	 len:           0x010000 ,
         ownerProcId:    0,
         isValid:        true,
         cacheEnable:    true
    })
);
  /* select ipc libraries */
var Build = xdc.useModule('ti.sdo.ipc.Build');
Build.libType = (true ? Build.LibType_NonInstrumented : Build.LibType_Debug);
Build.assertsEnabled = (true ? false : true);
Build.logsEnabled = (true ? false : true); 

  • Hi Wei,

    In your code, IPC_start() is called inside the msgWriter() and it is getting called on a conditional basis of CoreID - 1.
    If the core ID is zero, there is a possibility that the IPC_start() may not get called right???
    make sure that the IPC_start is getting called before the BIOS_start().

    As per the IPC user guide,

    An application that uses IPC APIs—such as MessageQ, GateMP, and ListMP—must include the Ipc
    module header file and call Ipc_start() in the main() function. If the main() function calls any IPC APIs, the
    call to Ipc_start() must be placed before any calls to IPC modules. For example:
    #include <ti/ipc/Ipc.h>
    ...
    Int main(Int argc, Char* argv[])
    {
    Int status;
    /* Call Ipc_start() */
    status = Ipc_start();
    if (status < 0) {
    System_abort("Ipc_start failed\n");
    }
    BIOS_start();
    return (0);
    }

    -----------
  • Hi, Shankari. I tried and moved Ipc_start() to the main function. It still failed. The problem is that it gets stuck in the Ipc_start() function. My application never got to the status checking line. Can you check if the configuration file has any mistakes? Again, I trying to have dsp0 talk to dsp1 using messageQ with dsp0 being the reader.
  • Wei,

    You mentioned that you were attaching a zip file of the project but I don't see anything attached.  Anyways...

    In your listed configuration file you have the SharedRegion setup in L2SRAM:

    wei chen91 said:
    /* sharedRegion setup */ var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion'); var L2SRAM = Program.cpu.memoryMap["L2SRAM"]; print("L2SRAM info "); print(L2SRAM.base.toString(16)); print(L2SRAM.len.toString(16)); SharedRegion.setEntryMeta(0, new SharedRegion.Entry({base: 0x800000, name: "L2SRAM_shared", len: 0x010000 , ownerProcId: 0, isValid: true, cacheEnable: true }) );

    L2SRAM is *not* shared memory.  Each DSP core has its own L1 and L2 RAM/cache.  Ipc_start()/Ipc_attach() uses the SharedRegion for the handshaking, so this would be the reason that DSP0 & DSP1 can't synch the Ipc.

    Also, Ipc.ProcSync_ALL requires *all* processors in the MultiProc.setConfig() list to participate:

    wei chen91 said:
    /* multiProc setup */ var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc'); var procNameAry = [ "CORE0", "CORE1", "CORE2", "CORE3", "CORE4", "CORE5", "CORE6", "CORE7" ,"HOST"]; MultiProc.setConfig("CORE1", procNameAry);

    The above list requires DSPs 0-7 *and* the "HOST" A15 to be running with Ipc.ProcSync_ALL and calling Ipc_start().  If your goal is to have just DSP0 and DSP1 do Ipc communication then your MultiProc.setConfig() list should include just those processors when using Ipc.ProcSync_ALL.

    If using Ipc.ProcSync_PAIR then you can have the full MultiProc.setConfig() list as you do, and then just Ipc_attach() to cores as needed.  But your commented-out Ipc_attach() code is using "CORE1" for both msgWriter (which runs on just "CORE0") and msgReader (which runs on just "CORE1").  msgReader should be attempting to Ipc_attach() to "CORE0".

    Finally, for Keystone2 you shouldn't be assigning the "self" element of MultiProc.setConfig():

    wei chen91 said:
    MultiProc.setConfig("CORE1", procNameAry);

    You should instead use null (mostly for situations where you have just one .cfg file for all DSPs):
        MultiProc.setConfig(null, procNameAry);
    since MultiProcSetup_init() will assign it automatically based on DNUM: 

    /*!
     *  ======== MultiProcSetup_init ========
     */
    Void MultiProcSetup_init()
    {
        extern cregister volatile UInt DNUM;
        UInt16 procId;

        /* Skip if the procId has already been set */
        if (MultiProc_self() != MultiProc_INVALIDID) {
            return;
        }

        procId = MultiProcSetup_getProcId(DNUM);

        /*
         *  Assert that image is being loaded onto a core that was included in the
         *  MultiProc name list (via setConfig)
         */
        Assert_isTrue(procId != MultiProc_INVALIDID,
                MultiProcSetup_A_invalidProcessor);

        /* Set the local ID */
        MultiProc_setLocalId(procId);

    You also could have a different .cfg file for each DSP core, with just the "self" parameter of MultiProc.setConfig() being different.  For DSP0's .cfg you would do:
        MultiProc.setConfig("CORE0, procNameAry);
    and for DSP1's .cfg you would do:
        MultiProc.setConfig("CORE1, procNameAry);

    Regards,

    - Rob

     

  • thanks. your answer is very extensive. I did find out that I was using the wrong memory.