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.

Undefined references to ipc_gates and ipc_heaps, redux

Other Parts Discussed in Thread: SYSBIOS

I figured out how to get the notify_multicore example running with a lot of help from the previous thread under this name.  Now I'd like to integrate the IPC framework into my application.  However, I've been using newer XDC and SYSBIOS versions, with loggingSetup and a couple other components.  The old XDC/Bios don't seem to work with that, for various reasons.  So why does IPC have link time errors with newer XDC/BIOS versions?  I'm trying to use

XDC   3.30.5.6

SYSBIOS 6.41.0.6

The application builds fine until I try and include IPC. Then I get link errors on the following things:

Undefined reference to 'ti_sdo_ipc_gates_GatePeterson_query__E'         
Undefined reference to 'ti_sdo_ipc_gates_GateMPSupportNull_query__E'     
Undefined reference to 'ti_sdo_ipc_heaps_HeapMemMP_isBlocking__E'         
Undefined reference to 'ti_sdo_ipc_gates_GateHWSem_query__E'    

The defines/typedefs and source code for these are in (for example) C:\ti\ipc_3_22_02_11\packages\ti\sdo\ipc\gates. 

The linker.cmd that is generated says it is using:

-l"C:\ti\ipc_3_22_02_11\packages\ti\sdo\ipc\lib\ipc\instrumented\ipc.ae66"
-l"C:\ti\ipc_3_22_02_11\packages\ti\sdo\utils\lib\utils\instrumented\utils.ae66"

Shouldn't those be in one of these libraries?

Thanks for any direction on this

Mike

  • I have managed to get the application to build with an updated version of IPC. The versions that work are
    XDC 3.30.5.60
    IPC 3.30.2.13
    SYSBIOS 6.41.0.26

    Now there are runtime problems, apparently with CIO. I'm running the notify_example on 8 cores, each core should just round robin between the cores and print to the console two messages for each pass, then notify the next core, looping thru all 8 cores 10 times. This worked with older versions of the tools. Now the errors are variable, but typically look like this:

    .......
    Instruction fetch exception
    ti.sysbios.family.c64p.Exception: line 256: E_exceptionMax: pc = 0x00000000, sp = 0x800317d8.
    xdc.runtime.Error.raise: terminating execution
    [C66xx_1] Invalid CIO command (14) in the CIO buffer at address (0x80037600) was not recognized. Please check the device and program memory maps.
    c id = 0
    main: MultiProc name = CORE0
    ti.sdo.ipc.Notify: line 380: assertion failure: A_internal: An internal error has occurred
    xdc.runtime.Error.raise: terminating execution

    Any hints on where to look? Thanks in advance.
    Mike
  • I've discovered that the application fails at Ipc_start() for any core other than 0.  I've pared the application down to 3 cores. Core 0 seems to get past Ipc_start, Core 1 throws an error and exits, and Core 2 seems to hang, usually in an Ipc_sync call. It is a pretty simple example, I've attached the code and .cfg below. Bios versions are described above.(Note this all works with older versions of the tools)  Can anybody tell what I'm doing wrong?

    The console error is:

    Exception at 0xc00068c
    EFR=0x2 NRP=0xc00068c
    Internal exception: IERR=0x8
    Opcode exception
    ti.sysbios.family.c64p.Exception: line 256: E_exceptionMax: pc = 0x0c00068c, sp = 0x00800e30.
    xdc.runtime.Error.raise: terminating execution

    The Debug session shows:  (Core 0 is at a point where it is waiting for the other cores, it started normally, core 1 aborted, and core 2 is hung)

    Group 1     
        Spectrum Digital XDSPRO USB Emulator/C66xx_0 (Suspended)    
            Notify_sendEvent() 0x8000942E  (reason unknown)    
        Spectrum Digital XDSPRO USB Emulator/C66xx_1 (Suspended)    
            abort() at exit.c:109 0x80023100  (abort does not contain frame information)    
        Spectrum Digital XDSPRO USB Emulator/C66xx_2 (Suspended)    
            ti_sdo_ipc_Ipc_procSyncStart__I() 0x8000D7AE  (reason unknown)    

    Code:

    /* 
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * */
    /*
     *  ======== notify_multicore.c ========
     *  Single-image version of Notify example
     *
     *  See notify_multicore.k file for expected output.
     */
    
    #include <xdc/std.h>
    
    /*  -----------------------------------XDC.RUNTIME module Headers    */
    #include <xdc/runtime/System.h>
    
    /*  ----------------------------------- IPC module Headers           */
    #include <ti/ipc/MultiProc.h>
    #include <ti/ipc/Notify.h>
    #include <ti/ipc/Ipc.h>
    /*  ----------------------------------- BIOS6 module Headers         */
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/BIOS.h>
    
    /*  ----------------------------------- To get globals from .cfg Header */
    #include <xdc/cfg/global.h>
    
    //#include <xdc/runtime/Log.h>
    
    #define INTERRUPT_LINE  0
    
                                     /* Notify event number that the app uses */
    #define EVENTID         10
    
                                     /* Number of times to run the loop */
    #define NUMLOOPS        2
    
    UInt32 seq = 0;
    UInt16 recvProcId;
    
    UInt16 srcProc, dstProc;
    
    /* ------------------------------------------------------------------------------------------------
     *  ======== cbFxn ========
     *  This function was registered with Notify. It is called when any event is
     *  sent to this processor.
     */
    Void cbFxn(UInt16 procId, UInt16 lineId,
               UInt32 eventId, UArg arg, UInt32 payload)
    {
                                  /* The payload is a sequence number. */
        recvProcId = procId;
        seq = payload;
        Semaphore_post(semHandle);
    }
    
    /* ------------------------------------------------------------------------------------------------
     *  ======== tsk0_func ========
     *  Sends an event to the next processor then pends on a semaphore.
     *  The semaphore is posted by the callback function.
     */
    Void tsk0_func(UArg arg0, UArg arg1)
    {
        Int i = 1;
        Int status;
        
        if (MultiProc_self() == 0)
        {
            while (i <= NUMLOOPS)
            {
                /* Send an event to the next processor */
                status = Notify_sendEvent(dstProc, INTERRUPT_LINE, EVENTID, i, TRUE);
    
                /* Continue until remote side is up */
                if (status < 0)
                {
                    continue;
                }
    
                System_printf("tsk1_func: Sent request #%d to %s\n",
                                                        seq,   MultiProc_getName(dstProc));
    
                                           /* Wait to be released by the cbFxn posting the semaphore */
                Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
    
                System_printf("tsk1_func: Received request #%d from %s\n",
                                                             seq,     MultiProc_getName(recvProcId));
    
                i++;              /* increment for next iteration */
            }
        }
        else
        {
            while (seq < NUMLOOPS)
            {
                                     /* wait forever on a semaphore, semaphore is posted in callback */
                Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
    
                System_printf("tsk1_func: Received request #%d from %s\n",
                                                             seq,     MultiProc_getName(recvProcId));
    
                do
                {                 /* Send an event to the next processor. Since the next processor
                                   * may not be initialized yet, spin here until it is successful.
                                   * Wonder if there is a better way to check for ready?         */
                   status = Notify_sendEvent(dstProc, INTERRUPT_LINE, EVENTID, seq, TRUE);
    
                } while(  (status == Notify_E_NOTINITIALIZED  )
                        ||(status == Notify_E_EVTNOTREGISTERED)  );
    
                if (status < 0)
                {
                    System_abort("sendEvent failed\n");
                }
    
                System_printf("tsk1_func: Sent request #%d to %s\n",
                                                         seq,  MultiProc_getName(dstProc));
            }
        }
    
        System_printf("Test completed\n");
        BIOS_exit(0);
    }
    
    /* ------------------------------------------------------------------------------------------------
     *  ======== main ========
     *  Synchronizes all processors (in Ipc_start), calls BIOS_start, and registers 
     *  for an incoming event
     *
     */
    Int main(Int argc, Char* argv[])
    {
        Int status;
        UInt numProcs = MultiProc_getNumProcessors();
                                /*  Determine which processors Notify will communicate with based on the
                                 *  local MultiProc id.  Also, create a processor-specific Task.
                                 */
        srcProc = ((MultiProc_self() - 1 + numProcs) % numProcs);
        dstProc = ((MultiProc_self() + 1           ) % numProcs);
    
        System_printf("main: MultiProc id = %d\n", MultiProc_self());
        System_printf("main: MultiProc name = %s\n", 
                                               MultiProc_getName(MultiProc_self()));
    
                                /*  Ipc_start() calls Ipc_attach() to synchronize all remote processors
                                 *  because 'Ipc.procSync' is set to 'Ipc.ProcSync_ALL' in *.cfg
                                 */
        status = Ipc_start();
        if (status < 0)
        {
            System_abort("Ipc_start failed\n");
        }
                                /*  Register call back with Notify. It will be called when the processor
                                 *  with id = srcProc sends event number EVENTID to this processor.
                                 */
        status = Notify_registerEvent(srcProc,
                                        INTERRUPT_LINE,
                                        EVENTID,
                                        (Notify_FnNotifyCbck)cbFxn,
                                        NULL                          );
        if (status < 0)
        {
            System_abort("Notify_registerEvent failed\n");
        }
    
        BIOS_start();
        
        return (0);
    }
    
    

    .cfg file:

    /* 
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * */
     
    var MultiProc    = xdc.useModule('ti.sdo.utils.MultiProc');
    var System       = xdc.useModule('xdc.runtime.System');
    var SysMin       = xdc.useModule('xdc.runtime.SysMin');
                                                        /* Modules explicitly used in the application */
    var Notify       = xdc.useModule('ti.sdo.ipc.Notify');
    var Ipc          = xdc.useModule('ti.sdo.ipc.Ipc');
    var BIOS         = xdc.useModule('ti.sysbios.BIOS');
    var Task         = xdc.useModule('ti.sysbios.knl.Task');
    var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
    var Semaphore    = xdc.useModule('ti.sysbios.knl.Semaphore');
    
    BIOS.heapSize   = 0x8000;
    
    System.SupportProxy = SysMin;
    SysMin.bufSize = 2048;
    
    System.maxAtexitHandlers = 4;
    
    						/*  Get the list of names that the build device supports.
    						 *  I.e. ["CORE0", "CORE1", "CORE2" ... ]
    						 */
    var nameList = MultiProc.getDeviceProcNames();
    MultiProc.numProcessors = 3;
    nameList = ["CORE0","CORE1","CORE2"];
    
    
    						/*  Since this is a single-image example, we don't (at build-time) which 
    						 *  processor we're building for.  We therefore supply 'null' as the local 
    						 *  procName and use MultiProc_setLocalId to set the procId at runtime.
    						 */
    MultiProc.setConfig(null, nameList);
    
    
    var tsk0 = Task.create('&tsk0_func');
    tsk0.instance.name = "tsk0";
    
                                        /* To avoid wasting shared memory for MessageQ transports */
    for (var i = 0; i < MultiProc.numProcessors; i++) 
    {
      Ipc.setEntryMeta(
          {
            remoteProcId: i,
            setupMessageQ: false,
          }                              );
    }
    
                                       /* Synchronize all processors (this will be done in Ipc_start) */
    Ipc.procSync = Ipc.ProcSync_ALL;
    
    //SharedRegion.numEntries = 2;
    //SharedRegion.translate = false;
    
                                        /* Shared Memory base address and length */
    var SHAREDMSMC          = 0x0C000000;
    var SHAREDMSMCSIZE      = 0x00100000;
    
    									/*  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.
    									 */ 
    SharedRegion.setEntryMeta(0,
    						    { base: SHAREDMSMC, 
    						      len:  SHAREDMSMCSIZE,
    						      ownerProcId: 0,
    						      isValid: true,
    						      name: "MSMC_RAM",
    						    }                             );
    						    
    //var SHAREDDDR3          = 0x80000000;
    //var SHAREDDDR3SIZE      = 0x10000000;
    						    
    //SharedRegion.setEntryMeta(1,
    //                            { base: SHAREDDDR3, 
    //                              len:  SHAREDDDR3SIZE,
    //                              ownerProcId: 0,
    //                              isValid: true,
    //                              createHeap: false,
    //                              name: "DDR3_RAM",
    //                            }                             );
                                
    
                                         /* Create a semaphore with count 0                     */
    Program.global.semHandle = Semaphore.create(0);
    

  • I've discovered that somewhere between the old tools I was using and the new ones, the default memory for all the sections changed from L2SRAM (not shared) to external DDR3 (shared). This means that variables defined at file level scope are now visible to all cores. One of these variables is used in the call to Notify_registerEvent() which is failing, likely because the variable needs to be local to each core.

    Where is the default memory for all the linker sections set? In the platform package? I think the old and new tools have them in different places. If so, how do I change it? I've seen how it can be set manually in the .cfg file with Program.sectmap[.text] = "L2SRAM" for example, but one doesn't necessarily know all the sections generated by sysbios/xdc/ipc/targets, etc. They all moved from unshared to shared memory.

    Thanks for any advice.
    Mike
  • Hi Mike,
    Please be patient for a reply. I don't know the answers to your questions and have asked a team-member to help out.
    Regards,- Rob
  • Hi Rob,

    Ok, no problem. 

    Additional information:  it turns out the CIO buffers in the .cio section (don't know where that is created) were residing in shared external DDR3 also.  The application would crash with CIO buffer corruption message, probably because cores were stepping on each others buffers when printf'ing.

    As a test I have added Program.sectmap directives to my .cfg file for every section I found in the linker map file remapping them to L2SRAM, which is local to each core.  This has allowed the application to run correctly with the newer tools.  For the record, the versions are:

    XDC       3.30.5.60

    IPC         3.30.2.13

    SYSBIOS  6.41.0.26

    I still look forward to an answer to the previous question. I suspect more than just CIO and IPC are broken with memory defaulting to shared areas. It is also possible I missed the documentation on this.

    Thanks much            Mike

  • Hi Mike,

    What platform are you using ?

    There are three types of memory sections in each platform, namely "Code Memory", "Data Memory" and "Stack Memory". These can individually be set to either L2SRAM or DDR3. Setting "Code Memory" to L2SRAM will for instance ensure that all sections that are placed in code memory will go to L2SRAM. Similarly setting "Data Memory" to L2SRAM will ensure that all data sections are placed in L2SRAM.

    If the platform you are using is setting these memory sections to DDR3, then you can create a custom platform (using platform wizard) that sets them to L2SRAM. There is another way of overriding the platform's defaults but I think creating your own custom platform is easier.

    If you want finer grain control then as you already know you can use "Program.sectMap". You can determine all the section names from the app's map file.

    Best,

    Ashish

  • Hi Ashish,

    I am using an EVM6678 eval module and select the ti.platforms.evm6678 on the RTSC tab in CCSv6.  Originally I did not do anything to set where the sections mapped to in memory.  Somewhere between XDC 3.2x/Bios 6.3x and XDC 3.3x/Bios 6.4x, all the sections changed from L2SRAM to DDR. This caused a significant amount of effort until I figured out what was going on. Even CIO from multiple cores was broken.

    Since I am quite new to the whole XDC/BIOS environment, creating a new platform has seemed like a daunting task. It is much easier to learn from existing code by modifying it.  It seems to me I would have to work through a lot of issues to get back to where I am, which is in the middle of trying to develop an algorithm and evaluate if the timing is going to work out.  I understand that eventually with a custom board I may have to do that, but figuring out how to support all the hardware on the EVM (DDR3 timing parameters, i2c, spi, emif, more stuff ?? ) with a custom platform was not in the plan right now.  Thus I was interested to know where section mapping is specified in the tools.

    Is there a good document describing all the platform creation steps?

    Mike

  • Hi Mike,

    As far as I can tell, we did not change the default memory segment where sections are placed from L2SRAM to DDR for evm6678 platform. Can you tell me what is the name of the platform you are using and which version of XDC/Tools were you using before ? I believe you are using SYS/BIOS 6.41.00.xx now right ? I can check if the memory segment assignment changed.

    Custom platforms can be created using a tool called "Platform wizard". Here's the link to a tutorial showing how to do this: rtsc.eclipse.org/.../Demo_of_the_RTSC_Platform_Wizard_in_CCSv4

    The tutorial was made using CCSv4 but most steps are still relevant. On CCSv6, please note that the "Tools" menu item is not visible when CCS is in "CCS Edit" mode. You need to switch to "CCS Debug" mode to view it.

    Best,
    Ashish

  • Hi Ashish,

    Thanks for the info, I'll check out the video.

    Using  ti.platforms.evm6678

    When I used

    XDCTools    3.25.3.72

    IPC              1.24.3.32

    SYSBIOS     6.37.3.30

    all sections were mapped to L2SRAM

    When I used

    XDCTools    3.30.5.60

    IPC              3.30.2.13

    SYSBIOS     6.41.0.26

    all sections were mapped to DDR3

    The .cfg was the same in both cases, posted above on 20 Jan.  

    I believe that between those two sets of tools the location of the platforms changed from XDC to BIOS, right? 

    Mike

  • Hi Mike,

    I looked at the evm6678 platform in SYS/BIOS 6.41.00.26 and see the L2SRAM is used as the default memory segment. So, I am not sure how it changed for you.

    Mike Stich said:

    I believe that between those two sets of tools the location of the platforms changed from XDC to BIOS, right? 

    That is correct. Starting with SYS/BIOS 6.40+, the targets and platforms are shipped with SYS/BIOS product.

    Best,

    Ashish