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.

PROCESSOR-SDK-OMAPL138: Understanding The IPC/MessageQ communication flow with Sys/bios & Linux

Part Number: PROCESSOR-SDK-OMAPL138
Other Parts Discussed in Thread: OMAPL138

Hi,

I am currently working with the OMAPL138 platform. I am running SYS/BIOS on the DSP & Linux on the ARM. I would like to communicate between the cores with IPC over RPmsg.
In this regard, I have tried out the "ex02_messageq" & "ex11_ping" examples and the outputs looks fine.

MessageQ flow question:
I am currently writing my own application, which is applying IPC & MessaageQ, but I am struggeling a bit with understanding the MessageQ flow between the ARM & the DSP.
Considering the steps mentioned below, is the MessageQ flow correctly understood?

DSP opens queue created by ARM, OR ARM opens queue created by DSP

  • [DSP] creates local MessageQ with MessageQ_create().
  • [DSP] waits for a handshake message from the ARM with MessageQ_get().
  • [ARM] creates local MessaageQ with MessageQ_create().
  • [ARM] opens DSP local messageQ to obtain queue id for DSP local queue.
  • [ARM] initializes MessageQ header in message with MessageQ_setReplyQueue().
  • [ARM] sends message with MessageQ_put().
  • [DSP] receives the message from the ARM and is able to obtain a queue id with MessageQ_getReplyQueue() from the ARM message.

MessaageQ_open not working on DSP:
I have also experienced that any calls to MessageQ_open() on the DSP always returns "MessageQ_E_NOTFOUND" If I try to open a local MessageQ created by the ARM.
However, the ARM is perfectly able to open any local MessageQ created by the DSP with MessageQ_open(). Is this due to the ARM being able to obtain the queue id's using
the LAD daemon & the DSP is unable to use the LAD daemon since it is running in Linux?


Thanks & Regards,
Kim

  • Considering the steps mentioned below, is the MessageQ flow correctly understood?

    Yes, your understanding is correct.

    Is this due to the ARM being able to obtain the queue id's using
    the LAD daemon & the DSP is unable to use the LAD daemon since it is running in Linux?

    I believe when DSP tried to open a message queue created by ARM, that message queue has not been created yet.

  • Hi Jianzhongxu,

    That sounds great.


    Makes  sense, but is the DSP able to at all use the LAD daemon in any way. Is it only accesible in Linux?


    To me it seems like that the ARM is able to open queues both remotely and locally because of the LAD Daemon, but the DSP can only open queues locally?

  • Makes  sense, but is the DSP able to at all use the LAD daemon in any way. Is it only accesible in Linux?

    LAD daemon is only available in Linux, not in RTOS.

    To me it seems like that the ARM is able to open queues both remotely and locally because of the LAD Daemon, but the DSP can only open queues locally?

    DSP can open queues created by ARM. It's just that the queue needs to be created by ARM first. You can do MessageQ_open() in a while loop as what's currently done on ARM. If DSP runs first, MessageQ_open() will return MessageQ_E_NOTFOUND until ARM runs the application which creates the message queue that DSP tries to open.

  • Hi Jianzhongxu,

    In my application, the DSP starts before the ARM.

    This is what I do on the DSP if I try to open a queue (HOST:dspsystem) created by the ARM:

    Int status;
    
    do {
          status = MessageQ_open( "HOST:dspsystem", &RemotequeId);
          if (status == MessageQ_E_NOTFOUND) {
            Task_sleep(1);
          }
        } while(status == MessageQ_E_NOTFOUND);

    This is what I do when I create the queue (HOST:dspsystem) on the ARM:

    Char cbuf[48];
    MessageQ_Params messageQParams;
    MessageQ_Handle  localMessageQ = NULL;
    
    /* Create local MessageQ handler */
    sprintf(cbuf, "%s:%s", HOST, dspsystem);
    
    MessageQ_Params_init(&messageQParams);
    localMessageQ = MessageQ_create(cbuf, &messageQParams);
    

    On the DSP, the MessageQ_open() function keeps returning MessageQ_E_NOTFOUND.
    According to "SYS/BIOS Inter-Processor Communication" user guide, the MessageQ_open() internally calls NameServer_get().

    Link to user guide: user_guide

    In Linux, I understand that the NameServer_get() call makes use of the LAD daemon to look for queues on the DSP. I guess this is why MessageQ_open() works fine on the ARM.

    But how does the DSP locate any queues on the ARM, does it make use of something similar to the LAD daemon perhaps?

    Thank you & regards,
    Kim

  • Hi Kim,

    But how does the DSP locate any queues on the ARM, does it make use of something similar to the LAD daemon perhaps?

    It uses NameServer_get(), as described here.

    I tried to call MessageQ_open() on DSP to open a queue to be created by the ARM as well. Initially I constantly saw message "virtio_rpmsg_bus virtio0: msg received with no recipient", but once I started ARM application by "./app_host DSP", that message stopped and everything worked fine.

    BTW, I saw you have the following in your code:

    sprintf(cbuf, "%s:%s", HOST, dspsystem);

    Did you miss the double quote before and after HOST and dspsystem?

    Regards,

    Jianzhong

  • Hi Jianzhongxu,

    Are you testing with any IPC example, if yes which one are you using?
    Could you perhaps attach the example here?

    Yes I missed the double quotes, when I inserted the code here on the forum...

    When I call MessageQ_open() on the DSP I do not get "virtio_rpmsg_bus virtio0: msg received with no recipient".

    I noticed that if I insert a printf after the Task_sleep(1) I get no printf output. But if I insert the printf before the task_sleep I the printf output can be seen:

    Int status;
    
    do {
          status = MessageQ_open( "HOST:dspsystem", &RemotequeId);
          if (status == MessageQ_E_NOTFOUND) {
            Task_sleep(1);
            System_printf("Test...\n");
          }
        } while(status == MessageQ_E_NOTFOUND);


    Regards,
    Kim

  • Hi Kim,

    I was testing IPC example ex02_messageq. Please see modified ipc_3_50_04_08/examples/OMAPL138_linux_elf/ex02_messageq/dsp/server.c in the attachment.

    /*
     * Copyright (c) 2013-2014, 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.
     */
    
    /*
     *  ======== Server.c ========
     *
     */
    
    /* this define must precede inclusion of any xdc header file */
    #define Registry_CURDESC Test__Desc
    #define MODULE_NAME "Server"
    
    /* xdctools header files */
    #include <xdc/std.h>
    #include <xdc/runtime/Assert.h>
    #include <xdc/runtime/Diags.h>
    #include <xdc/runtime/Log.h>
    #include <xdc/runtime/Registry.h>
    
    #include <stdio.h>
    
    /* package header files */
    #include <ti/ipc/MessageQ.h>
    #include <ti/ipc/MultiProc.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* local header files */
    #include "../shared/AppCommon.h"
    
    /* module header file */
    #include "Server.h"
    
    /* module structure */
    typedef struct {
        UInt16              hostProcId;         // host processor id
        MessageQ_Handle     slaveQue;           // created locally
        MessageQ_QueueId    hostQue;            // created by the host
    } Server_Module;
    
    /* private data */
    Registry_Desc               Registry_CURDESC;
    static Server_Module        Module;
    
    
    /*
     *  ======== Server_init ========
     */
    Void Server_init(Void)
    {
        Registry_Result result;
    
        /* register with xdc.runtime to get a diags mask */
        result = Registry_addModule(&Registry_CURDESC, MODULE_NAME);
        Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
    
        /* initialize module object state */
        Module.hostProcId = MultiProc_getId("HOST");
    }
    
    
    /*
     *  ======== Server_create ========
     */
    Int Server_create()
    {
        Int                 status = 0;
        MessageQ_Params     msgqParams;
        char                msgqName[32];
    
        /* enable some log events */
        Diags_setMask(MODULE_NAME"+EXF");
    
        /* create local message queue (inbound messages) */
        MessageQ_Params_init(&msgqParams);
        sprintf(msgqName, App_SlaveMsgQueName, MultiProc_getName(MultiProc_self()));
        Module.slaveQue = MessageQ_create(msgqName, &msgqParams);
    
        if (Module.slaveQue == NULL) {
            status = -1;
            goto leave;
        }
    
        Log_print0(Diags_INFO,"Server_create: server is ready");
    
        do {
            status = MessageQ_open(App_HostMsgQueName, &Module.hostQue);
            Task_sleep(10);
        } while (status == MessageQ_E_NOTFOUND);
    
        Log_print0(Diags_INFO, "Server_create: host queue opened");
    
    leave:
        Log_print1(Diags_EXIT, "<-- Server_create: %d", (IArg)status);
        return (status);
    }
    
    
    
    
    /*
     *  ======== Server_exec ========
     */
    Int Server_exec()
    {
        Int                 status;
        Bool                running = TRUE;
        App_Msg *           msg;
        MessageQ_QueueId    queId;
    
        Log_print0(Diags_ENTRY | Diags_INFO, "--> Server_exec:");
    
        while (running) {
    
            /* wait for inbound message */
            status = MessageQ_get(Module.slaveQue, (MessageQ_Msg *)&msg,
                MessageQ_FOREVER);
    
            if (status < 0) {
                goto leave;
            }
    
            if (msg->cmd == App_CMD_SHUTDOWN) {
                running = FALSE;
            }
    
            /* process the message */
            Log_print1(Diags_INFO, "Server_exec: processed cmd=0x%x", msg->cmd);
    
            /* send message back */
            queId = MessageQ_getReplyQueue(msg); /* type-cast not needed */
            MessageQ_put(queId, (MessageQ_Msg)msg);
        } /* while (running) */
    
    leave:
        Log_print1(Diags_EXIT, "<-- Server_exec: %d", (IArg)status);
        return(status);
    }
    
    /*
     *  ======== Server_delete ========
     */
    
    Int Server_delete()
    {
        Int         status;
    
        Log_print0(Diags_ENTRY, "--> Server_delete:");
    
        /* delete the video message queue */
        status = MessageQ_delete(&Module.slaveQue);
    
        if (status < 0) {
            goto leave;
        }
    
    leave:
        if (status < 0) {
            Log_error1("Server_finish: error=0x%x", (IArg)status);
        }
    
        Log_print0(Diags_INFO, "closing host queue");
        status = MessageQ_close(&Module.hostQue);
        if (status < 0) {
            Log_print0(Diags_INFO, "host queue closing has error");
        }
        else {
            Log_print0(Diags_INFO, "hot queue closed");
        }
    
    
        /* disable log events */
        Log_print1(Diags_EXIT, "<-- Server_delete: %d", (IArg)status);
        Diags_setMask(MODULE_NAME"-EXF");
    
        return(status);
    }
    
    /*
     *  ======== Server_exit ========
     */
    
    Void Server_exit(Void)
    {
        /*
         * Note that there isn't a Registry_removeModule() yet:
         *     https://bugs.eclipse.org/bugs/show_bug.cgi?id=315448
         *
         * ... but this is where we'd call it.
         */
    }
    
    Regards,

    Jianzhong

  • Hi Jianzhongxu,

    ex02_MessageQ
    I tried out the ex02_messageq example and updated the server.c to your attached code.

    I indeed see the "virtio_rpmsg_bus virtio0: msg received with no recipient", but it only occurs once in my dmesg output, but not constantly.

    When I start the ARM application as "app_host DSP", the DSP is still unable to open the ARM queue.

    In server.c the DSP is unable to move pass this while loop:

        Log_print0(Diags_INFO,"Server_create: server is ready");
    
        do {
            status = MessageQ_open(App_HostMsgQueName, &Module.hostQue);
            Task_sleep(10);
        } while (status == MessageQ_E_NOTFOUND);
    
        Log_print0(Diags_INFO, "Server_create: host queue opened");


    Task_sleep
    I also noticed that the Task_sleep() is not working correctly. I simply modified the while loop code to the following:
        Log_print0(Diags_INFO,"Server_create: server is ready");
        
        do {
            // status = MessageQ_open(App_HostMsgQueName, &Module.hostQue);
            System_printf("Before Task_sleep()\n");
            Task_sleep(1);
            System_printf("After Task_sleep()\n");
        } while (status == MessageQ_E_NOTFOUND);
    
        Log_print0(Diags_INFO, "Server_create: host queue opened");

     

    I am able to see the printf before the Task_sleep(1), but not after.
    However, Task_sleep(0) seems to work... Any ideas why this is happening?

    Modifications?
    I have not modified anything in the ex02_messageq example except the server.c you attached and using 0xC6100000 for DDR instead of 0xC3100000 in the config.bld file.

    Thanks & Regards,
    Kim

  • Hi Kim,

    To clarify, below is what I did to build and run the example:

    - Build DSP RTOS lib:
          cd processor_sdk_rtos_omapl138_6_03_00_106/
          source ./setupenv.sh
          export TOOLS_INSTALL_PATH=~/ti
          export SDK_INSTALL_PATH=~/ti
          make ipc_bios
    
          Binaries at: ipc_3_50_04_08/packages/ti/ipc/tests/bin/ti_platforms_evmOMAPL138_DSP/
      
    - Build ARM Linux lib:
          export PATH=~/ti/processor-sdk-linux-omapl138-lcdk-06.03.00.106/linux-devkit/sysroots/x86_64-arago-linux/usr/bin:$PATH
          export IPC_INSTALL_PATH=~/ti/ipc_3_50_04_08/
          export TI_RTOS_PATH=~/ti
          make ti-ipc-linux
    
          Binaries at: ipc_3_50_04_08/linux/src/tests
    
    - Build the examples:
          make ti-ipc-linux-examples
    
          Binaries at:
             - Host: ipc_3_50_04_08/examples/OMAPL138_linux_elf/ex02_messageq/host/bin/release/app_host
             - DSP: ipc_3_50_04_08/examples/OMAPL138_linux_elf/ex02_messageq/dsp/bin/release/server_dsp.xe674
    
    - Run the example on LCDK:
        tftp -g 192.168.1.235 -r app_host
        
        tftp -g 192.168.1.235 -r server_dsp.xe674
        
        ln -sfn /home/root/server_dsp.xe674 /lib/firmware/rproc-dsp-fw
        
        chmod +x app_host
        
        reboot the board
        
        ./app_host DSP
    
    - Stop messages virtio_rpmsg_bus virtio0:
        dmesg -n 4
    
    - Check DSP debug traces:
        mkdir /debug
        mount -t debugfs none /debug
        ./app_host DSP
        cat /debug/remoteproc/remoteproc0/trace0
    

    Regards,

    Jianzhong

  • Hi Jianzhongxu,

    Thank you for the detailed clarification.

    I managed to get an output similar to what you mentioned,.
     

     I also see the "virtio_rpmsg_bus" message constantly.


    The problem was that SYS/BIOS was using timer1 because Clock.timerId = 1 was defined in the Dsp.cfg script.
    I changed the applied timer to 3, then the ex02_MessageQ seems to run correctly on my board.

    I am guessing that timer0 and timer1 are reserved for Linux, and timer2 & timer3 can be used for SYS/BIOS.

    Thank you & Regards,
    Kim

  • Hi Kim,

    Glad that you have it working and thanks for sharing the information about timers. I'll close this thread. Please open a new one if you have further questions.

    Regards,

    Jianzhong