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 problems

Other Parts Discussed in Thread: SYSBIOS

Hello,

I'm starting testing IPC to pass notifications between two cores and I'm getting some problems with the IPC_start function.

I have modified cfg file to include all the next modules to work with IPC in a tms332c6678 multicore DSP:

var Ipc = xdc.useModule('ti.sdo.ipc.Ipc');
var Notify = xdc.useModule('ti.sdo.ipc.Notify');
var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
var nameList = MultiProc.getDeviceProcNames();
MultiProc.setConfig(null, nameList);
Ipc.procSync = Ipc.ProcSync_ALL;

With this configuration I get a -11 in function returning value. I've seen similar problems in this forums but I'm not able to get enough information from your answers.

I've added a shared memory (same as in the evm667x example):

var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
SharedRegion.setEntryMeta(0,
    { base: SHAREDMEM,
      len:  SHAREDMEMSIZE,
      ownerProcId: 0,
      isValid: true,
      name: "DDR2_RAM",
    });

But now the problem is that the IPC_start function seems to go into an infinite loop because the execution takes a long time without returning from it.

 

I'm not sure what to try now. Could you help me with it?

Regards.

  • An error code of -11 is "Ipc_E_NOTREADY" (you can see for yourself in ipc_xxx_xxx/ti/ipc/Ipc.h). Other IPC functions may return this value -- and that's expected, you just need to put your function in a while() loop until it succeeds. HOWEVER, Ipc_start does not normally return NOTREADY -- but it looks like Ipc_start may return NOTREADY if your SharedRegion is not configured correctly.

    If you didn't have a SharedRegion in the first test, then you would _definitely_ get some errors. IPC needs SharedRegion entry 0 to (1) exist and (2) be accessible by all cores on the device (which typically isn't a problem, especially if you follow the default configuration and put it in MSMCSRAM [0x0c000000])

    My guess on the infinite loop is that you aren't running all 8 cores.  Since you use the command:

    var nameList = MultiProc.getDeviceProcNames();
    MultiProc.setConfig(null, nameList);

     That means that MultiProc is configured to use all cores on your device (8 cores for c6678) -- and Ipc.procSync_ALL uses MultiProc to discover which cores it needs to connect with.  So if MultiProc tells a core to connect with 7 others, but only 3 others are running.. then it will loop forever until it connects with the missing cores.

     

    Let me know if that was your problem. If not, I'd be glad to help some more.

  • Ok, I've defined a shared memory from 0x0c0000 to 0x0c200000 whit followin instructions:

    var SHAREDMEM           = 0x0C000000;
    var SHAREDMEMSIZE       = 0x00200000;

    var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
    SharedRegion.setEntryMeta(0,
        { base: SHAREDMEM,
          len:  SHAREDMEMSIZE,
          ownerProcId: 0,
          isValid: true,
          name: "DDR2_RAM",
        });

    and I've indicated to IPC that I want to use this configuration in cores 0 and 1:

    MultiProc.setConfig(null, ["CORE0", "CORE1", "CORE2", "CORE3", "CORE4", "CORE5", "CORE6", "CORE7"]);
    var nameList = MultiProc.getDeviceProcNames();
    MultiProc.setConfig("CORE0", nameList);
    MultiProc.setConfig("CORE1", nameList);

    Then in the C program I have a recursive call to Ipc_start until the call would sucess:

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

    void main(void)
    {
        int status = -1;

        while(status<0){
            status = Ipc_start();
        }
       .....

    and I make run both cores but the execution doesn't get out while loop.

    It is suposed that when both cores are runing Ipc_start should sucess, right? What seems to be wrong?

  • 1) Don't put Ipc_start in a loop -- I tried to make it clear that Ipc_start does not need to be in a loop, but other functions may need to be

    2) Do not do MultiProc.setConfig("CORE0/1",...) if the same compiled image is going to be loaded on each core. Instead, do MultiProc.setConfig(null,...) and make sure MultiProc_setLocalId(...) is called in the application appropriately (sometimes it works without it, but you should call it to be safe).

  • 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 BIOS = xdc.useModule('ti.sysbios.BIOS');
    var Ipc = xdc.useModule('ti.sdo.ipc.Ipc');
    var Notify = xdc.useModule('ti.sdo.ipc.Notify');
    
    
    /* DSP will get assigned processor id 2. */
    var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
    MultiProc.setConfig(null, ["CORE0", "CORE1"]);
    var nameList = MultiProc.getDeviceProcNames();
    //MultiProc.setConfig("CORE0", ["CORE0", "CORE1", "CORE2", "CORE3", "CORE4", "CORE5", "CORE6", "CORE7"]);
    MultiProc.setConfig(null, nameList);
    
    Ipc.procSync = Ipc.ProcSync_PAIR;
    /*Ipc.procSync = Ipc.ProcSync_ALL;*/
    
    /* Configuration required because HOST is not running Linux */
    /*var Ipc = xdc.useModule('ti.sdo.ipc.Ipc');
    Ipc.sr0MemorySetup = true;*/
    
    /* Shared Memory base address and length */
    var SHAREDMEM           = 0x0C000000;
    var SHAREDMEMSIZE       = 0x00200000;
    
    /* 
     *  Need to define the shared region. The IPC modules use this
     *  to make portable pointers. All processors need to add this
     *  call with their base address of the shared memory region.
     *  If the processor cannot access the memory, do not add it.
     */ 
    var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
    SharedRegion.setEntryMeta(0,
        { base: SHAREDMEM, 
          len:  SHAREDMEMSIZE,
          ownerProcId: 0,
          isValid: true,
          name: "DDR2_RAM",
        });
    
    
    
    /*var System   = xdc.useModule('xdc.runtime.System');
    var SysStd   = xdc.useModule('xdc.runtime.SysStd');
    System.SupportProxy = SysStd;
    
    BIOS.heapSize   = 0x8000;*/

    Sorry I made some errors, first the instructions to use the config in the cores 0 and 1 seems to be:

    MultiProc.setConfig(null, ["CORE0", "CORE1"]);
    var nameList = MultiProc.getDeviceProcNames();
    MultiProc.setConfig("null", nameList);

    before modify it I always got 1 when calling MultiProc_self() from any core. Is it now correct?

    I also forgot to modify the syncronization method now:

    Ipc.procSync = Ipc.ProcSync_PAIR;

    With this changes the function Ipl_start returns 0 (even when just one core is running). However, the Ipc_attach function always returns -11 when calling from any core.

    I send you my short program to make easier to help me.

    Thanks.

    /*
     * main.c
     *
     *  Created on: 03/08/2011
     *      Author: Marcos
     */
    
    #include <xdc/std.h>
    #include <string.h>
    /* ---- XDC.RUNTIME module Headers */
    #include <xdc/runtime/Memory.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/IHeap.h>
    /* ----- IPC module Headers */
    #include <ti/ipc/GateMP.h>
    #include <ti/ipc/Ipc.h>
    #include <ti/ipc/MessageQ.h>
    #include <ti/ipc/HeapBufMP.h>
    #include <ti/ipc/MultiProc.h>
    /* ---- BIOS6 module Headers */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    /* ---- Get globals from .cfg Header */
    #include <xdc/cfg/global.h>
    
    
    #include <ti/ipc/Notify.h>
    
    #define INTERRUPT_LINE  0
    #define EVENTID         10
    
    //CSL_IntgenRegs *pIntGenRegs = (CSL_IntgenRegs *)0x02880800;
    Void task1(UArg, UArg);
    Void cbFxn(UInt16, UInt16, UInt32, UArg, UInt32);
    
    Task_Handle tsk1;
    
    
    /*
     *  ======== main ========
     */
    void main(void)
    {
    	int status = -1;
    
    	while(status<0){
    		status = Ipc_start();
    	}
    
    	/* Create a task to handle notification between two cores*/
    	Task_Params taskParams;
    	Task_Params_init(&taskParams);
    	taskParams.priority = 1;
    	tsk1 = Task_create (task1, NULL, NULL);
    
    	BIOS_start();
    }
    
    /*
     *  ======== task1 ========
     */
    Void task1(UArg arg0, UArg arg1)
    {
    	int status=-1;
    	int thisCore;
    
    	thisCore = MultiProc_self();
    	switch(thisCore)
    	{
    		case 0:
    		{
    			while(1){
    				while(status<0){
    					status = Ipc_attach(1);
    				}
    				status = Notify_sendEvent(1, 0, EVENTID, NULL, TRUE);
    				Task_sleep(1);
    			}
    		}
    
    		case 1:
    		{
    			while(1){
    				while(status<0){
    					status = Ipc_attach(0);
    				}
    				status = Notify_registerEvent(0, 0, 10, (Notify_FnNotifyCbck)cbFxn, NULL);
    				if (status < 0) {
    					System_abort("Notify_registerEvent failed\n");
    				}
    				Task_sleep(1);
    			}
    		}
    	}
    }
    
    /*
     *  ======== cbFxn ======== (task to handle notifying interruption)
     */
    Void cbFxn(UInt16 procId, UInt16 lineId, UInt32 eventId, UArg arg, UInt32 payload)
    {
    	int thisCore;
    
    	thisCore = MultiProc_self();
    	System_printf("Running callback function [from core %d]\n", thisCore);
    }
    

  • Changing from Ipc.procSync_ALL to PAIR has a very significant impact:  ALL does the synchronization inside Ipc_start whereas PAIR requires you to manually call Ipc_attach -- and importantly: the attaches need to be done in a certain order

    First, all processors need to attach to the region owner (specified as Core0 in the SharedRegion config) -- and then all cores need to attach to each other in increasing order.  The following is the "suggested" code for PAIR -- but I have found that I still get deadlocks sometimes, so I wrote my own routine.  But first, the example code for PAIR:

     

     

     

    SharedRegion_Entry entry;

    int status = Ipc_S_SUCCESS;

    unsigned int i;

     

     

    status = Ipc_start();


    if (status < 0) {

    printf("Ipc_start failed:!\n");

    switch(status) {

    case Ipc_S_SUCCESS: printf("Ipc_S_SUCCESS: operation was successful\n"); break;

    case Ipc_S_ALREADYSETUP: printf("Ipc_S_ALREADYSETUP: already successfully called\n"); break;

    case Ipc_E_NOTREADY: printf("Ipc_E_NOTREADY: shared memory is not ready\n"); break;

    case Ipc_E_FAIL: printf("Ipc_E_FAIL: operation failed\n"); break;

    }

    }


    // get region 0 (Special IPC region) information

    SharedRegion_getEntry(0, &entry);


    // if entry is not valid then return

    if (entry.isValid == FALSE) {

    return;

    }


    // Must attach to owner first to get default GateMP

    if (MultiProc_self() != entry.ownerProcId) {

    do {

    status = Ipc_attach(entry.ownerProcId);

    Task_sleep(1);

       } while (status < 0);

    printf("Proc %d attached to entryOwner %d\n", MultiProc_self(), entry.ownerProcId);

    }


    // Loop to attach to all other processors, starting from the specified base going through the cluster sequentially (skipping self & owner)

    for (i = 0; i < MultiProc_getNumProcessors(); i++) {

    if ((i == MultiProc_self()) || (i == entry.ownerProcId)) {

    continue;

       }


       // call Ipc_attach for each other processor in this cluster

       do {

        status = Ipc_attach(i);

       } while (status < 0);

       printf("     Proc %d attached to peerProc %d\n", MultiProc_self(), i);

    }

     

     

     

     


     

     

    And now my code is using Ipc.procSync_NONE:

     

    First, add to the cfg file:

    Program.sectMap[".myMSMC"] = "MSMCSRAM";

     

    and now in your main code:

     


    #include <ti/sysbios/hal/Cache.h>

     

    // This goes as a "global variable", putting it outside of the function should be fine

     

    #pragma DATA_SECTION(syncLine, ".myMSMC");

    int syncLine[8] = { 0,0,0,0, 0,0,0,0 };

     

    ........................... // more code

     

     

    SharedRegion_Entry entry;

        int status = Ipc_S_SUCCESS;

        unsigned int i;


    // Call Ipc_start() to setup sync structures

    status = Ipc_start();


    if (status < 0) {

    printf("Ipc_start failed:!\n");

    switch(status) {

    case Ipc_S_SUCCESS: printf("Ipc_S_SUCCESS: operation was successful\n"); break;

    case Ipc_S_ALREADYSETUP: printf("Ipc_S_ALREADYSETUP: already successfully called\n"); break;

    case Ipc_E_NOTREADY: printf("Ipc_E_NOTREADY: shared memory is not ready\n"); break;

    case Ipc_E_FAIL: printf("Ipc_E_FAIL: operation failed\n"); break;

    }

    }

     

     

     

    int j;

    int selfId = MultiProc_self();

    int clusterSize = MultiProc_getNumProcessors();

    int clusterBaseId = 0;

    Cache_inv(syncLine, sizeof(int)*8, Cache_Type_ALL, TRUE);

    for(i = 0; i < clusterSize; ) {

    if (i == (MultiProc_self() - clusterBaseId )) {

    for(j = 0; j < clusterSize; ++j) {

    if (j != i) {

    status = Ipc_attach(j);

    if (status < 0) {

    printf("Ipc_attach failed to attach to %d!\n", j);

    switch(status) {

    case Ipc_S_SUCCESS: printf("Ipc_S_SUCCESS: operation was successful\n"); break;

    case Ipc_S_ALREADYSETUP: printf("Ipc_S_ALREADYSETUP: already successfully called\n"); break;

    case Ipc_E_NOTREADY: printf("Ipc_E_NOTREADY: shared memory is not ready\n"); break;

    case Ipc_E_FAIL: printf("Ipc_E_FAIL: operation failed\n"); break;

    case Ipc_E_MEMORY: printf("Ipc_E_MEMORY: operation failed due to a memory error\n"); break;


    }

    }

    }

    }

    printf("Proc #%d attached to %d procs\n", MultiProc_self(), clusterSize);

    syncLine[i] = 1;

    Cache_wbInv(syncLine, sizeof(int)*8, Cache_Type_ALL, TRUE);

    ++i;

    }


    // If 1, increment loop control variable

    if (syncLine[i] == 1) {

    ++i;

    }

    Cache_inv(syncLine, sizeof(int)*8, Cache_Type_ALL, TRUE);

    }

    for(i = 0; i < clusterSize; ) {

    if (i == (selfId - clusterBaseId)) {

    syncLine[i] = 0;

    Cache_wbInv(syncLine, sizeof(int)*8, Cache_Type_ALL, TRUE);

    ++i;

    }


    // If 0, increment loop control variable

    if (syncLine[i] == 0) {

    ++i;

    }

    Cache_inv(syncLine, sizeof(int)*8, Cache_Type_ALL, TRUE);

    }

     

     

     


     

  • Hello again, Tim.

    I've tried both solutions you give me. The first one fails when I try to atach to the owner or shared memory (Ipc_attach(entry.ownerProcId)).

    I run the CORE0 just until before attach instruction tries to attach it to CORE1 and then I run the next cores so they try to attach with CORE0 but th function returns a -11. I've tried to let all cores run until any successful attachment but I never get any.

     

    About the second solution, I always get a -1 when trying to attach. What can be wrong with it if this code runs ok to you but doesn't to me?

  • Are you sure you called Ipc_start on all processors before trying to attach in both cases?  I'm guessing you didn't copy my code exactly if you quoted the error numbers rather than the error message.  If you copy my code, then the only thing that could possibly be wrong is the configuration of your SharedRegion, which is relatively straight-forward (entry=0, isValid=true, owner=0, sufficient size)

    Are you sure the "syncLine" array was correctly placed in shared memory (MSMCSRAM)? You probably would have noticed a warning from the compiler, but I'm just double-checking.

  • Hello,

    The code I'm using is exactly yours but I'm used to debug step by step and watch important variables (as status) and not only to watch printed strings. Any way, I know -1 is generic error and -11 is not ready error.

    By taking care on the execution order, I was calling Ipc_start in all cores before doing any other thing. And then I was calling attach to shared memory owner and I got the errors. 

    Now I've tried to make it in oposite order, first attach CORE0 to the others and then the others to it (I know that you adviced me to do in the right order and the documentation sustains what you told me). In this way I success when attaching cores 0,1 and 2 each other but fails with the rest. And I get success code when calling registerEvent and SendEvent. However, this functions don't generate the interrution in the destination core.

    I send you sorce and configuration code. Please take a look and tell me what can be wrong.

    Regards.8311.comunicacionCPUs.zip

     

  • Oh wow, you should have been getting an error long before that

    Ipc_start needs to be called after you call BIOS_start

    Actually, I guess you can call Ipc_start before starting BIOS, but you might need BIOS for some of the other things later. It's worth a try to see what calling BIOS affects.

     

     

    It should go as follows:

     

    Your source files needs to look like:

     

    main() {

    // This is the only thing to do in main

    BIOS_start();

    }


    void bios_task0(UArg arg0, UArg arg1) {

    // All of your actual code should go here

    Ipc_start()

    }

     

    And your configuration file should have:

     

     

    var Task        = xdc.useModule('ti.sysbios.knl.Task');

    var tsk0 = Task.create('&bios_task0');

    tsk0.instance.name = "tsk0";

     

  • Yes, that solved the problem. I've changed the program to fit in your structure and it works well.

    I've tried launching BIOS between the attaching and the register/sendEvent and it worked too.


    Just one remark, to help anyone who could have doubts and read this post, in order to make it work you have to attach shared memory owner before attaching the other ones but you have to keep always the attaching order (ascending order). So first core0 (the owner) attachs the others and then the others can attach it and the rest.

     

    Thanks Tim.

    Regards.

  • is it possible to do CORE1 as MASTER and CORE0 as SLAVE .

  • Yes, the cores are identical.