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.

TDA4VM: Notify A72 Linux app from DSPs

Part Number: TDA4VM
Other Parts Discussed in Thread: SYSBIOS

Hello!

Situation:

  • I have the Yocto Linux running on the A72 and I have a custom application running there.
  • The DSPs are currently running bare-metal (both C66 and C71)
    • I compile SYSBIOS and XDCTools stuff but I do not start the OS at the moment

What I want to do:

I want to send a notification from the DSPs to the application on the A72.
The notification does not need to contain data, I just must differentiate from which DSP the notification was sent.

What I have now on the C71 DSP:

#define IPC_RPMESSAGE_OBJ_SIZE 256U
#define RPMSG_DATA_SIZE (256U * 512U + IPC_RPMESSAGE_OBJ_SIZE)
uint8_t gCntrlBuf[RPMSG_DATA_SIZE] __attribute__((section("ipc_data_buffer"), aligned(8)));
uint8_t gRspBuf[RPMSG_DATA_SIZE] __attribute__((section("ipc_data_buffer"), aligned(8)));

static uint8_t ipcCntrlTskStack[64 * 1024] __attribute__((section(".bss:taskStackSection")))
__attribute__((aligned(8192)));

uint32_t fileio_rpmsg_endpt = 0;
RPMessage_Handle fileio_rpmsg_handle;
uint32_t fileio_rpmsg_remote_endpt = 0;

void initRpmsg()
{
    RPMessage_Params cntrlParam;
    RPMessage_Params params;
    int32_t ret = 0;

    RPMessageParams_init(&cntrlParam);
    cntrlParam.buf         = &gCntrlBuf[0];
    cntrlParam.bufSize     = RPMSG_DATA_SIZE;
    cntrlParam.stackBuffer = &ipcCntrlTskStack[0];
    cntrlParam.stackSize   = sizeof(ipcCntrlTskStack);
    ret                    = RPMessage_init(&cntrlParam);

    RPMessageParams_init(&params);
    params.requestedEndpt = 13;
    params.buf            = &gRspBuf[0];
    params.bufSize        = RPMSG_DATA_SIZE;
    fileio_rpmsg_handle   = RPMessage_create(&params, &fileio_rpmsg_endpt);
}

void sendMsg()
{
    int32_t ret = 0;
    char buf[10];
    std::sprintf(buf, "ping");

    ret = RPMessage_send(fileio_rpmsg_handle, IPC_MPU1_0, 13U, IPC_C7X_1, buf, std::strlen(buf));
}

What I have on the A72 app:

#define IPC_RPMESSAGE_OBJ_SIZE 256U
#define RPMSG_DATA_SIZE (256U * 512U + IPC_RPMESSAGE_OBJ_SIZE)
uint8_t buf[RPMSG_DATA_SIZE] __attribute__((section("ipc_data_buffer"), aligned(8)));
pthread_t task;
int unblockfd;

void* appIpcRpmsgRxTaskMain(void* arg)
{
    (void)arg;
    std::printf("appIpcRpmsgRxTaskMain\n");
    std::fflush(stdout);
    return nullptr;
}

int32_t appIpcCreateRpmsgRxTask()
{
    pthread_attr_t thread_attr;
    int32_t status = 0;

    unblockfd = eventfd(0, 0);
    if (unblockfd < 0)
    {
        status = -1;
        printf("IPC: ERROR: Unable to create unblock event !!!\n");
    }
    if (status == 0)
    {
        status |= pthread_attr_init(&thread_attr);
        if (status != 0)
        {
            printf("IPC: ERROR: Unable to set thread attr !!!\n");
        }
        if (status == 0)
        {
            status |= pthread_create(&task, &thread_attr, appIpcRpmsgRxTaskMain, nullptr);
        }
        pthread_attr_destroy(&thread_attr);
    }
    if (status != 0)
    {
        printf("IPC: ERROR: Unable to create RX thread !!!\n");
    }
    return status;
}

int main(int argc, char* argv[])
{
    rpmsg_char_init(nullptr);

    rpmsg_char_dev_t* rcdev;
    char eptdev_name[32] = {0};
    sprintf(eptdev_name, "rpmsg-char-%d-%d", DSP_C71_0, getpid());
    rcdev = rpmsg_char_open(DSP_C71_0, NULL, 13, eptdev_name, 0);

    appIpcCreateRpmsgRxTask();
}

Now I get the following error message on A72:

_rpmsg_char_find_rproc: 64800000.dsp is either not probed or not a remoteproc!

What am I doing wrong?
Sadly the documentation is not really good, although there are a lot of examples it's all full of OpenVx stuff and complicated.

Best regards

Jan Hieber

  • Hi Jan,

    Have you reviewed this application note regarding IPC development?

    https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-jacinto7/07_02_00_06/exports/docs/psdk_rtos/docs/user_guide/developer_notes_ipc.html

    You don't have to use OpenVx application. There is simple rpmsg example for you to follow.

    From the error, it doesn't look like DSP firmware is loaded.

    Could you explain how you load/run DSP firmware? Are you following the implementation from Processor SDK?

    In case of Processor SDK Linux, it will load ipc echo test firmware to DSP, which is similar to the baremetal code you have without OpenVX.

    The baremetal IPC code can be found here.

    https://software-dl.ti.com/jacinto7/esd/processor-sdk-rtos-jacinto7/07_02_00_06/exports/docs/pdk_jacinto_07_01_05_14/docs/userguide/jacinto/modules/ipc.html

    Regards,

    Stanley

  • Thanks Stanley for the fast answer,

    actually I could proceed further. The resource table on C71 was missing. Now Linux detects the C71 as remote proc (loaded via UBoot).

    I still get the message:

    _rpmsg_char_find_ctrldev: could not find the matching rpmsg_ctrl device for virtio0.rpmsg_chrdev.-1.13

    When doing this:

    rpmsg_char_init(nullptr);
    rpmsg_char_dev_t* rcdev;
    char eptdev_name[32] = {0};
    sprintf(eptdev_name, "rpmsg-char-%d-%d", DSP_C71_0, getpid());
    rcdev = rpmsg_char_open(DSP_C71_0, NULL, 13, eptdev_name, 0);

    Is there a way to gain some insights into the rpmsg driver?

    Br Jan

  • Hi Jan,

    Is this what you are looking for?

    https://git.ti.com/cgit/rpmsg/ti-rpmsg-char/about/

    Regards,
    Stanley

  • Yeah I already found that.

    I still get the message:

    _rpmsg_char_find_ctrldev: could not find the matching rpmsg_ctrl device for virtio0.rpmsg_chrdev.-1.13

    How can I find out what is missing?

    I see VirtIO stuff while booting:

    dmesg | grep virtio
    [    8.272115]  remoteproc0#vdev0buffer: registered virtio0 (type 7)
    [    8.365905] virtio_rpmsg_bus virtio0: rpmsg host is online

    And also the remoteproc:

    cat /sys/class/remoteproc/remoteproc0/name
    64800000.dsp
    

    sudo cat /sys/kernel/debug/remoteproc/remoteproc0/resource_table
    Entry 0 is of type vdev
      ID 7
      Notify ID 0
      Device features 0x1
      Guest features 0x1
      Config length 0x0
      Status 0x7
      Number of vrings 2
      Reserved (should be zero) [0][0]
    
      Vring 0
        Device Address 0xc0000000
        Alignment 4096
        Number of buffers 256
        Notify ID 0
        Physical Address 0x0
    
      Vring 1
        Device Address 0xc0010000
        Alignment 4096
        Number of buffers 256
        Notify ID 1
        Physical Address 0x0
    
    Entry 1 is version 1 of type trace
      Device Address 0xa3000000
      Length 0x80000 Bytes
      Reserved (should be zero) [0]
      Name trace:r5f0
    

  • To recap, I have this code on the C71 DSP:

        uint32_t selfId  = Ipc_getCoreId();
        uint32_t numProc = sizeof(remoteProc) / sizeof(uint32_t);
        ret              = Ipc_mpSetConfig(selfId, numProc, remoteProc);
        
        ret = Ipc_init(NULL);
        
        RPMessage_Params cntrlParam;
        RPMessage_Params params;
    
        RPMessageParams_init(&cntrlParam);
        cntrlParam.buf         = ctrlBuf;
        cntrlParam.bufSize     = RPMSG_DATA_SIZE;
        cntrlParam.stackBuffer = ctrlStack;
        cntrlParam.stackSize   = IPC_TASK_STACKSIZE;
        ret                    = RPMessage_init(&cntrlParam);
    
        RPMessageParams_init(&params);
        params.requestedEndpt = 13;
        params.buf            = &gRspBuf[0];
        params.bufSize        = RPMSG_DATA_SIZE;
        fileio_rpmsg_handle   = RPMessage_create(&params, &fileio_rpmsg_endpt);

    All those functions run succesfull, no errors. Is that enough? To get the RPMsg chrdev working like above?

    BTW compared to the SDK Linux I am missing the /sys/class/rpmsg/rpmsg_ctrl* entries. Who is responsible for creating these rpmsg_ctrl devs?

  • In order for Linux to be made aware of the endpoint created on the remote core, it needs to be announced by calling RPMessage_announce().

    Can you check if this is done in your code?

  • Thanks for your answer.

    I have that in my code now (from docu I thought it is only needed for receiving messages).

    Still I don't see the device come up.

    I boot the DSP via U-Boot. When Linux is booted I currently issue a command via custom shared memory mechanism which calls RPMessage_init(), RPMessage_announce() and so... When I do this I don't see any new messages via dmesg.

    This is what k3-dsp-rproc tells me, is that correct?

    [    7.841137] k3-dsp-rproc 64800000.dsp: assigned reserved memory node c71-dma-memory@c0000000
    [    7.841895] k3-dsp-rproc 64800000.dsp: configured DSP for IPC-only mode
    [    8.404130] k3-dsp-rproc 64800000.dsp: DSP initialized in IPC-only mode

    And some remoteproc messages from dmesg:

    [    7.819180] remoteproc remoteproc0: releasing 4d80800000.dsp
    [    7.840278] remoteproc remoteproc0: releasing 4d81800000.dsp
    [    7.851247] remoteproc remoteproc0: 64800000.dsp is available
    [    8.067519] remoteproc remoteproc1: releasing 41000000.r5f
    [    8.130274] platform 5c00000.r5f: configured R5F for remoteproc mode
    [    8.200735] remoteproc remoteproc1: releasing 5c00000.r5f
    [    8.241219] platform 5e00000.r5f: configured R5F for remoteproc mode
    [    8.268737] remoteproc remoteproc1: releasing 5e00000.r5f
    [    8.403943] remoteproc remoteproc0: powering up 64800000.dsp
    [    8.403956] remoteproc remoteproc0: Booting fw image j7-c71_0-fw, size 14604288
    [    8.413053]  remoteproc0#vdev0buffer: assigned reserved memory node c71-dma-memory@c0000000
    [    8.413228]  remoteproc0#vdev0buffer: registered virtio0 (type 7)
    [    8.413235] remoteproc remoteproc0: remote processor 64800000.dsp is now up

  • So I could advance a bit. I said I boot the DSPs via U-Boot.

    Unfortunately I was not able to make it work for this. I read the notes about late init of RPMSG and VirtIO but I wasn't able to make it work.

    Booting the DSPs via Linux remoteproc changed everything, I now see the kernel recognizing that there is a DSP it can talk to.

    There is one last bit which I'm missing at the moment. When I send messages from the C71 to the A72 I get this:

    virtio_rpmsg_bus virtio0: msg received with no recipient

    Currently I'm not sure but I will find out that last bit.

    So to sum it up: With U-Boot boot (late init) it did not work for me and the documentation was not good enough to really help, it was more pointing out a few functions and leaving many things open.

    Br Jan

  • Small update:

    I now managed to send messages from DSP to A72. Only problem left is the endpoint number on the A72. Linux choses automatically numbers > 1024 and increases the number with every iteration I start my program.

    Usually this is not a problem bc one can call RPMessage_getRemoteEndPt().

    Unfortunately that call always fails for me. When I debug into it, RPMessage_lookupName() fails because the queue is empty (IpcUtils_QisEmpty()).

    So it looks like there is no announcement from A72.

    My code on A72 currently is this:

            rpmsg_char_init(nullptr);
    
            rpmsg_char_dev_t* rcdev;
            char eptdev_name[32] = {0};
            sprintf(eptdev_name, "rpmsg-char-%d-%d", DSP_C71_0, getpid());
            rcdev = rpmsg_char_open(DSP_C71_0, NULL, 0, eptdev_name, 0);
            
            if (rcdev == nullptr)
            {
            }
            else
            {
                char reply_msg[20];
                memset(reply_msg, 0, 20);
                std::printf("reading...\n");
                size_t ret = read(rcdev->fd, reply_msg, 1);
                ...

    So for me whats missing is the announcement on the A72. I cannot see how exactly that can be done :/