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] IPC: MessageQ from Flash - without Debugger

Other Parts Discussed in Thread: CODECOMPOSER, SYSBIOS

Hello e2e-Community,

Is there an example for IPC MessageQ which runs from flash?

Of course, there is the Generic Example in CodeComposer - it runs perfectly as it is with the debugger and everything. But which steps do I have to do to get run from flash, when I just power-on the device with no debugger plugged in? (Or with the debugger configured like this: http://processors.wiki.ti.com/index.php/Concerto_Dual_Core_Boot#Debugging_Flash_Dual-Core_Boot )

To me, it seems like the M3 gets stuck in the IpcMgr-Startup in the function Int IpcMgr_Module_startup(Int phase) in line 197 of the file IpcMgr.c:

/* wait for C28 state to be sync start */
while (*startReadAddr != SYNCSTART);

Whereas the c28 does not really come alive at all - perhaps the IPC-Command from the M3 to the c28 for the Flash-Boot is missing? ... I can't even pause the c28 in the debugger in this mode..

Is there any trick to it? Do I have to enable "Boot from flash" in either of the SysBios-Config-Files? I tried it, nothing worked - perhaps I missed some combination? If I enable the function "initiate boot of the c28 processor" in the m3-SysBios-Config, I get stuck at the concertoInit_Boot_bootC28()-function..

I would be very happy if someone could help me - I've been trying for days already ... :(

Thank you,

Philipp L.

/edit: Seems like I can answer myself :)

When I put the M3's FlashInit() and the IPCMtoCBootControlSystem(CBROM_MTOC_BOOTMODE_BOOT_FROM_FLASH); in a Startup function which is called before the module initializations, and when I add some wait time with for-loops here and there, it WORKS!! Both cores start up, and IPC seems to work, too ..

Can anyone tell me: Is this the right way to do it? 

/edit2: Seems like with this trick, the m3 starts up, but the c28 somehow does not really start up - can't really see it in the debugger -.- The m3 is sending ipc-messages, but the c28 does not really do something, I guess ..

Any thoughts?

  • Philipp,

    What version of SYS/BIOS are you using?  There have been recent enhancements for Flash configuration and booting and it would be good to know which version you’re using. 

    I don’t know of any simple messageQ example that easily shows (by flashing an LED or something) that boot from Flash works.  I know of a simpler program that shows this, but it doesn’t use messageQ.  I’ve asked internally about an example, and will post that info if a good example is found...

    For the M3 side, to boot both M3 and C28 from Flash, the following configuration is needed:

    var Boot = xdc.useModule('ti.catalog.arm.cortexm3.concertoInit.Boot');
    Boot.bootFromFlash = true;
    Boot.bootC28 = true;

    The first config will cause a branch to the M3 program entry point to be emitted so that the M3 can boot out of Flash.  This is enabled by default.

    The second will cause the Boot module to handshake and send a low-level IPC command to the C28-side boot ROM to cause it to launch the C28 program running.  [This IPC command is to the C28 boot ROM, as defined in the Concerto device documentation.  The IpcMgr module has the same “IPC” naming, but is actually higher-level software that starts up later, after the M3 and C28 have exited their boot ROMs.]  This config defaults to “false”, and should be left this way for execution in CCS.  If it is set to “true” when running in CCS it usually causes the M3 to get stuck during the handshake with the C28 boot ROM, because CCS prevents the C28 from running.  To boot standalone, without CCS, this config must be set to “true”. 

    For the C28 application configuration, there is a similar Boot module with a “bootFromFlash” configuration parameter.  This will cause a long branch to the C28 program entry point to be emitted, so that the C28 program can be launched from the C28 boot ROM, via a command from the M3, as described above.  This parameter defaults to “true”, and can be left this way for either CCS or standalone Flash boot.

    One other thing… to test boot from Flash be sure to disconnect CCS, and power cycle the board.

    Hope this helps some.

    Scott

  • Scott,

    First of all: Thanks for your long answer!

    Then, I am currently using sysbios v. 6.32.05.54 (from the name of the folder in my windows-installation). I am downloading the latest version, v. 6.33.05.46 just now, and once I figured out how to update it, I will try it with this version. ;)

    And tell me if I get this right: I don't have to do any low-level calls when I use sysbios, correct? So, no need to call FlashInit(), no need for the low-level IPC command to startup the c28 core, and no SystemClock-Calls like SysCtlClockConfigSet(....)? But on the other hand, I do need lowlevel Calls for the GPIO-configuration, because there is no GPIO support for Concerto in sysbios yet, correct?

    OK, I will try the newer Sysbios version now, and report on my advances later :)

    UPDATE:

    I updated my software successfully, created a clean new project, and after some try&error, it really works now! - From Flash and everything!! yay :)

    The next thing is, I want to transfer some "real" information between the two cores, not only the MessageID. So, I defined a custom Message:

    typedef struct MyMsg {
    MessageQ_MsgHeader header; // Required
    Int32 myInt;
    char myString[15];
    } MyMsg;

    Then, I changed the commands (to the new data type MyMsg) to allocate Heap and to open the MsgQ and so on, and it still works well.

    But how do I now write something into my new defined message, and how can I read this out on the other core?

    Scott, could you (or someone else) post me a "code-snippet" on how I could write for example the value 4711 in my "myInt"-field in the structure, and another "code-snippet" on how I would read this out on the other core?

    As always, I am very thankful for every answer. You do a great work!

    - Philipp L.

  • Philipp,

    I’m glad to hear you are booting now!  

    Right, the Boot modules for M3 and C28 can handle the low-level details to manage Flash booting.  The M3 Boot module can also configure the PLLs and clock dividers. 

    The configuration of the Flash controllers (setting wait states and enabling of caches while executing from RAM) has been recently added, but not released externally yet.  This will be available in an XDCtools release scheduled for the end of the month.  Until then, you can leave the Flash controllers in their default configuration for booting.

    And yes, GPIO is not managed by SYS/BIOS.

    I will need to search for some MessageQ snippets to send…

    Scott

  • Here's an (uncompiled) example:

    Void example()
    {
    MyMsg msg;
    ...

    msg = MessageQ_alloc(HEAPID, sizeof(MyMsg));

    MessageQ_setReplyQueue(msgqHandle, (MessageQ_Msg)msg);

    msg.myInt = 0x4321;
    MessageQ_put(queueId, (MessageQ_Msg)msg);

    MessageQ_get(msgqHandle, (MessageQ_Msg)&msg, MessageQ_FOREVER);
    System_printf("received: 0x%x\n", msg.myInt);
    }

  • Ooops, those MessageQ_* calls should have &msg in them as in

    MessageQ_put(queueId, (MessageQ_Msg)&msg);

  • Gack! Try again (memo to Mark: don't try to respond while on conf call :)

    typedef struct MyMsg {
    MessageQ_MsgHeader header; // Required
    Int32 myInt;
    char myString[15];
    } MyMsg;

    Void example()
    {
    MyMsg *msg;
    ...

    msg = (MyMsg *)MessageQ_alloc(HEAPID, sizeof(MyMsg));

    MessageQ_setReplyQueue(msgqHandle, (MessageQ_Msg)msg);

    msg->myInt = 0x4321;
    MessageQ_put(queueId, (MessageQ_Msg)msg);

    MessageQ_get(msgqHandle, (MessageQ_Msg *)&msg, MessageQ_FOREVER);

    System_printf("received: 0x%x\n", msg->myInt);
    }

  • Ok, big thanks to you two, Mark and Scott :)

    It works. Perfectly.

    The only problem is: when I make a char[xx] (string)-field in the struct, I have the problem, that the c28 has only 16bit data width, and the m3 can do 8bit.

    That means, char is defined as 16bit on c28, and as 8bit on m3.

    So, if I send the string "HELLO" from c28 to m3 over a string field in my struct (as shown in my earlier post), I receive this string: "H\0E\0L\0L\0O\0". 

    My ideas for a solution are:
    - I could write a special "strcpy" function on c28, which would put two 8bit chars into one 16bit char field, which would be interpreted correctly on the m3
    - Perhaps I could define the char[xx] field on the m3 as int[xx], and after receiving do some kind of casting to char / or filter the '\0' out somehow else.

    What would you recommend? Or is there an exisiting solution? I think, performance in my application is more important on the c28 side, so the second solution would be better for the performance - but it would take more of the shared memory...

    -Philipp

  • Philipp,

    You could take either approach, depending on whether C28 performance or shared memory footprint is a higher priority for you.

    In case it helps, I’ve included below a function that does packing on the C28 side. The C compiler provides a __byte() intrinsic that you might use too, to simplify the below code.

    Scott

    ------

    /*
     *  ======== NameServerBlock_strncpy ========
     *  Copies the source string into the destination string as a
     *  packed string.  The length includes the null terminating
     *  character.
     */
    Char* NameServerBlock_strncpy(Char *dest, Char *src, SizeT len)
    {
        Int i;
        UInt half = len >> 1;

        /* copy and pack the string */
        for (i = 0; i < half; i++) {
            dest[i] = src[i << 1] | (src[(i << 1) + 1] << 8);
        }

        /* The terminating character */
        if (len & 1) {
            /*
             *  (len = odd) ==> name has even number of characters.
             *  The next byte is (len >> 1), so zero that out.
             */
            dest[half] = '\0';
        }
        else {
            /*
             *  (len = even) ==> name has odd number of characters.
             *  Zero out the upper half of the last byte.
             */
            dest[half - 1] |= ('\0' << 8);
        }

        return (dest);
    }

  • Scott,

    Thank you very much. Again :) I'll work with this.

    I'll mark this thread as "answered" then. (I'll take one of your answers from above, because the actual topic of this thread was already answered there..)

    Philipp

  • Philipp L wrote:

     >I updated my software successfully, created a clean new project, and after some try&error, it really works now! - From Flash and everything!! yay :)


    I'm experiencing similar problems.  I can't get the IPC messaging example to boot from flash. (same SW versions as you mentioned bios_6_33_05_46 IPC: ipc_1_24_03_32

    Could you share some details what you did to make it work ?

    How did you determine if the app runs ok ?  I added some blinking leds to it, to visually see that both cpus run and complete the test run.

    Here is what I did, and say

    I took the example, add some blinking leds to it. (GPIO).  (works fine in debugger)

      1 enabled bios C3: boot from flash  + boot C28:  

      2 eanbled bios C28: boot from flash

    From the leds it appears that the system keeps rebooting. (some where after the MessageQ_open() call on the ARM. unsure where)

  • Hello,

    I need to go on a business trip in just two hours, so I can't help you right now.

    If your problem still exists next week, I can try to help you on Monday! Perhaps the "MCU SDK" for Concerto can solve your problem, too. I had no chance yet to try that, but it seems promising!

    http://www.ti.com/product/f28m35h52c --> Technical Docs --> User Guides --> MCU SDK

    But I can tell you one thing right now: "How did you determine if the app runs ok ?" --> Also with LEDs, and on the M3 side, I made a console output to UART/USB, and from there I could see on my console program on the PC when the M3 resetted. The c28 side was more difficult. When the IPC worked, I could use the same console (send message c28 > m3, then m3 > console > PC), but before, I also only had LEDs.

  • Thanks, I got it working.

    This set of versions worked for me http://e2e.ti.com/support/embedded/bios/f/355/t/213533.aspx