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_attach failure

Other Parts Discussed in Thread: SYSBIOS

Hi,

I am using KeyStone II to develop codec demo program. I run my demo program on core0 and core1, from core2 to core 7, I use a dummy program which only call Ipc_start and BIOS_start.

Now the plan is to call Ipc_attach(2) on core0, and Ipc_attach(1) on core1. It turns out to have such a message:

ti.sysbios.family.c64p.Hwi: line 190: E_alreadyDefined: Hwi already defined: intr# 5
xdc.runtime.Error.raise: terminating execution

Here is part of my cfg file:

SharedRegion.setEntryMeta(0,
    { base: SHAREDMEM,
      len:  SHAREDMEMSIZE,
      ownerProcId: 1,
      isValid: true,
      cacheEnable: true,
	  cacheLineSize: 128,
	  createHeap: true,      
      name: "SRGN0",
    });




/* Synchronize all processors (this will be done in Ipc_start) */
/* If the app only runs on one core, enabling this item causes Ipc_start() to block forever */
ti_sdo_ipc_Ipc.procSync = ti_sdo_ipc_Ipc.ProcSync_NONE;

  • Hi,

    You shouldn't call Ipc_attach for the same core. Are you're really calling Ipc_attach(1) from core1 or it's a typo?

    Also, are you following IPC manual instructions?

    From the manual:

    Ipc.ProcSync_NONE. If you use this option, Ipc_start() doesn’t synchronize any processors before
    setting up the objects needed by other modules. Use this option with caution. It is intended for use in
    cases where the application performs its own synchronization and you want to avoid a potential
    deadlock situation with the IPC synchronization.
    If you use the ProcSync_NONE option, Ipc_start() works exactly as it does with ProcSync_PAIR.
    However, in this case, Ipc_attach() does not synchronize with the remote processor. As with other
    ProcSync options, Ipc_attach() still sets up access to GateMP, SharedRegion, Notify, NameServer,
    and MessageQ transports, so your application must still call Ipc_attach() for each remote processor
    that will be accessed. Note that an Ipc_attach() call for a remote processor whose ID is less than the
    local processor’s ID must occur after the corresponding remote processor has called Ipc_attach() to
    the local processor. For example, processor #2 can call Ipc_attach(1) only after processor #1 has
    called Ipc_attach(2).

  • Hi Johannes,

    It is not a typo. It is what I intend to to.

    First of all, you should not assume the core0 has ID 0, and core1 has ID 1. From my previous snippert, if you have noticed, the ownerId is 1, since our cfg does following:

    var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc'); /* Note: MultiProc_self is set during VirtQueue_init based on DNUM. */
    MultiProc.setConfig(null, ["HOST", "CORE0", "CORE1", "CORE3","CORE4","CORE5","CORE6","CORE7"]);

    And the test program just like following:

    int main(int argc, Char * argv[])
    {
    	kdump_init();
    
    	System_printf("%s %s, cpu = %d\n", __FUNCTION__, __TIME__, MultiProc_self());
    
    	/* 
    	 * Assume the program runs on core0, it is chosen as the master core.
    	 * When the program runs on core1..7, it is a slave core.
    	 */
    
        DBGPRINTF("[%d][%d]kdump_init success!\n", DNUM, MultiProc_self());
    
    
    	if (startup_IPC_init())
    	{
    		return -1;
    	}
        #if 1
        if ( MultiProc_self() == 1 )
        {
            int status = -1;
    
            do
            {
                DBGPRINTF("Try attach 2:%d\n", status);
                
                status = Ipc_attach(2);
                if (status < 0)
                {
                    Task_sleep(1);
                }
            } while (status < 0);
            DBGPRINTF("Attach 2:%d\n", status);
        }
        else
        {
            int status = -1;
    
            do
            {
                DBGPRINTF("Try attach 1:%d\n", status);
    
                status = Ipc_attach(1);
                if (status < 0)
                {
                    Task_sleep(1);
                }
            } while (status < 0);
            DBGPRINTF("Attach 1:%d\n", status);
        }
        #endif
    
        while (1)
        {
            DBGPRINTF("OK");
            Task_sleep(1);
        }
    
        BIOS_start();
    
        return (0);
    }

    8475.app.cfg

  • Hank,

    On a slave core, Ipc_start() should be called only if there is a need to initialize the SharedRegion module and/or to perform slave-to-slave IPC communication. In other words, if communication strictly happens between host and slave(s), and SharedRegions are not defined, then there is no need to call Ipc_start() on the slave. In fact, if SR0 (SharedRegion 0) is not defined on a slave core, do not call Ipc_start() on that slave core. The call would fail when it tries to look for SR0.


    On the host core, Ipc_start() always needs to be called to initialize IPC. Given host-side IPC code does not use SharedRegion, the function is strictly used to perform initialization for other IPC modules.

    Ipc.procSync = Ipc.ProcSync_ALL;

    Ipc.ProcSync_ALL: If you use this option, the Ipc_start() API automatically attaches to and synchronizes all remote processors. If you use this option, your application should never call Ipc_attach(). Use this option if all IPC processors on a device start up at the same time and connections should be established between every possible pair of processors.


    See the below E2E discussion and also refer the Inter-Processor Communication User’s Guide

    http://e2e.ti.com/support/embedded/tirtos/f/355/t/159905.aspx
    http://e2e.ti.com/support/embedded/tirtos/f/355/t/107028.aspx

  • We are using IPC to sync all cores, and SR0 is defined in cfg. In deed, we are going to use it with Name Server and barriers. If we turn Ipc_start off, then Name Server will not perform the right lookup at slave core.