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.

Concerto boot with shared memory

Other Parts Discussed in Thread: SYSBIOS

Dear support,
We work with concerto F28M35H52C1, MCU SDK 1.0.0.68, XDCTools 3.24.60.

Our configuration include shared memory using. Program work fine from CCS,
We have problem with shared memory after starting program from the flash without CCS using.
IPC doesn't work in this case - it seems that
MessageQ_get(messageQ, &msg, MessageQ_FOREVER); and MessageQ_get(messageQ_2, &msg, MessageQ_FOREVER);
don't returned with new message at all.

Without shared memory using we don't have this problem at all.

Per Judan recomendation (http://e2e.ti.com/support/embedded/bios/f/355/p/239671/854486.aspx#854486) we added M3_Ram_Init() in the main() before BIOS_start(), but it didn't help.

Could you help us to resolve the problem.

Attached is our jel files, cfg and map.7776.boot from mem.rar

Thanks, Sabina 

  • Sabina,

    When you run standalone without CCS have you verified that both cores are running?

    I suspect you may be forgetting to boot the C28 before trying to perform IPC communication.

    Regards,

    Trey

  • Hi Trey,

    Bith cores are running if i set:
    heapBuf0Params.sectionName = null; instead of heapBuf0Params.sectionName = "IPC_BUFFERS_SECTION_LPU:
    heapBuf1Params.sectionName = null; instead of heapBuf1Params.sectionName = "IPC_BUFFERS_SECTION_PMCU:

    in this case IPC connection work after booting

    Thanks, Sabina

  • Hi Trey,

    Could you please help us to fix this problem.  We have to fix this issue ASAP.

    Thanks,Sabina

  • Sabina,

    Sorry for the slow reply, I was distracted by other pressing issues.

    I think I need a little more information to be able to diagnose this.  Can you make a new target configuration and remove any GEL files associated with it?  I'd like you to try to run your code standalone, let the failure occur, and then connect to the board using the target configuration without GEL files.  This will allow us to view the state of the device after the failure occurs.  Then you can add the symbols of your program to see where it is at in the source code in each core.  We need to isolate why this IPC command is failing, and I think we can do so by working backward from where the code hangs.

    Let me know if you have questions on how to do this.

    Trey

  • Hi Trey,

    I don't know how to do it. Could you please explain me more ...

    Thanks,Sabina 

  • Go to File -> New -> Target Configuration.  Name it as you see fit. Select the appropriate emulator and device.  Near the bottom of the window click on the advanced tab.  Expand the tree on the left half of the pane till you get to the bottom two levels of the hierarchy.  Click on Cortex_M3_0 and remove the initialization script on the right (simply delete the path and filename).  Do the same for C28xx_0.  Save the configuration.

    Load your application as you normally would to flash using your normal target configuration (NOT the one we just created). Disconnect it from CCS and boot the device in whatever way causes the problem to occur.  After the problem occurs launch the new special target configuration that we just made and connect to each core. Click on Run -> Load -> Add Symbols and add the symbols for both the C28 and M3 application.  The cores should be halted and you should be able to see in the source code exactly where they are stuck at.  Please relay that information to me.

  • Where to find the Symbols file? Is it *.out or another extension?

  • Sabina Greenberg101872 said:

    Where to find the Symbols file? Is it *.out or another extension?

    Yes - symbols are included in the .out file.

    -Lori

  • Hi, I can not load symbol files. get the following errors:

    Cortex_M3_0: Breakpoint Manager: Retrying with a AET breakpoint
    Cortex_M3_0: Trouble Setting Breakpoint with the Action "Terminate Program Execution" at 0x21cd08: (Error -1066 @ 0x21CD08) Unable to set requested breakpoint in memory. Verify that the breakpoint address is in writable memory. (Emulation package 5.0.569.0)
    C28xx_0: Breakpoint Manager: Retrying with a AET breakpoint
    C28xx_0: Trouble Setting Breakpoint with the Action "Process CIO" at 0x10a0f2: (Error -1066 @ 0x10A0F2) Unable to set requested breakpoint in memory. Verify that the breakpoint address is in writable memory. (Emulation package 5.0.569.0) i can not load the symbol file. get the following:

    I don't have any breakpoints

  • Sabina Greenberg101872 said:

    Hi, I can not load symbol files. get the following errors:

    Cortex_M3_0: Breakpoint Manager: Retrying with a AET breakpoint
    Cortex_M3_0: Trouble Setting Breakpoint with the Action "Terminate Program Execution" at 0x21cd08: (Error -1066 @ 0x21CD08) Unable to set requested breakpoint in memory. Verify that the breakpoint address is in writable memory. (Emulation package 5.0.569.0)
    C28xx_0: Breakpoint Manager: Retrying with a AET breakpoint
    C28xx_0: Trouble Setting Breakpoint with the Action "Process CIO" at 0x10a0f2: (Error -1066 @ 0x10A0F2) Unable to set requested breakpoint in memory. Verify that the breakpoint address is in writable memory. (Emulation package 5.0.569.0) i can not load the symbol file. get the following:

    I don't have any breakpoints

    Sabina,

    These are breakpoints that are automatically set by CCS.  They are required for the C I/O functions (I/O functions like printf, puts, etc).  CCS also wants to put a breakpoint at the end of the program by default. 

    You can change this behavior in the debugger options for each of the CPUs but note that C I/O won't work without these breakpoints.   The 28x only has 2 hardware breakpoints so C I/O along with debug becomes difficult in flash.

    From the screenshot you supplied, it looks like the M3 symbols loaded, but not the 28x. 

    -Lori

  • Sabina,

    We believe we've found the issue.  The IpcManager gives access to the shared RAMs to the C28 AFTER Bios has booted the C28.  If your application is accessing these RAMs early on, you may do so before you have ownership and cause a fault.

    To confirm this we'd like you to add a while loop before you touch the shared RAMs on the C28.  In your while loop check the CSxMSEL register and wait for its value to become 0x0F.  After it does you can fall through and access the shared RAM.

    Please let us know if this fixes your issue,

    Best Regards,

    Trey German

  • Hi Trey,

    I added the following :

    #define S0_3_ACCESS  0x0000000F
        while ((RAMRegs.CSxMSEL.all & S0_3_ACCESS) != S0_3_ACCESS)
         {
         }

    before ipc using - but it didn't help.
    Application is ready for shared memory using, but doesn't want to work with it.

    Thanks,Sabina

     

     

  • Sabina,

    Where exactly did you add that line in your code?  Before or after Bios_Start()?

    Trey

  • We did two different tests:

    1. Add "while()"   Before Bios_start()
    2. Add "while()"   in the IPC task (before IPC_init() )

    In both cases we get the same result - application doesn't work

  • Ok, Do you have any communications interface available on the C28?  Could you hook up the SCI and add some debug statements to see how far in the C28 boot your application is getting?

    From previous comments it sounds like the M3 is still running in standalone boots, correct?  Its just the C28 that fails due to something related to IPC....just trying to make sure I fully understand the big picture.

    Trey

  • We have the following scenario:

    1. Start Application  - both leds blinks (by timers)- m3 and c28 running
    2. Send data from c28 to m3 - both leds blinks - m3 and c28 still running
    3. Send data from M3 to C28  - only one led blink (m3 running, c28 - crashes). we send it via PMCU_TYPE_M3_C28_Msg  (HEAPID_2)
  • Ahhhh...so your C28 application does actually boot standalone?!?

    Let me consult some more with our BootROM expert.

    Trey

  • Sabina,

    Just to confirm, the application runs correctly with shared RAMs and the debugger connected but does not function correctly in a standalone boot situation?

    Trey

  • yes,

    the application runs correctly with shared RAMs and the debugger connected but does not function correctly in a standalone boot situation

    Sabina

  • Sabina,

    can you tell what C28x is doing on receving the IPC command after which it stops working? I understand that you are not able to reproduce the issue with debugger connected.

    also can you brief the usage of IPC and shared memory in application? how they are being used...master puts data in some shared RAM and sends an IPC to C28x, now C28x received the IPC and reads the shared memory and responds? is C28x trying to write to shared memory that is owned by master?

    can you also monitor XRSn pin when running in stand-alone, because C28x not blinking LED but master alone bliking LED doesn't add up. there is some symptom we are missing here, probably the system is getting reset.

    Also after the error happens in stand alone, try connecting CCS to the device (after removing the GEL scripts from target configuration, this will allow us to preserve the system state when connected) and load symbols for your application on both cores, don't do a debug reset and see when the PC is in each core.

    I strongly suspect that the application is violating something and the device ends up being reset, one more thing you can try is change the SxRAM usage configuration from what you have, and try it out. It might not solve the problem but can throw some light into what is going on.

    Best Regards

    Santosh

     

  • Hi Santosh,

    >>can you tell what C28x is doing on receving the IPC command after which it stops working?|
    It stop working during calling myRcvMessage2 = IPC_recMsgQ2 ();

    PMCU_TYPE_M3_C28_Msg * IPC_recMsgQ2 (void)
    {
     Int              status;
     MessageQ_Msg     msg  = NULL;
           status = MessageQ_get(messageQ_2, &msg, MessageQ_FOREVER);
        if (status < 0) {
            System_printf("PMCU_TYPE_M3_C28_Msg/This should not happen since timeout is forever\n");
        }
        return ((PMCU_TYPE_M3_C28_Msg *)msg);
    }

    if i comment MessageQ_get(messageQ_2, &msg, MessageQ_FOREVER) calling the program work, else it stay in IPC-task that has the higest priority and block all other tasks.

    >> I understand that you are not able to reproduce the issue with debugger connected.>
    Yes,

    >>also can you brief the usage of IPC and shared memory in application? how they are being used...master puts data in some shared RAM and sends an IPC to C28x, now C28x >>received the IPC and reads the shared memory and responds? is C28x trying to write to shared memory that is owned by master?

    We have the following scenario:

    1. Start Application  - both leds blinks (by timers)- m3 and c28 running
    2. Send data from c28 to m3 via IPC  - both leds blinks - m3 and c28 still running
    3. Send data from M3 to C28  via IPC - only one led blink (m3 running, c28 - crashes). we send it via PMCU_TYPE_M3_C28_Msg  (HEAPID_2)

     

    >>Also after the error happens in stand alone, try connecting CCS to the device (after removing the GEL scripts from target configuration, this will allow us to preserve the system state >>when connected) and load symbols for your application on both cores, don't do a debug reset and see when the PC is in each core.

     

    I sent you our cfg files. maybe we miss something in our configuration?
    5164.CFG.zip

    could you please look into it?
    for m3 we have:

    void IPC_init_1 (void)
    {
     Int  status;
        UInt numProcs = MultiProc_getNumProcessors(); // Number of processors, in the Concerto case = 2

        // Generate queue names based on own proc ID and total number of procs
        System_sprintf(localQueueName, "%s_queue",
                MultiProc_getName(MultiProc_self()));
        System_sprintf(remoteQueueName, "%s_queue",
                MultiProc_getName(1 - MultiProc_self()));

        // Determine which processors Notify will communicate with based on the local MultiProc id.
        srcProc = ((MultiProc_self() - 1 + numProcs) % numProcs);
        dstProc = ((MultiProc_self() + 1) % numProcs);

        // 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)NotifycallBackFxn, NULL);
        if (status < 0) {
            System_abort("Notify_registerEvent failed\n");
        }

        // Register default system heap with MessageQ
        MessageQ_registerHeap((IHeap_Handle )(MsgQHeapBuf0), HEAPID);

        // Create the local message queue
        messageQ = MessageQ_create(localQueueName, NULL);
        if (messageQ == NULL) {
            System_abort("MessageQ1_create failed\n" );
        }

        // Open the remote message queue. Spin until it is ready.
        do {
            status = MessageQ_open(remoteQueueName, &remoteQueueId);
            // Sleep for 1 clock tick to avoid inundating remote processor
            // with interrupts if open failed
            if (status < 0) {
                Task_sleep(1);
            }
        } while (status < 0);

    }

    /*******************************************************************************
    Function Name : IPC_init_2
    Description :   This function init's the IPC data, for messageQ2
    *******************************************************************************/
    void IPC_init_2 (void)
    {
     Int  status;
        UInt numProcs = MultiProc_getNumProcessors(); // Number of processors, in the Concerto case = 2

        // Generate queue names based on own proc ID and total number of procs
        System_sprintf(localQueueName_tsk2, "%s2_queue",
                MultiProc_getName(MultiProc_self()));
        System_sprintf(remoteQueueName_tsk2, "%s2_queue",
                MultiProc_getName(1 - MultiProc_self()));


        // Register default system heap with MessageQ
        MessageQ_registerHeap((IHeap_Handle )(PMCUMsgQHeapBuf1), HEAPID_2);

        // Create the local message queue
        messageQ_2 = MessageQ_create(localQueueName_tsk2, NULL);
        if (messageQ_2 == NULL) {
            System_abort("MessageQ2_create failed\n" );
        }

        // Open the remote message queue. Spin until it is ready.
        do {
            status = MessageQ_open(remoteQueueName_tsk2, &remoteQueueId_2);
            // Sleep for 1 clock tick to avoid inundating remote processor
            // with interrupts if open failed
            if (status < 0) {
                Task_sleep(1);
            }
        } while (status < 0);

    }

     and for c28:

    void IPC_init_1(void)
    {
     Int  status;
        UInt numProcs = MultiProc_getNumProcessors(); // Number of processors, in the Concerto case = 2

        // Generate queue names based on own proc ID and total number of procs
        System_sprintf(localQueueName, "%s_queue",
                MultiProc_getName(MultiProc_self()));
        System_sprintf(remoteQueueName, "%s_queue",
                MultiProc_getName(1 - MultiProc_self()));

        // Determine which processors Notify will communicate with based on the local MultiProc id.
        srcProc = ((MultiProc_self() - 1 + numProcs) % numProcs);
        dstProc = ((MultiProc_self() + 1) % numProcs);

        // 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)NotifycallBackFxn, NULL);
        if (status < 0) {
            System_abort("Notify_registerEvent failed\n");
        }

        status = Notify_registerEvent(srcProc, INTERRUPT_LINE, EVENTID_ERR,
                                          (Notify_FnNotifyCbck)NotifycallBackFxn_ERR, NULL);
     if (status < 0) {
      System_abort("Notify_registerEvent failed\n");
     }

     status = Notify_registerEvent(srcProc, INTERRUPT_LINE, EVENTID_IPC,
                                           (Notify_FnNotifyCbck)NotifycallBackFxn_IPC, NULL);
      if (status < 0) {
       System_abort("Notify_registerEvent failed\n");
      }


        // Register default system heap with MessageQ
        MessageQ_registerHeap((IHeap_Handle)(MsgQHeapBuf0),HEAPID);

        // Create the local message queue
        messageQ = MessageQ_create(localQueueName, NULL);
        if (messageQ == NULL) {
            System_abort("MessageQ_create failed\n" );
        }

        // Open the remote message queue. Spin until it is ready.
        do {
            status = MessageQ_open(remoteQueueName, &remoteQueueId);
            // Sleep for 1 clock tick to avoid inundating remote processor
            // with interrupts if open failed
            if (status < 0) {
                Task_sleep(1);
            }
        } while (status < 0);

    }

    /*******************************************************************************
    Function Name : IPC_init_2
    Description :   This function init's the IPC data, for messageQ2
    *******************************************************************************/
    void IPC_init_2 (void)
    {
     Int  status;
        UInt numProcs = MultiProc_getNumProcessors(); // Number of processors, in the Concerto case = 2

        // Generate queue names based on own proc ID and total number of procs
        System_sprintf(localQueueName_tsk2, "%s2_queue",
                MultiProc_getName(MultiProc_self()));
        System_sprintf(remoteQueueName_tsk2, "%s2_queue",
                MultiProc_getName(1 - MultiProc_self()));


        // Register default system heap with MessageQ
        MessageQ_registerHeap((IHeap_Handle)(PMCUMsgQHeapBuf1), HEAPID_2);

        // Create the local message queue
        messageQ_2 = MessageQ_create(localQueueName_tsk2, NULL);
        if (messageQ_2 == NULL) {
            System_abort("MessageQ2_create failed\n" );
        }

        // Open the remote message queue. Spin until it is ready.
        do {
            status = MessageQ_open(remoteQueueName_tsk2, &remoteQueueId_2);
            // Sleep for 1 clock tick to avoid inundating remote processor
            // with interrupts if open failed
            if (status < 0) {
                Task_sleep(1);
            }
        } while (status < 0);

    }

    Thanks,Sabina

  • Hi Santosh,

    I put all our IPC stuff in the test project. 0181.MMCU_Emb test shram.rar.

    May be it is more easy for you look into our code and configuration via this project.

    this project is based on messageQ example of TI(for C28 and M3)

    Thanks.Sabina

  • sabina,

    thaks a lot. Give us some time to digest the details and look into the project you sent. One of us (Trey or me) will try to reproduce the issue and dig into it further to see if it is a SYSBIOS issue or something else.

     

    Best Regards

    Santosh

     

  • Hi Santosh,

    Do you have something for us?

    Thanks,Sabina

  • Sabina,

    I've got the project imported and I'm trying to build.  The M3 project builds fine, but the C28 project has a problem.  It would appear that the PMCU_IPCReciveTask doesn't have a function defined for it.  What function should this task call?

    Trey

  • it should be Tsk_IPCMsgRecieveFromPMCU() function

    pls let me know it it is ok

  • Hi  Trey,

    Did you have a time to look into the example that i sent you?  if yes may be you found the source of our problems with shared memory?

    Thanks,Sabina

  • Sabina,

    We actually had a 2 hr call this morning with 4 experts and we still were unable to find the exact source of the problems you're seeing.  That said we did notice a few things that we'd like you to take a look at:

    1. The M3 CFG file was setup NOT to boot the C28.  This is incorrect.  The M3 needs to boot up the C28.
    2. Increasing the number of blocks allocated to the HeapBufs appears to make the IPC more robust.  We were getting errors, but they stopped when we bumped up the buffers to 10 blocks.
    3. You are using the SysStd package which is resource intensive.  Try replacing SysStd with SysMin in the CFG files.

    Can you try making these changes and seeing if behavior improves on your end.

    Trey

  • Sabina,

    in the test applicaiton, we see that M3 is sending two messages to C28x and C28x is receving the messages.

    Now before sending the message M3 allocates a buffer from HEAP (SHx RAM) sends the message and frees up this buffer after it sends it. C28x is supposed to receive the message copy the data to its own allocated buffer from its HEAP (SHx RAM) before M3 frees up its  buffer - correct? would it be possible for M3 to free up the buffer and start filling it up again with a new message before C28x had a chance to get the message and copy the data?

    Along with what Trey has suggested above, can we add one more level of sync between M3 and C28x where the buffer won't be freed up back to the HEAP before the other core has acknowledged the reception and completion of usage of the message?

    Best Regards

    Santosh

  • Hi Santosh,

    According to explanation that we got from the form in the past:

    http://e2e.ti.com/support/embedded/bios/f/355/p/206861/762009.aspx

    ".....

    For Concerto, this is how a message is passed from one core to another (pseudo-code).

    Assume we are sending the message from the M3 to the C28 and the queue on the C28 has been created on the C28 and opened on the M3. Also assume both sides have a heap registered with MessageQ and the heapId is HEAPID. Also assume we are using MTOC and CTOM.

    M3 side
    msg = MessageQ_alloc(HEAPID, size);

    //fill in msg...

    MessageQ_put(remoteQ, msg);

    //MessageQ sees that this message is for the C28. So it copies the contents on the message into the MTOC memory and sends an interrupt to the C28. It then calls MessageQ_free on the msg...returning it to the heap.

    C28 Side
    When the C28 interrupt runs, it posts a Swi. This Swi looks the msg in the MTOC memory. The Swi notes the size and the heapId of the msg. It calls MessageQ_alloc(heapId, size). It copies the contents of the MTOC msg into the newly allocated message. It then calls MessageQ_put of the message (note it gets the destination queue from the message). The Swi then updates its shared memory to let the M3 that the message has been processed.

    When the application gets the message (via MessageQ_get), it can call MessageQ_free which returns it back to the heap.

    The reverse (C28 to M3) is exactly the same except the CTOM memory would be used....."

    We understand that it is some internal mechanism of IPC messageQ.

    In our application we do the following.....

    From M3 side:

    For sending.....

    MY_M3_C28_Msg *msgAlloc = NULL;

     // Allocate a message
     msgAlloc = (MY_M3_C28_Msg *)MessageQ_alloc(HEAPID, sizeof(MY_M3_C28_Msg));

    status = MessageQ_put(remoteQueueId, (MessageQ_Msg)Message);

     

    For receiving  messages from C28...

    we have task that is blocked on MessageQ_get(messageQ, &msg, MessageQ_FOREVER);

    Once the message is received the  MessageQ_free((MessageQ_Msg)Message); is called.

    We didn't understand what do you suggest in your previous post. In application (above IPC driver) we don't do any "free"  of message after sending to C28.

    One of the issues that we see that may be problematic is because our IPC receive tasks (task for each MessegeQ) are not in the same priority. Therefore we see that in messageQ creation, Queue opening and Heap registration for eah Queue can be conflicted because different priority of the tasks.  Please note that in your example (MessageQ example) that you provide  for IPC synchroonization we see that the tasks on each core have the same priority (tsk0 & tsk1 on C28 priority 1 both), (tsk0 & tsk1 on CM3 priority 1 both). In our application the tasks for IPC managing are no with the same priority. Please note that IPC_Init() is done in begining of each task. Can it be a problem? We see some contex switch in the middle of heap registration of 1 MessageQ to another task.

    In addition in MessageQ example we see some ping pong on startup (after IPC_Init) to see that synchronization is OK as following:

    Void tsk0_func(UArg arg0, UArg arg1)
    {
        MessageQ_Msg     msg;   
        MessageQ_Handle  messageQ;
        MessageQ_QueueId remoteQueueId;   
        Int              status;
        UInt16           msgId = 0;
        Ptr              buf;
        SizeT            blockSize;
        UInt             numBlocks;

           ////////IPC_INIT ---------------------------------------------------------------------------------------------------------


        /* Register default system heap with MessageQ */
        MessageQ_registerHeap((IHeap_Handle)(MsgQHeapBuf0), HEAPID);

        /* Create the local message queue */


        System_printf("MessageQ_registerHeap finished for MsgQHeapBuf0\n");


        messageQ = MessageQ_create(localQueueName, NULL);   
        if (messageQ == NULL) {
            System_abort("MessageQ_create failed\n" );
        }
       

        System_printf("MessageQ_create finished for MsgQHeapBuf0\n");

        /* Open the remote message queue. Spin until it is ready. */
        do {
            status = MessageQ_open(remoteQueueName, &remoteQueueId);
            /*
             *  Sleep for 1 clock tick to avoid inundating remote processor
             *  with interrupts if open failed
             */
            if (status < 0) {
                Task_sleep(1);
            }
        } while (status < 0);
       

        System_printf("MessageQ_open finished for MsgQHeapBuf0\n");

    ///Now do Ping Pong between the cores  to send one message ------------------------------------------------------------
        if (MultiProc_self() == 0) {
            /* Allocate a message to be ping-ponged around the processors */
            msg = MessageQ_alloc(HEAPID, sizeof(MessageQ_MsgHeader));
            if (msg == NULL) {
               System_abort("MessageQ_alloc failed\n" );
            }
           
            /*
             *  Send the message to the remote processor and wait for a message
             *  from the previous processor.
             */
            System_printf("Start the main loop5\n");
            while (msgId < 1) {
                /* Increment...the remote side will check this */
                msgId++;
                MessageQ_setMsgId(msg, msgId);
               
                System_printf("Sending a message #%d to %s\n", msgId, remoteQueueName);
               
                /* send the message to the remote processor */
                status = MessageQ_put(remoteQueueId, msg);
                if (status < 0) {
                   System_abort("MessageQ_put had a failure/error\n");       
                }
               
                /* Get a message */
                status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
                if (status < 0) {
                   System_abort("This should not happen since timeout is forever\n");
                }
            }
        }
        else {
            /*
             *  Wait for a message from the previous processor and
             *  send it to the remote processor
             */
            System_printf("Start the main loop6\n");
            while (TRUE) {
                /* Get a message */
                status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
                if (status < 0) {
                   System_abort("This should not happen since timeout is forever\n");
                }

                System_printf("Sending a message #%d to %s\n", MessageQ_getMsgId(msg),
                    remoteQueueName);

                /* Get the message id */
                msgId = MessageQ_getMsgId(msg);

                /* send the message to the remote processor */
                status = MessageQ_put(remoteQueueId, msg);
                if (status < 0) {
                   System_abort("MessageQ_put had a failure/error\n");
                }
               
                /* test done */
                if (msgId >= 1) {
                    break;
                }
            }
        }

    }

     Please advice .....do we need to make IPc_Init for each MessageQ when task priority shall be identical?  From your previous post we don't understand what do you suggest for better syncrinization in application layer. Do we need to do Ping Pong synchronization before start normal operation of IPC.

    Hope to hear from you soon, this issue is critical for us

     Thank you

    Regards, Alla

  • Alla,

    Your description of M3 side and C28 side is correct.

    You don't need to do any extra ping pong on startup!  In fact, when you do a MessageQ_open() this will query the remote processor by sending an interrupt and expecting an interrupt back.  Now here are something you need to be aware of:

    1.  All MessageQ msgs will go through the same TransportCirc driver.  This means that when you specify the number of MessageQ msgs in IpcMgr, make sure you account for all MessageQ msgs.

    2.  The sum of the number of blocks in your heaps meant for MessageQ should match the number of MessageQ msgs you configured in IpcMgr.

    3.  Your IPC INIT above is okay.  I assume each tasks creates its own local messageq and opens a different remote messageq?

    4.  I looked at the BlueBox.cfg and message_c28.cfg file attached by Sabina.  There are a few questions/comments I have:

      a.  Why do you have multiple IpcMgr.writeAddr and IpcMgr.readAddr?  You should only have 1 for each and they should point to the base.  This is what is going to be used by IPC.  The C28 and M3 have to match each other.  Looks to me like you are using SRAM0-3 for C28 and SRAM4-7 for the M3?  Then it should be:
            For C28:
                           IpcMgr.writeAddr = 0xC000;
                           IpcMgr.readAddr = 0x10000;

             For M3:
                           IpcMgr.writeAddr = 0x20010000;
                           IpcMgr.readAddr = 0x20008000;

      b.  The IpcMgr.numMessageQMsgs should be the same on both the C28 and M3 side.  I see that you have set it to 4.  You should increase this to the sum of the number of blocks of the heaps that you register for MessageQ.  You should do this unless you know that you will never have more than 3 oustanding Messageq msgs.  If all your sends are synchronized [Meaning, when I send a message, I won't send another one until I receive one] then this should not be a problem.

    5.  It wasn't clear to me whether the simple ping pong example you listed above is working for you?  What you did in the ping pong example should be fine.  Instead of freeing the message, you send it back and that is perfectly fine to do.  There are only two options when a core gets a message. (A) Free it after its done processing it.  (B)  Send it back to the other core (the transport driver will free it in this case).

    Judah

  • Hi Judah,

    thanks for so good clarification.

    we have two heap buffers (144 bytes* 6 blocks = 864 bytes) and (96 bytes*8 blocks = 768 bytes) that we transfer it via IPC between two cores (m3 and C28). Per your explanation we have to define 6+8=14 blocks *144 bytes =2016 bytes for MessageQ. there is no enouph memory in CtoM and MtoC memory for it. so we have tome questions:

    1. could we use for example SRAM3 instead of MtoC and SRAM4 instead of CtoM? 

      [M3]
          CTOMMSGRAM (R)  : origin =   0x2000E0000, length = 0x1000
          MTOCMSGRAM (RW) : origin = 0x20010000, length = 0x1000
      [C28]
          CTOMMSGRAM   : origin = 0x000F000,  length = 0x800
          MTOCMSGRAM   : origin = 0x0001000,  length = 0x800

      in this case we can use onse only:
        For C28:
                             IpcMgr.writeAddr = 0xC000;
                             IpcMgr.readAddr = 0x10000;

               For M3:
                             IpcMgr.writeAddr = 0x20010000;
                             IpcMgr.readAddr = 0x20008000;

    2. if above is correct , how could we use  0x2007F0000 and 0x2007F800 memory? could we define there other heap buffers? Or this memory is used for IPC only?

    3. how coud we use unused memory of SRAM3 ans SRAM4 (for CtoM and MtoC we used only 4k from 8k). is it legal to use part of SRAM for messageQ and the rest memory for something else?

    Thanks,Sabina

  • Sabina,

    #1.  Since you only need 2016 bytes isn't there 2K or 2048 bytest available in CTOMMSGRAM and MTOCMSGRAM?  So you should be able to use either these or Shared RAM right?  So if I understand you correctly, you want to use 0x200E0000 and 0x20010000 for your heaps? and Then 0x20010000 and 0x20008000 for IPC?  If so, there's a conflict with the address 0x20010000 being used in both cases.

    So I'm confused on your memory map.  What is being used for what?  Please clarify:
    A.  What memory are you using for the heap.
    B.  What memory are you using for IPC communications.

    #2.  Again, since there's 2048 bytest available in 0x2007F0000 and 0x2007F800, these can be used for your IPC buffers.

    Look, your IPC buffer can be in one place and your heaps can be in another place.  They do not have to be next to each other.  Here's what I would do.

    1.  Specify your IPC to use 0x2007F000 and 0x2007F800

    2.  Create your heap for SRAM3 and SRAM4.  This way, the rest of SRAM3 and SRAM4 is still available to you for other use.

    Judah

  • Hi Judah,

    #1.
    A. Now we use for heap[C28]: 
       IPC_Mem1       : > S01SHRAM (S01SHRAM    : origin = 0xD000,   length = 0x1000)
        IPC_Mem2       : > S02SHRAM(S02SHRAM    : origin = 0xE000,   length = 0x1000)

    B. and for IPC memory:
    [c28]   CTOMMSGRAM   : origin = 0x3F800,  length = 0x400
        MTOCMSGRAM   : origin = 0x3FC00,  length = 0x400
    [M3]    CTOMMSGRAM (R)  : origin = 0x2007F000, length = 0x800
        MTOCMSGRAM (RW) : origin = 0x2007F800, length = 0x800

    #2. Per your explanation in the previous post:
     1.  All MessageQ msgs will go through the same TransportCirc driver.  This means that when you specify the number of MessageQ msgs in IpcMgr, make sure you account for all MessageQ msgs.

    Does it mean that if we use 8 buffer for one Heap and 6 buffers for another heap - out MessageQ should include 8+6=14  messages?

    if yes:
    We can not use 14 buffers in the messageQ. get the following error:
    ti.sdo.ipc.family.f28m35x.TransportCirc : TransportCirc.numMsgs: 12 is not a power of 2 ‪.xdchelp‬ ‪/L-Full_M3-1‬ 72 C/C++ Problem

    so we can use or 8 or 16 buffers . 16*144 = 2304 > 2048bytes.

    Thanks,Sabina

  • Sabina,

    #1.  Okay, IPC_Mem1 and IPC_Mem2 for heaps on the C28 side looks fine.  What about the M3 side?  Where are the heaps there?

    #2.  The answer to your question "Does it mean that if we use 8 buffer for one Heap and 6 buffers for another heap - out MessageQ should include 8+6=14  messages?" is it depends if your system is synchronous or asynchronous.

    a.  If it is a synchronous system, where M3 sends a message and does not send another one until it gets one back then it is not necessary.  Or lets say you have 4 tasks and all of them send 1 message but does not send another message until it gets one back, then the maximum number of oustanding messages is only 4 and you would not need the number of msgs to be 14.

    b.  if it is an asynchronous system where you don't know if the M3 is going to be sending 1 or 2 or 20 messages before the C28 can respond to any of them, then the answer is "yes", you should have at least 14 message blocks available in IPC.  If you don't have at least 14, then messageQ could return a FAIL for MessageQ_put(). This is not a "must have".  Its more a "nice to have".  It really depends on the system.

    You are correct about the power of 2.  In your case, you could do either 8 or 16.  If you specify 8, then you could use the MTOC and CTOM MSG RAMS.  If you specify 16, then you would need to use Shared Ram.  If you can't use MTOC and CTOM for IPC, you might still be able to use them for your heaps since the heaps do not have this power of 2 restriction.

    Judah

  • Hi Judah,

    #1. In M3 side we don't use shared memory for heap buffers. We define 'Memory section" as null.

    #2. Our case is (b).
    So we have to specify 16 MessageQ blocks in shared memory for M3 and C28. 
    [M3]
    m3.cmd:
    ...
        S00SHRAM   (R)  : origin = 0x20008000, length = 0x2000
        S01SHRAM   (R)  : origin = 0x2000A000, length = 0x2000
        S02SHRAM   (R)  : origin = 0x2000C000, length = 0x2000
        S03SHRAM   (R)  : origin = 0x2000E000, length = 0x2000
        S07SHRAM (RWX)  : origin = 0x20020000, length = 0x7000
       CTOMMSGRAM (R)  : origin = 0x2000E000, length = 0x1000
       MTOCMSGRAM (RW) : origin = 0x20010000, length = 0x1000
    ...

    m3.cfg:

    var IpcMgr = xdc.useModule('ti.sdo.ipc.family.f28m35x.IpcMgr');
    IpcMgr.readAddr  = 0x2000 E000; //sram3- CTOMMSGRAM
    IpcMgr.writeAddr = 0x2001 0000; //sram4-MTOCMSGRAM

    IpcMgr.readAddr  = 0x20008000; //sram0
    IpcMgr.readAddr  = 0x2000A000; //sram1
    IpcMgr.readAddr  = 0x2000C000; //sram2

    IpcMgr.sharedMemoryOwnerMask = 0x0F;


     [c28]
    c28.cmd:

        S00SHRAM   : origin = 0xC000,   length = 0x1000
        S01SHRAM    : origin = 0xD000,   length = 0x1000      /* IPC_BUFFERS_SECTION data S01SHRAM*/
        S02SHRAM    : origin = 0xE000,   length = 0x1000      /* IPC_BUFFERS_SECTION data S02SHRAM*/
        CTOMMSGRAM   : origin = 0x0000 F000,  length = 0x800
        MTOCMSGRAM   : origin = 0x0001 0000,  length = 0x800

    ...

    c28.cfg:
    ...

    IpcMgr.writeAddr = 0xC000;
    IpcMgr.writeAddr = 0xD000;
    IpcMgr.writeAddr = 0xE000;
    IpcMgr.writeAddr = 0xF000;


    Could you please verify that above configuration is correct for our case?


    Could we use CtoM and MtoC (IpcMgr.readAddr  = 0x2007F000;IpcMgr.writeAddr = 0x2007F800;) as regular shared memory or we have to add some additional specification for use it? Could we define section in C28 by the following way:

        MMSGRAM   : origin = 0x3F800,  length = 0x400
        CMSGRAM   : origin = 0x3FC00,  length = 0x400

    MemCtom       : > MMSGRAM   
    MemMtoC       : > CMSGRAM   

    and use it for heap buffer location?

    Thanks,Sabina

  • Sabina,

    #1.  So on the C28 you use shared memory for heaps but not on the M3.  Is the reason why you did this is because there isn't a lot of memory on the C28 side?  Its fine to do this.

    #2.  I spoke about this configuration a few posts back.  I think you have a misunderstading of what IpcMgr.readAddr and IpcMgr.writeAddr is for.  You are suppose to only set these two config parameters once each for the M3 and C28...Not many times like you have here.  If you set it multiple times, the last one wins which I don't think is what you want right?  Set it once to where you want the IPC buffers for messages to be.

    On the C28:  IpcMgr.writeAddr = Address use by C28 for sending message to M3
                            IpcMgr.readAddr = Address use by C28 for reading message from M3

    On the M3:  IpcMgr.writeAddr = Address use by M3 for sending message to C28
                         IpcMgr.readAddr = Address use by M3 for reading message from C28

    C28's IpcMgr.writeAddr must be the same memory address in their respective address space as M3's IpcMgr.readAddr and
    C28's IpcMgr.readAddr must be the same memory address in their respective address space as M3's IpcMgr.writeAddr

    For example:
    C28:  IpcMgr.writeAddr = 0xC000  then M3:  IpcMgr.readAddr = 0x20008000
    C28:  IpcMgr.readAddr = 0x10000 then M3: IpcMgr.writeAddr = 0x20010000

    You need to specify both readAddr and writeAddr for both C28 and M3.  I didn't see a C28 readAddr specified above!

    You can use CtoM and MtoC as a regular shared memory.  To me, functionally I see no difference between these and the shared memories.  These are nice because they've already been designated and you don't need to specify anywhere which is read-only for which processor.

    Judah

  • Hi Judan,

    We discovered the sourse of our problem. the situation is the following:

    1. if we work with ping-pong per your example - all work perfect:

        if (MultiProc_self() == 0) {
            /* Allocate a message to be ping-ponged around the processors */
            msg = MessageQ_alloc(HEAPID, sizeof(MessageQ_MsgHeader));
            if (msg == NULL) {
               System_abort("MessageQ_alloc failed\n" );
            }

            /*
             *  Send the message to the remote processor and wait for a message
             *  from the previous processor.
             */
            System_printf("Start the main loop7\n");
            while (msgId < NUMLOOPS) {
                /* Increment...the remote side will check this */
                msgId++;
                MessageQ_setMsgId(msg, msgId);

                System_printf("Sending a message #%d to %s\n", msgId, remoteQueueName_tsk2);

                /* send the message to the remote processor */
                status = MessageQ_put(remoteQueueId, msg);
                if (status < 0) {
                   System_abort("MessageQ_put had a failure/error\n");
                }

                /* Get a message */
                status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
                if (status < 0) {
                   System_abort("This should not happen since timeout is forever\n");
                }
            }
        }
        else {
            /*
             *  Wait for a message from the previous processor and
             *  send it to the remote processor
             */
            System_printf("Start the main loop8\n");
            while (TRUE) {
                /* Get a message */
                status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER);
                if (status < 0) {
                   System_abort("This should not happen since timeout is forever\n");
                }

                System_printf("Sending a message #%d to %s\n", MessageQ_getMsgId(msg),
                    remoteQueueName_tsk2);

                /* Get the message id */
                msgId = MessageQ_getMsgId(msg);

                /* send the message to the remote processor */
                status = MessageQ_put(remoteQueueId, msg);
                if (status < 0) {
                   System_abort("MessageQ_put had a failure/error\n");
                }

                /* test done */
                if (msgId >= NUMLOOPS) {
                    break;
                }
            }
        }

    in this case the situation as per your description in the previous post".(A) Free it after its done processing it..".
    M3 allocate memory, send message to C28, c28 get the message and send it back to m3.
    In this case we don't free the heap, Free is done by transport driver on M3 side, after M3 get back the message from C28.

    2. our scenario is the following:

        if (MultiProc_self() == 0) {
             /* Allocate a message to be ping-ponged around the processors */

             /*
              *  Send the message to the remote processor and wait for a message
              *  from the previous processor.
              */
             System_printf("Start the main loop1/PMCU \n");
             while (msgId < 1) {

                 msg = MessageQ_alloc(HEAPID_2, sizeof(MessageQ_MsgHeader));
                 if (msg == NULL) {
                    System_abort("MessageQ_alloc failed\n" );
                 }

                 /* Increment...the remote side will check this */
                 msgId++;
                 MessageQ_setMsgId(msg, msgId);

                 System_printf("Sending a message #%d to %s/PMCU \n", msgId, remoteQueueName_tsk2);

                 /* send the message to the remote processor */
                 status = MessageQ_put(remoteQueueId_2, msg);
                 if (status < 0) {
                    System_abort("MessageQ_put had a failure/error\n");
                 }

                 /* Get a message */
                 status = MessageQ_get(messageQ_2, &msg1, MessageQ_FOREVER);
                 if (status < 0) {
                    System_abort("This should not happen since timeout is forever\n");
                 }
                 MessageQ_free((MessageQ_Msg)msg1);

             }
         }
         else {
             /*
              *  Wait for a message from the previous processor and
              *  send it to the remote processor
              */
             System_printf("Start the main loop2/PMCU \n");
             while (TRUE) {
                 /* Get a message */
                 status = MessageQ_get(messageQ_2, &msg1, MessageQ_FOREVER);
                 if (status < 0) {
                     System_printf("This should not happen since timeout is forever\n");
                    System_abort("This should not happen since timeout is forever\n");
                 }
                 /* Get the message id */
                msgId = MessageQ_getMsgId(msg1);
                 //free
                MessageQ_free((MessageQ_Msg)msg1);
                System_printf("MessageQ_free = %d/ PMCU\n",msgId);

                 System_printf("Sending a message #%d to %s/PMCU \n", msgId, remoteQueueName);
                 msg = MessageQ_alloc(HEAPID_2, sizeof(MessageQ_MsgHeader));
                 if (msg == NULL) {
                    System_abort("MessageQ_alloc failed\n" );
                 }
                 msgId++;
                 MessageQ_setMsgId(msg, msgId);

                 /* send the message to the remote processor */
                 status = MessageQ_put(remoteQueueId_2, msg);
                 if (status < 0) {
                    System_abort("MessageQ_put had a failure/error\n");
                  }

                 /* test done */
                 if (msgId >= 1) {
                     break;
                 }
             }
         }

    M3 allocate message on the heap, send data to C28, C28 get the data, release the heap, allocate another message on the heap and send it to M3. M3 get a message and release the heap from its side.

    this scenarion doesn't work. application C28 fail on the allocate memory on the heap:
    msg = MessageQ_alloc(HEAPID_2, sizeof(MessageQ_MsgHeader));

    we define C28 IPC messages as:
        S03SHRAM   : origin = 0x0000F000, length = 0x1000  //IPC write
        S04SHRAM   : origin = 0x00010000, length = 0x1000  //IPC read

     CTOMMSGRAM   : origin = 0x3F800,  length = 0x400 // use it as heap for MsgQHeapBuf0

    in cfg:

    var IpcMgr = xdc.useModule('ti.sdo.ipc.family.f28m35x.IpcMgr');
    IpcMgr.writeAddr = 0x0000F000;
    IpcMgr.readAddr  = 0x00010000;

    var heapBuf0Params = new HeapBuf.Params();
    heapBuf0Params.instance.name = "MsgQHeapBuf0";
    heapBuf0Params.blockSize = 144;
    heapBuf0Params.numBlocks = 6;
    heapBuf0Params.align = 8;
    heapBuf0Params.sectionName = "IPC_Mem1";
    Program.sectMap["IPC_Mem1"] = { loadSegment: "CTOMMSGRAM" };

    heapBuf1Params.instance.name = "PMCUMsgQHeapBuf1";
    heapBuf1Params.blockSize = 96;
    heapBuf1Params.numBlocks = 8;
    heapBuf1Params.align = 8;
    heapBuf1Params.sectionName = "IPC_Mem2";
    Program.sectMap["IPC_Mem2"] = { loadSegment: "S02SHRAM" };

    M3:
       S03SHRAM   (R)  : origin = 0x2000E000, length = 0x2000 //ipc read
      S04SHRAM (RWX)  : origin = 0x20010000, length = 0x2000 //ipc write

    cfg:

    var IpcMgr = xdc.useModule('ti.sdo.ipc.family.f28m35x.IpcMgr');
    IpcMgr.writeAddr = 0x20010000;
    IpcMgr.readAddr = 0x2000E000;

    IpcMgr.sharedMemoryOwnerMask = 0x0F;

    var heapBuf0Params = new HeapBuf.Params();
    heapBuf0Params.instance.name = "MsgQHeapBuf0";
    heapBuf0Params.blockSize = 144;
    heapBuf0Params.numBlocks = 8;
    heapBuf0Params.align = 8;
    heapBuf0Params.sectionName = null;
    Program.global.MsgQHeapBuf0 = HeapBuf.create(heapBuf0Params);

    var heapBuf3Params = new HeapBuf.Params();
    heapBuf3Params.instance.name = "PMCUMsgQHeapBuf1";
    heapBuf3Params.blockSize = 96;
    heapBuf3Params.numBlocks = 8;
    heapBuf3Params.align = 8;
    Program.global.PMCUMsgQHeapBuf1 = HeapBuf.create(heapBuf3Params);

    the problem appear after we burn application and run it otside of CCS.

    Why we can not allocate data on the C28 heap?
    We based our testing on the example from TI/Sys/Bios

    Thanks,Sabina

     

  • Sabina,

    I don't see anything wrong with the 'C' code in your scenario above.  It looks like its okay to me.  However I do have a couple of questions:

    1.  I assume that you have set 'S02SHRAM' to be read/write by C28? And is there where the HEAPID_2 is coming from?

    2.  Did you register HEAPID_2 with MessgeQ?

    3.  Have you tried stepping into the MessageQ_alloc and see why its returning NULL?

    Judah

  • IpcMgr.sharedMemoryOwnerMask = 0x0F;Hi Judah,

    1. it define in c28.cmd as:   S02SHRAM    : origin = 0xE000,   length = 0x1000
    [M3]:
    A  M3.cmd:S02SHRAM   (R)  as: origin = 0x2000C000, length = 0x2000
    B. M3.cfg: IpcMgr.sharedMemoryOwnerMask = 0x0F;
    C. Before sys/bios start in M3 main() :
        RAMMReqSharedMemAccess(S0_ACCESS , SX_C28MASTER );
        RAMMReqSharedMemAccess(S1_ACCESS , SX_C28MASTER );
        RAMMReqSharedMemAccess(S2_ACCESS , SX_C28MASTER );
        RAMMReqSharedMemAccess(S3_ACCESS , SX_C28MASTER );

    HEAPID_2 is placed on S02SHRAM   
    HEAPID is placed on CTOMMSGRAM

    2. Yes.  And it work properly always.

        UInt numProcs = MultiProc_getNumProcessors(); 
        // Generate queue names based on own proc ID and total number of procs
        System_sprintf(localQueueName_tsk2, "%s2_queue",
                MultiProc_getName(MultiProc_self()));
        System_sprintf(remoteQueueName_tsk2, "%s2_queue",
                MultiProc_getName(1 - MultiProc_self()));


        // Register default system heap with MessageQ
        MessageQ_registerHeap((IHeap_Handle)(PMCUMsgQHeapBuf1), HEAPID_2);
     System_printf("MessageQ_registerHeap finished for PMCUMsgQHeapBuf1/PMCU \n");

        // Create the local message queue
        messageQ_2 = MessageQ_create(localQueueName_tsk2, NULL);
        if (messageQ_2 == NULL) {
            System_abort("MessageQ2_create failed\n" );
        }
     System_printf("MessageQ_create finished for PMCUMsgQHeapBuf1/PMCU \n");

        // Open the remote message queue. Spin until it is ready.
        do {
            status = MessageQ_open(remoteQueueName_tsk2, &remoteQueueId_2);
            // Sleep for 1 clock tick to avoid inundating remote processor
            // with interrupts if open failed
            if (status < 0) {
                Task_sleep(1);
            }
        } while (status < 0);
     System_printf("MessageQ_open finished for PMCUMsgQHeapBuf1/PMCU \n");

    3. We don't have any problem during debugging - all work good. The problem appear only after booting without CCS.


    Thanks,Sabina


     

  • Sabina,

    Okay, so everything works in CCS.  That is good to know.

    Now about the booting without CCS.  How do you know the MessageQ_alloc failed?

    Did you remember to set all of the config params needed to make things bootable without CCS?

    Did you remember to set the default System proxy to SysMin instead of SysStd?  See below:

    SysMin = xdc.useModule('xdc.runtime.SysMin');
    System = xdc.useModule('xdc.runtime.System');
    System.SupportProxy = SysMin;

    Judah

  • Hi Judan,

    We put UART debug printing from M3. And after running without CCS we see the following data on UART display:

     MessageQ_create finished for PMCUMsgQHeapBuf1/PMCU                               
    Notify_registerEvent finished for MsgQHeapBuf0/LPU                               
    MessageQ_registerHeap finished for MsgQHeapBuf0/LPU                              
    MessageQ_create finished for MsgQHeapBuf0/LPU                                   
    Start TaskCanTransmit                                                            
    Start TaskCanReceive                                                             
    Start HandleReceivePacket                                                        
    CCANDataLinkLayer::HandleReceivePacket start                                     
    CCANDataLinkLayer::before while                                                  
    Start TaskTransmitLogToLPU                                                      
    MessageQ_open finished for PMCUMsgQHeapBuf1/PMCU                                 
    Start the main loop1/PMCU                                                        
    Sending a message #1 to C282_queue/PMCU                                          
    MessageQ_open finished for MsgQHeapBuf0/LPU                                      
    Start the main loop1/LPU                                                         
    Sending a message #1 to C28_queue/LPU 

    So we see that M3 send data to C28. C28 receive the data and perform Free/Allocate and as result of it Fail. we removed Free() and leave Allocate() only. C28 fail in this case also.  C28 work (from booting) only if it doesn't allocate memory on heap.

    From CCS running we get the following (properly behaviors) with Free/Allocate from C28. In this case M3 and C28 finish synchronization and start send/receive messages :

    MessageQ_create finished for MsgQHeapBuf0/LPU                                    
    Start TaskCanTransmit                                                            
    Start TaskCanReceive                                                             
    Start HandleReceivePacket                                                        
    CCANDataLinkLayer::HandleReceivePacket start                                     
    CCANDataLinkLayer::before while                                                  
    Start TaskTransmitLogToLPU                                                       
    MessageQ_open finished for PMCUMsgQHeapBuf1/PMCU                                 
    Start the main loop1/PMCU                                                        
    Sending a message #1 to C282_queue/PMCU                                          
    MessaMessageQ_free = 2/ PMCU                                                     
    Synchronization /PMCU finished successfully                                      
    geQ_open finished for MsgQHeapBuf0/LPU                                           
    Start CIPCInterface (M3):: before while, after IPC_init_2()                      
    the main loop1/LPU                                                               
    Sending a message #1 to C28_queue/LPU                                            
    MessageQ_free = 2 /LPU                                                           
    Synchronization /LPU finished successfully                                       
    CIPCInterface (M3):: before while, after IPC_init_1()                            
    IPC_TaskReceiveLPUMsg /  before receive a message                                
    IPC_recMsgQ1 11/PMCU                                                             
    IPC_TaskReceivePMCUMsg /receive a message to be forwarded to one of PMCUs        
    IPC_TaskReceivePMCUMsg/PMCU_TYPE_HVPS                                            
    IPC_freeMsg 11/PMCU                                                              
    IPC_TaskReceivePMCUMsg/IPC_freeMsgPMCUType1                                      
    HV_B                                                                             
    IPC_recMsgQ1 12/PMCU                                                             
    IPC_TaskReceivePMCUMsg /receive a message to be forwarded to one of PMCUs        
    IPC_TaskReceivePMCUMsg/PMCU_TYPE_SERVO_MOTOR                                     
    IPC_freeMsg 12/PMCU                                                              
    IPC_TaskReceivePMCUMsg/IPC_freeMsgPMCUType2                                      
    CANRecData = 0, 21, 1,BId=1, SSI=1                                               
    Sending a message #21 to Q2 C282_queue/PMCU                                      
    IPC_recMsgQ1 13/PMCU                                                             
    IPC_TaskReceivePMCUMsg /receive a message to be forwarded to one of PMCUs        
    IPC_TaskReceivePMCUMsg/PMCU_TYPE_HVPS                                            
    IPC_freeMsg 13/PMCU                                                              
    IPC_TaskReceivePMCUMsg/IPC_freeMsgPMCUType1                                      
    HV_B                                                                             
    CANRecData = 10, 12, 1,BId=1, SSI=1                                              
    Sending a message #22 to Q2 C282_queue/PMCU 

    I use System.SupportProxy = SysMin;

    You ask :  Did you remember to set all of the config params needed to make things bootable without CCS?

    I don't know - may be we have to add something specific for shared memory on C28 side? Why it can not allocate the memory there?

    Thanks,Sabina

     

  • Sabina,

    All the config params I was speaking about has to do with startup except for the SysMin, but those do not appear to be your issue.

    I don't know why C28 can not allocate from shared memory only in the case of booting without CCS.  That does not make sense to me from a software prespective.

    At this point, I don't think its a BIOS problem.  It sounds more like a timing issue or something not being initialized.  Can you tell me what frequencies you are running the cores at?

    Note that when you run with CCS, it does some stuff in the gel files possibly with FLASH wait states and PLLs to make things run slower.  When you are running outside of CCS, this is not happening so the timing could be different.

    Here's one suggestion I got from a collegue to try:  Run your program in CCS as you typically do when it works.  Then do a "reset" and a "restart" and "run" again.  DO NOT DO A "RELOAD".  This should be similar to running your program from flash.  If your program is failing, I think this should fail too.

    Another thing to try would be to not have a gel file or empty the gel file and run your program through CCS.  This would simulate booting without CCS and I would expect it to fail the same way.  If it does fail, then obviously, the gel file in CCS is doing something to make it not fail, and you can pinpoint this and perhaps added to your code.

    If you could try the different scenario and let me know what you find...If after all this you still cannot solve the issue, I can try to reproduce on my end.

    Judah

     

  • Hi Judan,

    1. C28: 150000000 hz
    M3: 75000000

    2. When we run program from debug we always do reset/restart/run for both cores, else CAN doesn't work from debugging.pls see1447.RE working with NDK IPC and CAN interfaces in parallel..rar

    3. I didn't succeed to work with empty gel file in the past.  I'll try it again, but if you can reproduce the problem on your side - it help us a lot. we face with this problem more then month and can not resolve it.  It is the 3rd post on the forum with this problem.

     Thanks,Sabina

  • Sabina,

    Okay, can you please attach the following:

    Your .cfg files for C28 and M3.

    You gel files for C28 and M3.

    Your .c file or a modified version for C28 and M3.

    I'm hoping I can reproduce the problem without all the CAN and UART and other modules.  I basically want a skeleton of the program as you previously describe with MessageQ sending messages back and forth.

    Judah

  • Hi Judan,

    Pls see 7120.ProjectFiles.rar

    It doesn't include the project, but includes all files that i use in the project. Now I am at home(9.00PM), and can send you an example only tomorrow from the office.
    Pls let me know if you need an example from our side, or you can reproduce the problem with attached files. Our example is based on the TI example of messaheQ from IPC/SysBios.

    Thanks, Sabina 

     

     

  • Sabina,

    Just wanted to update you.  So I think I finally was able to reproduce the problem that you are seeing.
    I am able to see the program work when loading/running through CCS but when booting off flash the program does not complete.
    At this point, I will continue to debug the issue to determine why booting off flash fails.

    Judah

  • Sabina,

    After looking into this, I realize that you cannot create a static HeapBuf from the C28 in Shared Memory Regions because that memory is not writable by C28 initially.  Now, I took the skeleton of your program and I was able to get the program to work correctly booting from flash but only if I did one of the two options below:

    Option 1:  I created the HeapBuf in Shared Memory Region 2 dynamically at runtime.  In my case, I just created it in main():

         #pragma DATA_SECTION(buf, ".mybuffer");
         HeapBuf_Handle PMCUMsgQHeapBuf1;
         Char   buf[1024];

         Void main()
         {
                HeapBuf_Params params;
     
                HeapBuf_Params_init(&params);
                params.blockSize = 96;
                params.numBlocks = 8;
                params.align = 8;
                params.buf = (Ptr)buf;
                params.bufSize = sizeof(buf);
     
                PMCUMsgQHeapBuf1 = HeapBuf_create(&params, NULL);
                if (PMCUMsgQHeapBuf1 == NULL) {
                           System_printf("Error creating HeapBuf\n");
                }
     
               BIOS_start();
          }

          In *cfg file:

         Remove the code to create "PMCUMsgQHeapBuf1" statically and added the following line to place my buffer to the right memory:
         Program.sectMap[".mybuffer"] = { runAddress: 0xE000};

    Option 2:  Create the "PMCUMsgQHeapBuf1" in CTOMMSGRAM and create the "MsgQHeapBuf0" in 0xE000 (Shared Ram 2);

          This worked for me.

    Now to as why your program works when loaded through CCS but not when booting from flash, I don't know.  It seems to me it should not have worked in either case.  This is still a mystery to me.  My only guess is that CCS is doing something to permit write violations?

    Judah

  • Hi Judah,

    I removed "PMCUMsgQHeapBuf1" from cfg and created it dinamically per your suggestion in Option#1. It work now! thank a lot! Both core work, leds blink, CAN work.... 

    It is not so clear for me option#2. Do you mean create dinamically  MsgQHeapBuf0 and statically PMCUMsgQHeapBuf1?

    THANK YOU!!!!  Sabina