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-J784S4: R5F IPC communication hangs in RPMessage_recv

Part Number: PROCESSOR-SDK-J784S4

Hello experts,
I need help / advice on an IPC communication between R5F cores.

I want to demonstrate IPC communication between two R5F cores (mcu1_0 and mcu2_1)

Tool/software:

I'm using SBL boot via UART (

sbl_uart_img_mcu1_0_release.tiimage -> 
tifs.bin -> 
multicore.appimage)
SDK used 
ti-processor-sdk-rtos-j784s4-evm-11_00_00_06
Board used: J784S4_EVM



CORE1_0:


Core 1_0 runs modified sciserver_testapp_freertos example. I picked this because I need sciserver with freertos running on mcu1_0 apparently.

I've modified taskFxn to initialize IPC and send a string to mcu2_1 after sciserver is setup. Code attached:

uint32_t virt2phy_func(const void *virtAddr)
{ 
  return ((uint32_t)virtAddr);
}

void *phy2virt_func(uint32_t phyAddr) {
  uint32_t temp = phyAddr;
#if defined (BUILD_M4F_0)
    temp = phyAddr + 0x40000000;
#endif
  return ((void *)temp);
}

void newmsg_callback_func(uint32_t srcEndPt, uint32_t procId) 
{ 
  return;
}

void uart_print(const char *str) {
  UART_printf("%s", str);
  return;
}

uint8_t vqBuf[VQ_BUF_SIZE] __attribute__((section(".my_ipc_data_buffer"), aligned(8)));
uint8_t selfBuf[RPMSG_DATA_SIZE] __attribute__((section(".my_ipc_data_buffer"), aligned(8)));


static void taskFxn(void* a0, void* a1)
{
    int32_t ret                = CSL_PASS;
    Sciclient_ConfigPrms_t clientPrms;
    Sciserver_TirtosCfgPrms_t appPrms;
    char    *versionStr        = NULL;
    char    *rmpmhalVersionStr = NULL;

    /* Sciclient needs to be initialized before Sciserver. Sciserver depends on
     * Sciclient API to execute message forwarding */
    ret = Sciclient_configPrmsInit(&clientPrms);

    if (ret == CSL_PASS)
    {
        ret = Sciclient_boardCfgParseHeader(
            (uint8_t *) SCISERVER_COMMON_X509_HEADER_ADDR,
            &clientPrms.inPmPrms, &clientPrms.inRmPrms);
    }

    if (ret == CSL_PASS)
    {
        ret = Sciclient_init(&clientPrms);
    }

    /* Enable UART console print*/
    if (ret == CSL_PASS)
    {
        SciApp_consoleInit();
    }

    if (ret == CSL_PASS)
    {
        ret = Sciserver_tirtosInitPrms_Init(&appPrms);
        appPrms.taskPriority[SCISERVER_TASK_USER_LO] = SCISERVER_SETUP_TASK_PRI_LOW;
        appPrms.taskPriority[SCISERVER_TASK_USER_HI] = SCISERVER_SETUP_TASK_PRI_HIGH;        
    }

    if (ret == CSL_PASS)
    {
        ret = Sciserver_tirtosInit(&appPrms);
    }

    /* Set PMIC Shutdown Function Pointer */
    if (ret == CSL_PASS)
    {
        ret = Sciclient_setPmicShutdownCb(SciApp_pmicShutdown);
    }

    if (ret == CSL_PASS)
    {
        versionStr = Sciserver_getVersionStr();
        rmpmhalVersionStr = Sciserver_getRmPmHalVersionStr();
        SciApp_printf("Sciserver Testapp Built On: %s %s\n", __DATE__, __TIME__);
        SciApp_printf("Sciserver Version: %s\n", versionStr);
        SciApp_printf("RM_PM_HAL Version: %s\n", rmpmhalVersionStr);
    }

    #if defined LDRA_DYN_COVERAGE_EXIT
    UART_printf("\n LDRA Entry... \n");
    /* Add 3 minutes delay before printing execution history to make sure extended ut running on 
       mcu2_0 will complete it's execution, this will introduce additional code coverage by 
       sending requests to sciserver.
     */
    Osal_delay(180*1000);
    upload_execution_history();
    UART_printf("\n LDRA Exit... \n");
    #endif

    if (ret == CSL_PASS)
    {
        SciApp_printf("Starting Sciserver..... PASSED\n");
    }
    else
    {
        SciApp_printf("Starting Sciserver..... FAILED\n");
    }

    UART_printf("IPC_echo_test mcu1_1\n");
  
    uint32_t numProc = 1;
    uint32_t pRemoteProcArray[] = {IPC_MCU2_1};
    uint32_t selfProcId = IPC_MCU1_0;

    uint32_t selfPt = 10;
    uint32_t remotePt = 10;
    uint32_t remoteProcId = IPC_MCU2_1;

    Ipc_InitPrms initPrms;
    Ipc_VirtIoParams vqParam;

    /* Step1 : Initialize the multiproc */
    if (IPC_SOK == Ipc_mpSetConfig(selfProcId, numProc, pRemoteProcArray)) {
        UART_printf("IPC_echo_test (core : %s) (ID: %d).....\r\n", Ipc_mpGetSelfName(), Ipc_mpGetSelfId());

        /* Initialize params with defaults */
        IpcInitPrms_init(0U, &initPrms);

        initPrms.newMsgFxn = &newmsg_callback_func;
        initPrms.virtToPhyFxn = &virt2phy_func;
        initPrms.phyToVirtFxn = &phy2virt_func;
        initPrms.printFxn = &uart_print;

        if (IPC_SOK != Ipc_init(&initPrms)) {
            return;
        }
    } else {
        UART_printf("Ipc_mpSetConfig failed\n");
    }

    App_printf("Required Local memory for Virtio_Object = %d\r\n",
                    numProc * Ipc_getVqObjMemoryRequiredPerCore());

    /* Step2 : Initialize Virtio */
    vqParam.vqObjBaseAddr = (void *)vqBuf;
    vqParam.vqBufSize = numProc * Ipc_getVqObjMemoryRequiredPerCore();
    vqParam.vringBaseAddr = (void *)VRING_BASE_ADDRESS;
    vqParam.vringBufSize = IPC_VRING_BUFFER_SIZE;
    vqParam.timeoutCnt = 100; /* Wait for counts */
    // Ipc_initVirtIO(&vqParam);
    if (IPC_SOK != Ipc_initVirtIO(&vqParam))
    {
        // E_NOT_OK;
        UART_printf("Ipc_initVirtIO: E_NOT_OK\n");
    }

    App_printf("Required Local memory for RPMessage Object = %d\n",
                    RPMessage_getObjMemRequired());


    UART_printf("selfBuf @ %p\n", selfBuf);
    UART_printf("vqBuf @ %p\n", vqBuf);
    UART_printf("VRING_BASE_ADDRESS @ %p\n", (void*)VRING_BASE_ADDRESS);

    /* Step 3: Initialize RPMessage */
    RPMessage_Params selfRPMsgParam;
    RPMessageParams_init(&selfRPMsgParam);

    selfRPMsgParam.buf = selfBuf;
    selfRPMsgParam.bufSize = RPMSG_DATA_SIZE;
    selfRPMsgParam.stackBuffer = NULL;
    selfRPMsgParam.stackSize = 0U;
    selfRPMsgParam.requestedEndpt = remotePt;

    UART_printf("RPMessage_init: RPMSG_DATA_SIZE %d\n", RPMSG_DATA_SIZE);
    RPMessage_init(&selfRPMsgParam);
    
    RPMessage_Handle selfRPMsgHandle;
    selfRPMsgHandle = RPMessage_create(&selfRPMsgParam, &selfPt);
    if (selfRPMsgHandle == NULL) {
        UART_printf("RPMessage_create failed!\n");
        return;
    }
    UART_printf("Created RPMessage endpoint %d on core %s\n", selfPt, Ipc_mpGetSelfName());

    char sendMsg[512] = "hello from mcu1_0";
    uint32_t msgLen = strlen(sendMsg);

    UART_printf("A----------------------\n");
    int32_t status = RPMessage_send(selfRPMsgHandle, remoteProcId, remotePt,
                                    selfPt, (void *)sendMsg, msgLen);

    if (status != IPC_SOK) {
        UART_printf("Failed: RPMessage %s ----> %s\nMsg: %s\n", Ipc_mpGetSelfName(),
                    Ipc_mpGetName(remoteProcId), sendMsg);
        UART_printf("remoteProcId %d\n", remoteProcId);
    } else {
        UART_printf("Success: RPMessage %s ----> %s\nMsg: %s\n",
                    Ipc_mpGetSelfName(), Ipc_mpGetName(remoteProcId), sendMsg);
    }
}


I've also modified linker script so it includes my_ipc_data_buffer

(path to linker script ti-processor-sdk-rtos-j784s4-evm-11_00_00_06/pdk_j784s4_11_00_00_21/packages/ti/drv/sciclient/examples/sciserver_testapp/linker_r5_freertos_release.lds)

#define DDR0_ALLOCATED_START 0xA0000000
#define MCU1_0_DDR_SPACE_BASE    (DDR0_ALLOCATED_START + 0x00400000)

MEMORY
{
    VECTORS (X)                 : ORIGIN = 0x00000000 , LENGTH = 0x00000040
    R5F_TCMA0(RWIX)             : ORIGIN = 0x00000040 , LENGTH = 0x00007F00
    R5F_TCMB0(RWIX)             : ORIGIN = 0x41010100 , LENGTH = 0x00007F00
    SBL_USED_OCMC_RAM           : ORIGIN = 0x41C01000 , LENGTH = 0x2F000
    OCMC_RAM_BOARD_CFG (RWIX)   : ORIGIN = 0x41c80000 , LENGTH = 0x2000
    /* Sciserver App Space */
    OCMC_RAM_SCISERVER (RWIX)   : ORIGIN = 0x41C82000 , LENGTH = 0x00060000
    OCMC_RAM_X509_HEADER1 (RWIX) : ORIGIN = 0x41cffb00 , LENGTH = 0x500 /* covers header for J7200/J721E */
    OCMC_RAM_X509_HEADER2 (RWIX) : ORIGIN = 0x41cfdb00 , LENGTH = 0x500 /* covers header for J721S2 */
    MCU1_0_DDR_SPACE (RWIX)	: origin=MCU1_0_DDR_SPACE_BASE    length=0x00C00000	/*  12MB */
}

SECTIONS
{
    .freertosrstvectors : {} palign(8) > VECTORS
    .bootCode           : {} palign(8) > R5F_TCMA0
    .startupCode        : {} palign(8) > R5F_TCMA0
    .text.hwi           : {} palign(8) > R5F_TCMA0
    .startupData        : {} palign(8) > R5F_TCMA0, type = NOINIT
    .text               : {} palign(8) > OCMC_RAM_SCISERVER
    .my_ipc_data_buffer (NOINIT) : {} palign(128)	> MCU1_0_DDR_SPACE
    
    ...


I'm using MCU1_0_DDR_SPACE

All of this is compiled with

 make -s -j BOARD=j784s4_evm SOC=j784s4 BUILD_TYPE=release sciserver_testapp_freertos

CORE2_1:

I've this example (taken from ipc_testsetup.c) - this is a baremetal app

/*
* receiver goes on mcu2_1
*/
#include <stdint.h>
#include <ti/board/board.h>
#include <ti/csl/tistdtypes.h>
#include <ti/drv/ipc/examples/common/src/ipc_setup.h>
#include <ti/drv/ipc/ipc.h>
#include <ti/drv/ipc/soc/V4/ipc_soc.h>
#include <ti/drv/sciclient/sciclient.h>
#include <ti/drv/uart/UART_stdio.h>


uint32_t virt2phy_func(const void *virtAddr)
{
  return ((uint32_t)virtAddr);
}

void *phy2virt_func(uint32_t phyAddr) {
  uint32_t temp = phyAddr;
#if defined (BUILD_M4F_0)
    temp = phyAddr + 0x40000000;
#endif
  return ((void *)temp);
}

// void newmsg_callback_func(uint32_t srcEndPt, uint32_t procId) { return; }

void newmsg_callback_func(uint32_t srcEndPt, uint32_t procId) {
    UART_printf("MCU2_1: newmsg_callback_func called from procId=%d, srcEndPt=%d\n", procId, srcEndPt);
}

void uart_print(const char *str)
{
  UART_printf("%s", str);
  return;
}

uint8_t vqBuf[VQ_BUF_SIZE] __attribute__((section(".my_ipc_data_buffer"), aligned(8)));
uint8_t selfBuf[RPMSG_DATA_SIZE] __attribute__((section(".my_ipc_data_buffer"), aligned(8)));

int main(void) {
  Sciclient_ConfigPrms_t config;
  Sciclient_configPrmsInit(&config);
  Sciclient_init(&config);

  Board_initCfg boardCfg;
  boardCfg = BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_UART_STDIO;
  Board_init(boardCfg);

  // UART_printf("IPC_echo_test\n");

  uint32_t numProc = 1;
  uint32_t pRemoteProcArray[] = {IPC_MCU1_0};
  uint32_t selfProcId = IPC_MCU2_1;

  uint32_t selfPt = 10;
  uint32_t remotePt = 10;
  uint32_t remoteProcId = IPC_MCU1_0;

  Ipc_InitPrms initPrms;
  Ipc_VirtIoParams vqParam;

  /* Step1 : Initialize the multiproc */
  if (IPC_SOK == Ipc_mpSetConfig(selfProcId, numProc, pRemoteProcArray)) {
    UART_printf("IPC_echo_test (core : %s) .....\r\n", Ipc_mpGetSelfName());

    /* Initialize params with defaults */
    IpcInitPrms_init(0U, &initPrms);

    initPrms.newMsgFxn = &newmsg_callback_func;
    initPrms.virtToPhyFxn = &virt2phy_func;
    initPrms.phyToVirtFxn = &phy2virt_func;
    initPrms.printFxn = &uart_print;

    if (IPC_SOK != Ipc_init(&initPrms)) {
      return -1;
    }
  } else {
    UART_printf("Ipc_mpSetConfig failed\n");
  }

  /* Step2 : Initialize Virtio */
  vqParam.vqObjBaseAddr = (void *)vqBuf;
  vqParam.vqBufSize = numProc * Ipc_getVqObjMemoryRequiredPerCore();
  vqParam.vringBaseAddr = (void *)VRING_BASE_ADDRESS;
  vqParam.vringBufSize = IPC_VRING_BUFFER_SIZE;
  vqParam.timeoutCnt = 100; /* Wait for counts */
  if (IPC_SOK != Ipc_initVirtIO(&vqParam))
  {
      // E_NOT_OK;
      UART_printf("Ipc_initVirtIO: E_NOT_OK\n");
  }

  UART_printf("selfBuf @ %p\n", selfBuf);
  UART_printf("vqBuf @ %p\n", vqBuf);
  UART_printf("VRING_BASE_ADDRESS @ %p\n", (void*)VRING_BASE_ADDRESS);

  /* Step 3: Initialize RPMessage */
  RPMessage_Params selfRPMsgParam;
  RPMessageParams_init(&selfRPMsgParam);

  selfRPMsgParam.buf = selfBuf;
  selfRPMsgParam.bufSize = RPMSG_DATA_SIZE;
  selfRPMsgParam.stackBuffer = NULL;
  selfRPMsgParam.stackSize = 0U;
  selfRPMsgParam.requestedEndpt = remotePt;

  RPMessage_init(&selfRPMsgParam);
  RPMessage_Handle selfRPMsgHandle;
  selfRPMsgHandle = RPMessage_create(&selfRPMsgParam, &selfPt);

  if (selfRPMsgHandle == NULL) {
      UART_printf("RPMessage_create failed!\n");
      return 0;
  }
  UART_printf("Created RPMessage endpoint %d on core %s\n", selfPt, Ipc_mpGetSelfName());

  UART_printf("Waiting for message from %s...\n", Ipc_mpGetName(remoteProcId));

  char recvMsg[512] = {0};
  uint16_t msgLen = sizeof(recvMsg);

  Osal_delay(3*1000);
  // int32_t status = RPMessage_recvNb(selfRPMsgHandle,
  //                                 recvMsg, &msgLen, &remotePt,
  //                                 &remoteProcId);

  int32_t status = RPMessage_recv(selfRPMsgHandle, recvMsg, &msgLen,
                                  &remotePt, &remoteProcId, IPC_RPMESSAGE_TIMEOUT_FOREVER);

  UART_printf("After RPMessage_recv\n");
  if (status != IPC_SOK) {
    UART_printf("Failed: RPMessage %s <---- %s\nMsg: %s\n", Ipc_mpGetSelfName(),
                Ipc_mpGetName(remoteProcId), recvMsg);
  } else {
    UART_printf("Success: RPMessage %s <---- %s\nMsg: %s\n",
                Ipc_mpGetSelfName(), Ipc_mpGetName(remoteProcId), recvMsg);
  }
  return (0);
}



Linker script for it is:
...

/* Memory Map */
MEMORY
{
    /* MCU0_R5F_0 local view */
    MCU0_R5F_TCMA (X)  : origin=0x0        length=0x100

    /* MCU0_R5F_0 SoC view */
    MCU0_R5F0_ATCM (RWIX)   : origin=0x41000000 length=0x8000
    MCU0_R5F0_BTCM (RWIX)   : origin=0x41010000 length=0x8000
    /* MCU0_R5F_1 SoC view */
    MCU0_R5F1_ATCM (RWIX)   : origin=0x41400000 length=0x8000
    MCU0_R5F1_BTCM (RWIX)   : origin=0x41410000 length=0x8000

    MSMC3_DMSC_FW  (RWIX)   : origin=0x700F0000 length=0x10000         /* 64KB */

    /* Used in this file */
    DDR0_MCU_2_1 (RWIX)     : origin=0x9B000000 length=0x4000000         /* 64 MB */
    /* MSMC_SRAM */
    RESET_VECTORS (X)       : origin=0x70000000 length=0x40000    /* 256KB */
    MAIN_MSRAM_0            : origin=0x70040000 length=0xB0000 /* 1MB - 320KB */
}

/* Section Configuration */
SECTIONS
{
    .rstvectors    : {} palign(8)      > MCU0_R5F_TCMA
    .bootCode      : {} palign(8)      > MAIN_MSRAM_0
    .startupCode   : {} palign(8)      > MAIN_MSRAM_0
    .startupData   : {} palign(8)      > MAIN_MSRAM_0, type = NOINIT
    .text          : {} palign(8)      > DDR0_MCU_2_1
    .const         : {} palign(8)      > DDR0_MCU_2_1
    .rodata        : {} palign(8)      > DDR0_MCU_2_1
    .cinit         : {} palign(8)      > DDR0_MCU_2_1
    .pinit         : {} palign(8)      > DDR0_MCU_2_1
    .bss           : {} align(4)       > DDR0_MCU_2_1
    .far           : {} align(4)       > DDR0_MCU_2_1
    .data          : {} palign(128)    > DDR0_MCU_2_1
    .boardcfg_data : {} palign(128)    > MAIN_MSRAM_0
    .sysmem        : {}                > DDR0_MCU_2_1
    .data_buffer   : {} palign(128)    > DDR0_MCU_2_1
    /* Require to host MPU configuration code in MAIN_MSRAM_0 */
    .my_ipc_data_buffer (NOINIT) : {} palign(128)	> MAIN_MSRAM_0
    .CDD_IPC_MPU_CFG_OCMRAM : {} palign(8) > MAIN_MSRAM_0
    
    
    ...

All of this is compiled with:
make receiver_example_app BOARD=j784s4_evm BUILD_TYPE=release SOC=j784s4 CORE=mcu2_1

Both examples are build with 

#define IPC_EXCLUDE_CTRL_TASKS 1

MULTICORE CREATION:

Once compiled I create a multicore image with:
./MulticoreImageGen LE 55 multicore.appimage 8 sciserver_testapp_freertos_mcu1_0_release.rprc 9 sender_example_app_mcu1_1_release.rprc 10 sbl_mcux_0_dummy_app.rprc 11 receiver_example_app_mcu2_1_release.rprc

sender_example_app_mcu1_1_release is just a hello world print:

int main(void) 
{
UART_printf("Sender example\n");
return 0;
}


(I'm using sbl_mcux_0_dummy_app on mcu2_0 since "mcu2_0 can't be in a higher power state than mcu2_1" as found here https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1085821/faq-tda4vm-booting-mcu2_1-application-form-sbl)


-------------------------------

Similar question:
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1517544/tda4vm-sciclient_init-is-blocked-when-using-ipclld

PROBLEM:
Running this results with mcu2_1 hanging in RPMessage_recv. (Very rarely it works, but it's unpredictable)

Prints from mcu1_0:
Sciserver Testapp Built On: Jul 11 2025 09:42:12
Sciserver Version: 11.0.0-REL.PSDK.11.00.00.21
RM_PM_HAL Version: v11.00.09
Starting Sciserver..... PASSED
IPC_echo_test mcu1_0
IPC_echo_test (core : mcu1_0) (ID: 1).....
selfBuf @ a0400800
vqBuf @ a0400000
VRING_BASE_ADDRESS @ ac000000
RPMessage_init: RPMSG_DATA_SIZE 135424
Created RPMessage endpoint 10 on core mcu1_0
A----------------------
procId is 4
Success: RPMessage mcu1_0 ----> mcu2_1
Msg: hello from mcu1_0

Prints from mcu2_1:

IPC_echo_test (core : mcu2_1) .....
selfBuf @ 70040800
vqBuf @ 70040000
VRING_BASE_ADDRESS @ ac000000
Created RPMessage endpoint 10 on core mcu2_1
Waiting for message from mcu1_0...


After some debugging I know that RPMessage_recv hangs here:

        pOsalPrms->unLockHIsrGate(module.gateSwi, key);

        /*  Block until notified. */
          semStatus = pOsalPrms->lockMutex(obj->semHandle, timeout);

        key = pOsalPrms->lockHIsrGate(module.gateSwi);

So it seems that the core does not get notified. What am I missing?

WHAT I NEED HELP WITH / CLARIFICATION:

Notice how I'm putting my_ipc_buffer_data section in different memory ranges on mcu1_0 and mcu2_1 (I've also tried putting it in the same memory range, but not much luck in making it work reliably)

What else can I do to make this work?

Thanks in advance.

  • Hello,

    After some debugging I know that RPMessage_recv hangs here:

    RPMessage_recv is a blocking call if it doesn't receive the message then it will be blocked.

    How are you running the cores, is MCU1_0 coming up first followed by MCU2_1 ? Is MCU2_1 application running in while loop ?

    I have couple of suggestion for you ,if i understand correctly you want to do IPC communication between MCU1_0 and MCU2_1.

    You can use ipc_echo_testb_freertos on MCU1_0 and ipc_echo_test_freertos on MCU2_1. The ipc_echo_test example running on MCU1_0 core is integrated with sciserver and you have sci server and ipc echo test running parallely with sciserver being highest priority.

    Regards

    Tarun Mukesh

  • Thanks for quick response. I'll try what you suggested and let you know of the results.

  • RPMessage_recv is a blocking call if it doesn't receive the message then it will be blocked.

    I know this. But the messsage is never received.

    Is MCU2_1 application running in while loop ?

    No, I only have RPMessage_recv, once the message is received I return from main. I've attached the code, you can check it out.

    if i understand correctly you want to do IPC communication between MCU1_0 and MCU2_1.

    Yes, that's correct.

    How are you running the cores, is MCU1_0 coming up first followed by MCU2_1

    Once compiled I create a multicore image with:
    ./MulticoreImageGen LE 55 multicore.appimage 8 sciserver_testapp_freertos_mcu1_0_release.rprc 9 sender_example_app_mcu1_1_release.rprc 10 sbl_mcux_0_dummy_app.rprc 11 receiver_example_app_mcu2_1_release.rprc

    Then I boot multicore.appimage with SBL

    So, regarding my problem, why isn't the mcu1_0 triggering interrupt on mcu2_1. NOTE: Sometimes it does.
    My guess is that I have buffer overwrite. Can you check the memory map in the linker script? I attached it.

  • Hello,

    Once compiled I create a multicore image with:
    ./MulticoreImageGen LE 55 multicore.appimage 8 sciserver_testapp_freertos_mcu1_0_release.rprc 9 sender_example_app_mcu1_1_release.rprc 10 sbl_mcux_0_dummy_app.rprc 11 receiver_example_app_mcu2_1_release.rprc

    Then I boot multicore.appimage with SBL

    In this sequence MCU2_1 will always start prior to MCU1_0 and will wait be blocked on sciclient calls for sciserver ,since you don't have sciclient calls in baremetal application and it will move to IPC and waits on RPMessage_recv it is expected.

    Once MCU1_0 comes up it will start sending the message and this has to trigger the MCU2_1 compulsorily for each mailbox kick. 

    So, regarding my problem, why isn't the mcu1_0 triggering interrupt on mcu2_1. NOTE: Sometimes it does.

    Two questions are

    1) How did you check only some times interrupt comes ,other than UART print ? 

    2) Does interrupt come everyime and being served some time ? 

    You can connect debugger and see where MCU1_0 is halted or hanged.

    You can use ipc_echo_testb_freertos on MCU1_0 and ipc_echo_test_freertos on MCU2_1. The ipc_echo_test example running on MCU1_0 core is integrated with sciserver and you have sci server and ipc echo test running parallely with sciserver being highest priority.

    Have you tried this ?

    Regards

    Tarun Mukesh

  • 1) How did you check only some times interrupt comes ,other than UART print ? 

    I only have UART print. I don't have any other means to check it since I'm using boot over UART with makefile system (not CCS). My callback in the receiver app looks like this:

    void newmsg_callback_func(uint32_t srcEndPt, uint32_t procId) {
        UART_printf("MCU2_1: newmsg_callback_func called from procId=%d, srcEndPt=%d\n", procId, srcEndPt);
    }


    Sometimes it "works" but the callback parameters are wild, for example:

    MCU2_1: newmsg_callback_func called from procId=723523, srcEndPt=512
    and sometimes I get the right callback and everything works. I have erratic behaviour.

    ProcId is supposed to be 4 and srcEndPt is supposed to be 10
    2) Does interrupt come everyime and being served some time ? 

    Since I only have prints from the callback, I don't know which one is the case.

    You can connect debugger and see where MCU1_0 is halted or hanged.

    I'm getting prints from both MCU's (one via MCU_UART port and the other print via UART port). If I use RPMessage_recvNb which is non-blocking then program continues (without receiving anything) until return.

    You can use ipc_echo_testb_freertos on MCU1_0 and ipc_echo_test_freertos on MCU2_1. The ipc_echo_test example running on MCU1_0 core is integrated with sciserver and you have sci server and ipc echo test running parallely with sciserver being highest priority.

    Have you tried this ?

    I did try that (I used that as a guide to write code attached in the original question)

    MCU1_0 prints:

    DM Built On: Jun 19 2025 13:35:02
    
    Sciserver Version: 11.0.0-REL.PSDK.11.00.00.21
    
    RM_PM_HAL Version: v11.00.09
    
    Starting Sciserver..... PASSED
    
    IPC_echo_test (core : mcu1_0) .....
    
    mcu1_0 <--> mcu2_0, Ping- 10000, pong - 10000 completed
    
    mcu1_0 <--> mcu2_1, Ping- 10000, pong - 10000 completed


    while I get no prints from MCU2_0 or MCU2_1

    I used this to create multicore image foripc_echo_testb_freertos and ipc_echo_test_freertos:
    ./MulticoreImageGen LE 55 multicore.appimage 8 ipc_rtos_echo_testb_freertos_mcu1_0_debug.rprc 10 ipc_rtos_echo_test_freertos_mcu2_0_release.rprc 11 ipc_rtos_echo_test_freertos_mcu2_1_release.rprc


    But I want to have baremetal app on mcu2_1. 

    Why am I getting weird prints like so:

    MCU2_1: newmsg_callback_func called from procId=723523, srcEndPt=512

    Can you help with this? I believe my memory map is wrong, can you provide guidance?

    Thanks.

  • Hello Damjan,

    Sometimes it "works" but the callback parameters are wild, for example:

    MCU2_1: newmsg_callback_func called from procId=723523, srcEndPt=512

    Call back Function is called as soon as mailbox interrupt is received ,at this point of time procid and end point details are not yet known/recieved to the core. RPMessage_recv will be called later  and that is the point where we receive the details of end point and procid.So it prints garbage values in call back API It is understandable.

    while I get no prints from MCU2_0 or MCU2_1

    I used this to create multicore image foripc_echo_testb_freertos and ipc_echo_test_freertos:
    ./MulticoreImageGen LE 55 multicore.appimage 8 ipc_rtos_echo_testb_freertos_mcu1_0_debug.rprc 10 ipc_rtos_echo_test_freertos_mcu2_0_release.rprc 11 ipc_rtos_echo_test_freertos_mcu2_1_release.rprc

    Correct. There are no prints on Main UART so all ping pong is validated and printed on MCU UART only. The prints looks correct.

    But I want to have baremetal app on mcu2_1. 

    If you want bare metal we have that as well in SDK ipc_echo_baremetal_test please check.

    Can you help with this? I believe my memory map is wrong, can you provide guidance?

    I saw your memory map , you are using Main SRAM for MCU2_1 instead of DDR .Any reason to use ?  I will tell you to refer the linker files of ipc echo test and use the same.

    Regards

    Tarun Mukesh


  • Thanks you for the response.

    Correct. There are no prints on Main UART so all ping pong is validated and printed on MCU UART only. The prints looks correct.

    Alright. Good. Thanks for confirming that.

    If you want bare metal we have that as well in SDK ipc_echo_baremetal_test please check.

    I am aware of this. But I need my example to work, I'm comparing it with everything I'm able to find in the SDK.

    I saw your memory map , you are using Main SRAM for MCU2_1 instead of DDR .Any reason to use ?  I will tell you to refer the linker files of ipc echo test and use the same.

    There is no specific reason to do so. I tried placing it in various places, but only time it worked was when I do this:

    .my_ipc_data_buffer (NOINIT) : {} palign(128)	> MAIN_MSRAM_0


    I tried defining new section like so:
    IPC_COMM_MEM            : origin=0xa3400000 length=0x001ae500

    but then my receiver just hangs in RPMessage_recv. If my_ipc_data_buffer is in MAIN_MSRAM_0 at least sometimes I get correct reception.
    I also tried putting my_ipc_data_buffer in the same memory range on both MCU, but again I didn't get functional code. I am printing addresses of buffers so I know linker script does what I want it to:

    MCU1_0 (my_ipc_data_buffer is placed in IPC_COMM_MEM            : origin=0xa0400000 length=0x001ae500)

    IPC_echo_test (core : mcu1_0) (ID: 1).....
    selfBuf @ a0400800
    vqBuf @ a0400000
    VRING_BASE_ADDRESS @ ac000000

    MCU2_1 (my_ipc_data_buffer is placed in MAIN_MSRAM_0            : origin=0x70040000 length=0xB0000):

    Created RPMessage endpoint 10 on core mcu2_1
    Waiting for message from mcu1_0...
    I am procId=4 (name: mcu2_1)
    IPC_echo_test (core : mcu2_1) .....
    selfBuf @ 70040800
    vqBuf @ 70040000
    VRING_BASE_ADDRESS @ ac000000


    (Note: I tried this for MCU2_1 IPC_COMM_MEM            : origin=0xa3400000 length=0x001ae500)

    This might be too much to ask for, but would it be possible to arrange a call?

    Damjan Prerad

  • Hello Damjan,

    For Data transfer between cores the address space used is VRING_BASE_ADDRESS @ ac000000 so this should not be changed at all.

    Remaining buffer placements you need to take care from MCU1_0 and MCU2_1 the buffers should not be conflicting. If it corrupting or not we can understand if we connect the debugger and see the memory space.

    I tried defining new section like so:
    Fullscreen
    1
    IPC_COMM_MEM : origin=0xa3400000 length=0x001ae500
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    but then my receiver just hangs in RPMessage_recv. If my_ipc_data_buffer at least sometimes I get correct reception.
    I also tried putting my_ipc_data_buffer in the same memory range on both MCU, but again I didn't

    This is wrong idea , if you keep same section space for MCU1_0 and MCU2_1 there will memory corruption from both cores.


    MCU1_0 (my_ipc_data_buffer is placed in IPC_COMM_MEM            : origin=0xa0400000 length=0x001ae500)

    Fullscreen
    1
    2
    3
    4
    IPC_echo_test (core : mcu1_0) (ID: 1).....
    selfBuf @ a0400800
    vqBuf @ a0400000
    VRING_BASE_ADDRESS @ ac000000
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    MCU2_1 (my_ipc_data_buffer is placed in MAIN_MSRAM_0            : origin=0x70040000 length=0xB0000):

    Ideally this should work but i cannot confirm during run time if there are any other conflicts from other cores or else where.

    Regards

    Tarun Mukesh

  • To answer my own question, problem was in the file `r5_mpu_freertos.c`, it needs to be added in the makefile to make the VIRTIO memory non-cached.
    Linked in the makefile like so:

    ```
    CONFIG_BLD_LNK_r5f = $(PDK_INSTALL_PATH)/ti/drv/ipc/examples/common/$(SOC)/linker_r5f_$(CORE).lds

    ```

    If someone from TI is willing to add this info here https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-j784s4/09_00_00_02/exports/docs/psdk_rtos/docs/user_guide/developer_notes_ipc.html I think that would help a lot in the future.