AM6442: RPMsg/IPC: How to implement non-blocking or timeout send for RPMsg char device in Linux?

Part Number: AM6442

Tool/software:

Hi,

I’m working on a multi-core IPC system using RPMsg on a TI SoC. From user space I send messages to remote cores via the RPMsg character device (e.g. /dev/rpmsgX). The problem: write() blocks indefinitely when the remote endpoint is not ready.

I tried calling select() / poll() on the fd before write(), but select() always times out (errno 110 / ETIMEDOUT) even though a plain blocking write() succeeds when the remote becomes ready shortly after. It looks like the RPMsg char device might not expose write-readiness the same way sockets/pipes do.

  • Is there a recommended way to implement a non-blocking or timeout send for RPMsg char devices on Linux?

  • Do standard RPMsg char drivers implement poll()/select() for write readiness? If not, are there known patches or driver options to enable that?

  • Any alternative techniques to avoid indefinite blocking on write() if the remote endpoint is not ready? (e.g., driver changes, kernel API, user-space pattern)

  • Any TI-specific APIs, examples, or best practices for robust send-with-timeout in RPMsg-based apps?

Regards,

Mary

  • Hello Mary,

    I have not done testing myself with these functions at this point in time. But my general understanding is that calling open() with O_NONBLOCK or O_NDELAY will allow you to do a non-blocking write, and poll() will allow you to poll until an RPMsg is received. You can set a timeout value with poll(). I am not sure if there is a way to implement a timeout with open().

    We should support all "standard" RPMsg features. We have not implemented any TI-specific APIs for interacting with the RPMsg driver.

    More information here:
    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1248401/processor-sdk-am62x-question-of-ti-rpmsg-char-scripts-specifically-the-recv_msg-method/4731803#4731803

    Please keep me updated as you run experiments and figure things out! Eventually I would like to add information about writing and reading RPMsg from Linux userspace to the Multicore academy: https://dev.ti.com/tirex/explore/node?node=A__AeQbQhHUWUoNbbj86zUSgg__AM64-ACADEMY__WI1KRXP__LATEST

    Regards,

    Nick

  • Part Number: AM6442

    Tool/software:

    Hi..

     I am working on Rpmsg transfer between different cores.I need to implement a timeout logic for sending/writing the data to created fd. Timeout logic means, If the core receiving the data not ready, sleep and continue writing again. I have tried select()/poll()/setsockopt() etc...But not working.Is there any other method that support for adding the timeout logic.

    Thanks and Regards

    Shiny K George

  • Hello Shiny K George,

    Are you working with Mary on this topic? If so I will move this discussion over to her thread so that we can keep the conversation in one place:
    AM6442: RPMsg/IPC: How to implement non-blocking or timeout send for RPMsg char device in Linux?

    I gave an initial response on that thread.

    Regards,

    Nick

  • Hello Nick,

    Thanks for the clarification and the references. I’ll try this out on my side and will keep you updated on the results.

    Regards,
    Mary

  • Thanks Nick for your immediate reply..yes,we are working together.

  • Hi Nick,

    Based on previous suggestions, I tried to implement timeout logic using poll() by setting the endpoint to non-blocking mode. However, the implementation is not working as expected.

    I tried changing:-

    rpmsg_char_dev_t *rcdev;

    int flags = O_NONBLOCK; // <--- ADDED O_NONBLOCK HERE // ...

    rcdev = rpmsg_char_open(rproc_id, dev_name, local_endpt, remote_endpt, eptdev_name, flags); // ...

    Then used poll()-based Send Function:

    static int send_with_poll_deadline(int fd, const void *buf, size_t len, int deadline_ms)
    {
    int ret;
    struct pollfd pfd;

    if (len == 0) return 0;

    pfd.fd = fd;
    pfd.events = POLLOUT;
    pfd.revents = 0;

    // Wait for the descriptor to become writable
    ret = poll(&pfd, 1, deadline_ms);

    if (ret < 0) {
    perror("poll error in send_with_poll_deadline");
    return -errno;
    }

    if (ret == 0) {
    // Timeout
    return -ETIMEDOUT;
    }

    // Check for writability and errors
    if (!(pfd.revents & POLLOUT)) {
    if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
    return -EIO;
    }
    return -EAGAIN; // Should not happen after a successful poll
    }

    // Attempt the write now that poll indicates it's safe
    ret = send_msg(fd, (char*)buf, (int)len);

    if (ret < 0) {
    // Handle failure in send_msg
    return -errno;
    }

    if ((size_t)ret != len) {
    // Partial write
    return -EIO;
    }

    return 0; // Success
    }

    The application immediately fails with a timeout (-ETIMEDOUT) from poll(), even though the R5F is running and ready to receive messages and trying to send again.

    I have tried 

    int fd = rcdev->fd;

    // Get the file descriptor

    int current_flags = fcntl(fd, F_GETFL, 0);

    if (current_flags == -1) {

    perror("fcntl F_GETFL");

    return -1;

    }

    if (fcntl(fd, F_SETFL, current_flags | O_NONBLOCK) == -1) {

    perror("fcntl F_SETFL O_NONBLOCK");

    return -1;

    }

    i am expecting  poll() to return successfully within the SEND_DEADLINE_MS (500 ms) when the R5F core is running and ready, allowing the message to be sent, or return -ETIMEDOUT if the R5F fails to respond or the buffer is perpetually full.Plese help me to implement this feature.

    Thanks and Regards.

    Shiny

  • For future readers, Mary and Shiny K George are working together on this project. Since there are 2 threads asking the same question, I am going to merge both threads here so that we can have a single discussion. If new questions pop up, we can split those off into separate threads.

  • Hello Shiny,

    I would expect that poll() is waiting to receive an RPMsg message from the R5F. So is the R5F programmed to send the first RPMsg?

    If the R5F is running the IPC_Echo example, then the R5F is also waiting for an RPMsg to be sent. In that case, I would expect you to test like this:

    Linux userspace
    open() <-- send RPMsg trigger
    poll() <-- wait for R5F to echo back the RPMsg

    Regards,

    Nick