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.

AM2432: Logical end points

Part Number: AM2432
Other Parts Discussed in Thread: SYSCONFIG

Hello TI,

This question is regarding the logical end points that can be created during IPC Communication.

As the documentation says, Users can create RPMessage_Object with local end value in the range of 0 .. RPMESSAGE_MAX_LOCAL_ENDPT - 1. 

Can we create as many endpoints on a single core or does it need to be unique across the cores?

Because we want to establish an IPC communication between R5 and M4 and would like to differentiate the messages based on the endpoints for different protocols?

Thanks & regards

Teja 

  • Hi,

    Yes you can set same end point on the other remote cores. The only restriction is you have to set unique end points on a give core i.e., you cannot set end point 12 on r50_0 twice, but you can set end point 12 on core0_0 and also on core0_1 and send messages across seamlessly.

    Thanks,
    G Kowshik

  • Hi,

    Thanks for the reply.

    Lets say, If I  have two freertos tasks running on R5 core and I would like to create different local end points for the two tasks for implementing the IPC. is this possible? because the RPMessage_Object Must be either global or static.

    Thanks & Regards

    Teja   

  • Hi,

    I would like to create different local end points for the two tasks for implementing the IPC. is this possible?

    Yes definitely possible.

    because the RPMessage_Object Must be either global or static.

    Nope, the understanding of RPMessage_object is wrong. In the example only one object is created because only one end point is used, in your case simply add more objects OR create array of objects and assign them as per your need.

    Your code will change as follows

    RPMessage_Object hi;
    RPMessage_Object hello;
    
    RPMessage_CreateParams_init(&createParams);
    createParams.localEndPt = 10;
    status = RPMessage_construct(&hi, &createParams);
    DebugP_assert(status==SystemP_SUCCESS);
    
    RPMessage_CreateParams_init(&createParams);
    createParams.localEndPt = 12;
    status = RPMessage_construct(&hello, &createParams);
    DebugP_assert(status==SystemP_SUCCESS);

    Hope this helps.

    Thanks,
    G Kowshik

  • HI,

    Thanks for the clarification.

    Based on the above explanation, I created a simple application and added two objects for IPC sending on M4 core and two objects for IPC receiving on the R5 core. For sending it works, but on the receiving side i only receive one message and the other does not work. 

    Do you have any similar example application available?

    Thanks

    Teja

  • Hi,

    Is the priority of the tasks given as same for both local end points? Please send us a snippet showing how they are declared.

    Thanks

  • Hi,

    Here are the snippets for the code. I took an empty example project provided in the SDk without freeRTOS and just implemented two functions with different endpoints as shown below

    FOR M4 CORE -> Sending

    #include <stdio.h>
    #include <string.h>
    #include <kernel/dpl/DebugP.h>
    #include <drivers/ipc_notify.h>
    #include <drivers/ipc_rpmsg.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"

    #define MAX_MSG_SIZE        (64u)
    /*
     * This is an empty project provided for all cores present in the device.
     * User can use this project to start their application by adding more SysConfig modules.
     *
     * This application does driver and board init and just prints the pass string on the console.
     * In case of the main core, the print is redirected to the UART console.
     * For all other cores, CCS prints are used.
     */
    RPMessage_Object gAckReplyMsgObject;
    RPMessage_Object ghelloObject;

    void init()
    {
        IpcNotify_syncAll(SystemP_WAIT_FOREVER);
    }

    void ipc_task()
    {
        RPMessage_CreateParams createParams;
        char msgBuf[MAX_MSG_SIZE];
        int32_t status;
        uint16_t remoteCoreId, remoteCoreEndPt, msgSize;

        RPMessage_CreateParams_init(&createParams);
        createParams.localEndPt = 12;
        remoteCoreId = CSL_CORE_ID_R5FSS0_0;
        remoteCoreEndPt =  11;
        status = RPMessage_construct(&gAckReplyMsgObject, &createParams);
        DebugP_assert(status==SystemP_SUCCESS);
        uint32_t msg = 0;

        snprintf(msgBuf, MAX_MSG_SIZE-1 ,"%d", msg);
        msgBuf[MAX_MSG_SIZE-1] = 0;
        msgSize = strlen(msgBuf) + 1;

        status = RPMessage_send(
                msgBuf, msgSize,
                remoteCoreId, remoteCoreEndPt,
                RPMessage_getLocalEndPt(&gAckReplyMsgObject),
                SystemP_WAIT_FOREVER);
        if(status == SystemP_SUCCESS)
        {
            DebugP_log("Sent Success \r\n");
        }
    }

    void ipc_hello()
    {
        RPMessage_CreateParams createParams;
        char msgBuf[MAX_MSG_SIZE];
        int32_t status;
        uint16_t remoteCoreId, remoteCoreEndPt, msgSize;

        RPMessage_CreateParams_init(&createParams);
        createParams.localEndPt = 5;
        remoteCoreId = CSL_CORE_ID_R5FSS0_0;
        remoteCoreEndPt =  6;
        status = RPMessage_construct(&ghelloObject, &createParams);
        DebugP_assert(status==SystemP_SUCCESS);
        uint32_t msg = 3;

        snprintf(msgBuf, MAX_MSG_SIZE-1 ,"%d", msg);
        msgBuf[MAX_MSG_SIZE-1] = 0;
        msgSize = strlen(msgBuf) + 1;

        status = RPMessage_send(
                msgBuf, msgSize,
                remoteCoreId, remoteCoreEndPt,
                RPMessage_getLocalEndPt(&ghelloObject),
                SystemP_WAIT_FOREVER);
        if(status == SystemP_SUCCESS)
        {
            DebugP_log("Sent Success hello \r\n");
        }

    }



    void empty_main(void *args)
    {
        /* Open drivers to open the UART driver for console */
        Drivers_open();
        Board_driversOpen();

        init();

        ipc_task();
        ClockP_sleep(1);
        ipc_hello();

        DebugP_log("All tests have passed!!\r\n");

        Board_driversClose();
        Drivers_close();
    }

    FOR R5 CORE -> Receiving

    #include <stdio.h>
    #include <kernel/dpl/DebugP.h>
    #include <drivers/ipc_notify.h>
    #include <drivers/ipc_rpmsg.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"

    /*
     * This is an empty project provided for all cores present in the device.
     * User can use this project to start their application by adding more SysConfig modules.
     *
     * This application does driver and board init and just prints the pass string on the console.
     * In case of the main core, the print is redirected to the UART console.
     * For all other cores, CCS prints are used.
     */
    #define MAX_MSG_SIZE        (64u)

    RPMessage_Object gAckReplyMsgObject;
    RPMessage_Object ghelloObject;

    void init()
    {
        IpcNotify_syncAll(SystemP_WAIT_FOREVER);
    }

    void ipc_task()
    {
        RPMessage_CreateParams createParams;
        char msgBuf[MAX_MSG_SIZE];
        int32_t status;
        uint16_t remoteCoreId, remoteCoreEndPt, msgSize;

        RPMessage_CreateParams_init(&createParams);
        createParams.localEndPt = 11;
        remoteCoreId = CSL_CORE_ID_M4FSS0_0;
        remoteCoreEndPt =  12;
        status = RPMessage_construct(&gAckReplyMsgObject, &createParams);
        DebugP_assert(status==SystemP_SUCCESS);
        status = SystemP_FAILURE;
        msgSize = sizeof(msgBuf);
        while(status != SystemP_SUCCESS )
        {
            status = RPMessage_recv(&gAckReplyMsgObject,
                               msgBuf,
                               &msgSize,
                               &remoteCoreId,
                               &remoteCoreEndPt,
                               20000);;
                if(status == SystemP_SUCCESS)
                {
                    DebugP_log("Recv Success \r\n");
                }
        }
    }

    void ipc_hello()
    {
        RPMessage_CreateParams createParams;
        char msgBuf[MAX_MSG_SIZE];
        int32_t status;
        uint16_t remoteCoreId, remoteCoreEndPt, msgSize;

        RPMessage_CreateParams_init(&createParams);
        createParams.localEndPt = 6;
        remoteCoreId = CSL_CORE_ID_M4FSS0_0;
        remoteCoreEndPt =  5;
        status = RPMessage_construct(&ghelloObject, &createParams);
        DebugP_assert(status==SystemP_SUCCESS);

        msgSize = sizeof(msgBuf);
        status = SystemP_FAILURE;

        while(status != SystemP_SUCCESS )
        {
            status = RPMessage_recv(&ghelloObject,
                               msgBuf,
                               &msgSize,
                               &remoteCoreId,
                               &remoteCoreEndPt,
                               SystemP_WAIT_FOREVER);
           if(status == SystemP_SUCCESS)
           {
             DebugP_log("Recv Success Hello \r\n");
           }
        }
    }

    void empty_main(void *args)
    {
        /* Open drivers to open the UART driver for console */
        Drivers_open();
        Board_driversOpen();
        init();

        ipc_task();
        ClockP_sleep(1);
        ipc_hello();

        DebugP_log("All tests have passed!!\r\n");

        Board_driversClose();
        Drivers_close();
    }

    OUTPUT

    [MAIN_Cortex_R5_0_0] Recv Success
    [BLAZAR_Cortex_M4F_0] Sent Success
    Sent Success hello
    All tests have passed!!

    R5 error - for receiving when ipc_hello() function called. This is where my code hangs

    let me know if you have any questions.

    Thanks & Regards

    Teja

  • Hi,

    What does this function do? Is it going to recv a message from M4F core?? Can you please try to increase the timeout to SystemP_forever from 20k ticks and try?

    void ipc_task()
    {
        RPMessage_CreateParams createParams;
        char msgBuf[MAX_MSG_SIZE];
        int32_t status;
        uint16_t remoteCoreId, remoteCoreEndPt, msgSize;
    
        RPMessage_CreateParams_init(&createParams);
        createParams.localEndPt = 11;
        remoteCoreId = CSL_CORE_ID_M4FSS0_0;
        remoteCoreEndPt =  12;
        status = RPMessage_construct(&gAckReplyMsgObject, &createParams);
        DebugP_assert(status==SystemP_SUCCESS);
        status = SystemP_FAILURE;
        msgSize = sizeof(msgBuf);
        while(status != SystemP_SUCCESS )
        {
            status = RPMessage_recv(&gAckReplyMsgObject,
                               msgBuf,
                               &msgSize,
                               &remoteCoreId,
                               &remoteCoreEndPt,
                               20000);;
                if(status == SystemP_SUCCESS)
                {
                    DebugP_log("Recv Success \r\n");
                }
        }
    }

  • Hi,

    yes, The above function receives the IPC message from the M4 core.

    we increased the timeout to SystemP_forever, still I ran into the same issue.

    The problem is in the other function ipc_hello(), where I want to receive an message that is sent by the M4 core.

    Please look at the console output in the attached image.

    Thanks

    Teja

  • Hi,

    For more understanding, I have created a simple table, please confirm if this is the behaviour you are seeing

    From To  End point Send status by M4 Receive status on R50_0
    M4 R50_0 11 Working Not working
    M4 R50_0 6 Working Not working

    M4 core local end points R50_0 local end points
    12 11
    5 6

    Are the above info correct???

    Also in the below code, I feel you shouldn't assign any values to the remoteCoreId and remoteCoreEndPt variables. Just declare them without defining and directly assign them to the recv API because recv APi will actually use the address of this variable and update the value accordingly. Even though this is not a major problem I would like to ask you to try it as how SDK examples has done it.

    The recv API automatically knows which core has sent the message on which local end point, you don't have to assign the variables or tell it before hand from which core the message is expected.

    remoteCoreId = CSL_CORE_ID_M4FSS0_0;
        remoteCoreEndPt =  12;
        status = RPMessage_construct(&gAckReplyMsgObject, &createParams);
        DebugP_assert(status==SystemP_SUCCESS);
        status = SystemP_FAILURE;
        msgSize = sizeof(msgBuf);
        while(status != SystemP_SUCCESS )
        {
            status = RPMessage_recv(&gAckReplyMsgObject,
                               msgBuf,
                               &msgSize,
                               &remoteCoreId,
                               &remoteCoreEndPt,
                               20000);;
                if(status == SystemP_SUCCESS)
  • Hi,

    A correction in the table. This is the behavior, I see until now.

    From To  End point Send status by M4 Receive status on R50_0
    M4 R50_0 11 Working Working
    M4 R50_0 6 Working Not working

    I will try it as described by you and let you know the status.

    Thanks

    Teja

  • Also in the below code, I feel you shouldn't assign any values to the remoteCoreId and remoteCoreEndPt variables. Just declare them without defining and directly assign them to the recv API because recv APi will actually use the address of this variable and update the value accordingly. Even though this is not a major problem I would like to ask you to try it as how SDK examples has done it.

    As per the discussion above, I implemented like the one provided in the TI SDK examples. But still I see the similar behavior as I described in the above table.

    Could be please provide some more information regarding this topic, because it is blocking us.

    Thanks

    Teja

  • Hi,

    Thanks for the update, I am currently running out of ideas regarding this. I have assigned this ticke to our IPC SDK expert and he should help you forward.

    Thanks,
    G Kowshik

  • HI TI,

    Do you have any update on this topic ?

    thanks & regards

    Poorna

  • Hi Poorna,

    Can you move the endpoint construct part into init() for both M4 and R5 cores? Consturct both endpoints before calling IpcNotify_syncAll().

    I'm suspecting that the issue is because M4 core is sending the message before the Endpoint registration is complete in the R5 side.

    Regards,

    Ashwin

  • Hi Raj,

    As you described, I moved the construct part to the init() function and tried it. But still It is running into the same issue.

    Could you please provide any examples that were done by TI with many logical end points?

    Regards

    Teja

  • Hi Teja,

    Currently we don't have an example in SDK which uses multiple endpoints. Below link points to IPC RPMsg Unit test case which uses multiple endpoints.

    mcupsdk-core/test/drivers/ipc_rpmsg/test_ipc_rpmsg.c at next · TexasInstruments/mcupsdk-core · GitHub

    If possible, can you share the updated code here? I can do a review.

    Regards,

    Ashwin