Read()/write() RPMsg on Apalis

Hello,

I’m trying to get a minimal user space program to communicate bidirectionally with M4_0 on the Apalis.

I have added the following device tree overlay:

Note: For the following problems, I also tried changing the aliases for vdev2/3* to match vdev2/3, e.g. before vdev2vring0: vdev0vring0; after vdev2vring0: vdev2vring0. I also tried removing the @ in the alias for rpmsg0 to match the format of rpmsg1; before rpmsg0: rpmsg@0; after rpmsg0: rpmsg0.

I have built and loaded in uboot the M4 with rpmsg_lite_str_echo_rtos/cm4_core0 from NXP’s SDK 2.9.0 for MIMX8QM6xxxFF.

I modprobe imx_rpmsg_tty and run a minimal program in an attempt to read()/write() on /dev/ttyRPMSG30:

        int rpMsgFd = -1;
        struct termios tty;

        rpMsgFd = open("/dev/ttyRPMSG30", 0, O_RDWR | O_NOCTTY);
        if(rpMsgFd < 0) {
            return -1;
        }
        if(tcgetattr(rpMsgFd, &tty) < 0) {
            return -2;
        }
        cfmakeraw(&tty);
        if(tcsetattr(rpMsgFd, TCSANOW, &tty) < 0) {
            return -3;
        }

        rpmsgResult = write(rpMsgFd, &outgoingMsg, sizeof(outgoingMsg));
        if(rpmsgResult != sizeof(outgoingMsg)) {
            std::cerr << "Error sending RPMsg (" << rpmsgResult << ", " << errno << ", " << rpMsgFd << ").\n";
            continue;
        }

write() fails and returns -1, errno is 9 (bad file descriptor), with a file descriptor of 3. Since this isn’t a real file, I suspect errno may be invalid.

I can successfully use cat and echo, though:

# cat /dev/ttyRPMSG30 &
# echo test > /dev/ttyRPMSG30
test

This minimal example is what I’ve resorted to after trying to use a custom M4 program that uses the bare metal RPMsg library with the following preprocessor symbol modification in rpmsg_config.h:
#define RL_USE_STATIC_API (1)

Performing the same cat/echo above resulted in the M4 replying with a pre-programmed message, but the M4 subsequently received unexpected infinite messages, which it claimed were sourced by the Linux side, whose contents were the original M4->Linux message, but 1-2 bytes at a time, and eventually garbage. These erroneous receptions resulted in more M4->Linux transmissions. The addresses of the received message data seemed to be incrementing by 0x200 in the vdevbuffer memory, which appears to be correct.

I also attempted adding the following symbol to rpmsg_config.h, which was present in the RPMsg API documentation but not rpmsg_config.h itself. The documentation claimed that it was needed in a Linux scenario, but was not used in any of the SDK examples. No change in behavior was observed.
#define RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION (1)

Aside from using the static API and using my own Rx callback function to store the received data, I’m not sure what’s going wrong here. I will try to incrementally convert the example program into the static with custom callback program to see where things go wrong.

I can provide a minimal version of this M4 program if desired, but I think the write() problem is the first hurdle.


Apalis i.MX8QM 4GB IT v1.1 D
Apalis Evaluation Board Rev. 1.1
Custom Yocto build using toradex-manifest branch kirkstone-6.x.y

Hi, I’m the Toradex AI Assistant. I’m in early beta, and I would appreciate your feedback.
The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello,

For the issue you’re encountering with write() failing with errno 9 (EBADF, Bad file descriptor) when attempting to communicate with the M4 core on the Apalis iMX8 via /dev/ttyRPMSG30, it seems there might be an issue with how the file descriptor is being managed or a misunderstanding in the device file’s usage.

Firstly, ensure that the file descriptor is correctly opened. The open() function call seems incorrect. The open() function prototype is int open(const char *pathname, int flags); or int open(const char *pathname, int flags, mode_t mode); if you’re specifying the mode explicitly for files that are created. In your code snippet, the order of arguments appears to be incorrect. It should be:

rpMsgFd = open("/dev/ttyRPMSG30", O_RDWR | O_NOCTTY);

The 0 argument is not necessary and might be causing the issue. The correct usage does not include a 0 as the second argument if you’re not specifying the mode (which is not needed for opening character devices like /dev/ttyRPMSG30).

Secondly, after correcting the open() call, if you’re still facing issues, consider verifying the permissions of /dev/ttyRPMSG30. Ensure the user running your application has the necessary permissions to read from and write to the device file. This can be a common oversight.

Regarding the behavior observed with your custom M4 program and the reception of unexpected messages, it’s crucial to ensure that the message buffers are correctly managed and that the RPMsg channel is properly synchronized between the Linux side and the M4. Mismanagement of buffers or incorrect synchronization can lead to the issues you described, such as receiving partial or garbled messages.

The RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION configuration is indeed intended for scenarios where the consumer (Linux side) notifies the producer (M4 side) that it has consumed a buffer, allowing for efficient buffer management. However, its effectiveness depends on correct implementation on both sides of the RPMsg channel.

For troubleshooting, starting with a minimal and verified working example on both the Linux and M4 sides is a good approach. Incrementally adding complexity can help isolate the issue. Since you mentioned the possibility of providing a minimal version of the M4 program, starting with a known working example from the NXP SDK or Toradex documentation and then making minimal modifications could help identify where the behavior diverges

Please, also check if these links can help you solve your problem:

Running FreeRTOS on the Cortex-M4 of a Colibri iMX7 | Toradex Developer Center.

Hello @rraz,

Hey @rraz,

Have you attempted to try the ping-pong demo example-rpmsg-demo found here. ?

This gives a basic communication example between the m-core and the linux side of things. I would recommend testing the demo first.

-Eric