RPMsg - Single write and read example

Based on the examples provided I managed to build a function to read the RPMsg on the M4:
static int rpmsg_str_read(char* message)
{
int message_lenght;

    if(message == NULL){
        return -1;
    }

    /* If no message available, return zero */
    if (msg_count == 0){
        return 0;
    }

    /* Copy string from RPMsg rx buffer */
    message_lenght = app_msg[app_idx].len;
    assert(message_lenght < sizeof(app_buf));
    memcpy(app_buf, app_msg[app_idx].data, message_lenght);
    memcpy(message, app_buf, message_lenght);// copy app_buf to string input pointer "message"
    app_buf[message_lenght] = 0; /* End string by '\0' */
    message[message_lenght] = 0; /* End string by '\0' */

    /* Release held RPMsg rx buffer */
    rpmsg_release_rx_buffer(app_chnl, app_msg[app_idx].data);
    app_idx = (app_idx + 1) % STRING_BUFFER_CNT;
    /* Once a message is consumed, minus the msg_count and might enable MU interrupt again */
    app_rpmsg_enable_rx_int(true);

    return message_lenght;
}

Howerver I also need a “rpmsg_str_write()” to be able to write to the Linux core. I could not make it work ()trying both rpmsg_sendto_nocopy() and rpmsg_send() and all examples perform the write inside the read. Is there a restriction or a catch on just writing to the A7?

Regarding rpmsg_rtos example, you are free to send/receive simultaneously. send is put between recv_nocopy and recv_nocopy_free to avoid the need for FIFO or receive message storage. But you may switch from recv_nocopy + recv_nocopy_free to just recv. No issues doing simultaneous send / receive from different FreeRTOS tasks.

Bare metal examples rpmsg_read_cb() callback routine should put received data into FIFO and exit immediately. If rx interrupt is disabled inside of receive callback, then it should be reenabled immediately in the same callback routine, and not … in the main loop. If you disable rx for longer, Cortex-A side has chances to stall. And if rpmsg A->M buffers are exhausted, virtio?? may suspend transmission for 15 seconds…
So if you fix receive part with FIFO and disable/enable of interrupt (is it really required?), you will fix as well simultaneous rx/tx.

Why just don’t use rpmsg_rtos_recv() / rpmsg_rtos_send() as it done at pingpong_freertos demo ?
And what do you mean saying all examples perform the write inside the read ? Could you point to file name/ line(s) of code?

We are on Baremetal.

The read is working fine now, but the right doesn’t seem to reach the A7 core.

static void app_rpmsg_str_write(char* message, int message_lenght) //Not working
{
    static void *tx_buffer;
    static unsigned long size;

    if(message == NULL || message_lenght < 1){
        return;
    }

    
    /* Get tx buffer from RPMsg */
    tx_buffer = rpmsg_alloc_tx_buffer(app_chnl, &size, RPMSG_TRUE);
    assert(tx_buffer);
    /* Copy string to RPMsg tx buffer */
    memcpy(tx_buffer, message, message_lenght);
    /* Echo back received message with nocopy send */
    rpmsg_sendto_nocopy(app_chnl, tx_buffer, message_lenght, app_chnl->src);
    
   //rpmsg_send((struct rpmsg_channel *)app_chnl, message, message_lenght);
}

I also tried

rpmsg_send((struct rpmsg_channel *)app_chnl, message, message_lenght);

But when I

cat < /dev/RPMSG0

I get in the terminal:
virtio_rpmsg_bus virtio0: msg received with no recipient

Since the read part works I have created a new thread with only the remaining problem:
https://www.toradex.com/community/questions/59971/rpmsg-error-virtio-rpmsg-bus-virtio0-msg-received.html

Issue was in this routine: rpmsg_sendto_nocopy(app_chnl, tx_buf, len, app_chnl->src);

The correct last parameter is app_chnl->dst

Perfect that you solved your issue. Thanks for the feedback.