Non-blocking read of RPMSG in ARM C code

I’m using remoteproc and need to have the ARM code check for a message from the PRU without stopping if there isn’t a message.
The examples I have been learning and ‘borrowing’ from all use read to read the RPMSG device on the ARM side. If there isn’t an incoming message, read just stops the program until there is one.
Is there an alternative? I’ve tried to apply both select() and poll() but they are both new to me in C and there isn’t much help online about them.

Hi @WalterCEden

I have had success using read() and setting the device file descriptor to be non-blocking. I based it on this You can set the file descriptor back to blocking by replacing flags | O_NONBLOCK with flags & ~O_NONBLOCK. The posts at the link also discuss options with select() and poll().

Hope this helps.


It appears that this has taken care of the issue.

Here’s the code it took to change read() to non-blocking in this usage on this version of Debian. I’ve pasted in the output of below for anyone who may be following or stumble on this later.

We are still testing this but so far it is working really well.

#define DEVICE_NAME		"/dev/rpmsg_pru30"
// set up file descriptor structure (this was existing already but including it here for clarity
struct pollfd pollfds[1];
		  int result;
// declare fcntl flag variable
int fcntl_flags;
// Open the rpmsg_pru character device file
	        	pollfds[0].fd = open(DEVICE_NAME, O_RDWR);
	            	 * If the RPMsg channel doesn't exist yet the character device
	            	 * won't either.
	            	 * Make sure the PRU firmware is loaded and that the rpmsg_pru
	            	 * module is inserted.
	            	if (pollfds[0].fd < 0) 
	            		printf("Failed to open %s\n", DEVICE_NAME);
	            		printf("Exiting program...\n");
	            		return -1;
	            	// now set the RPMSG incoming file read as a non-blocking read
                        // this is the new part that I added to fix the blocking
	            	fcntl_flags = fcntl(pollfds[0].fd,F_GETFL,0);  // get the current flag settings
			fcntl(pollfds[0].fd,F_SETFL, fcntl_flags | O_NONBLOCK);  // set the non-blocking bit in the flags
                        result = read(pollfds[0].fd, readBuf, MAX_BUFFER_SIZE);
               		printf("result is %d\n",result);  // if nothing to read, result will be -1
               		if (result > 0)
              		printf("Message from PRU is: %s ",readBuf);
                         // do whatever else you want to do in your application

Output of is…

debian@beaglebone:/var/lib/cloud9/EDEN/BP_POC$ sudo /opt/scripts/tools/
[sudo] password for debian:
dogtag:[ Debian Buster IoT Image 2021-02-15]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot SPL 2019.04-00002-gc9b3922522 (Aug 24 2020 - 16:42:18 -0500)]:[location: dd MBR]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot 2019.04-00002-gc9b3922522]:[location: dd MBR]
UBOOT: Booted Device-Tree:[am335x-boneblack-uboot-univ.dts]
UBOOT: Loaded Overlay:[AM335X-PRU-RPROC-4-19-TI-00A0]
UBOOT: Loaded Overlay:[]
UBOOT: Loaded Overlay:[]
UBOOT: Loaded Overlay:[]
/boot/uEnv.txt Settings:
pkg check: to individually upgrade run: [sudo apt install --only-upgrade ]
groups:[debian : debian adm kmem dialout cdrom floppy audio dip video plugdev users systemd-journal input bluetooth netdev i2c gpio admin spi iio docker tisdk weston-launch xenomai cloud9ide pwm eqep remoteproc]
cmdline:[console=ttyO0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk1p1 ro rootfstype=ext4 rootwait coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet]
dmesg | grep remote
[ 56.402008] Bluetooth: hci0: change remote baud rate command in firmware
[ 75.051571] remoteproc remoteproc0: wkup_m3 is available
[ 75.407933] remoteproc remoteproc0: powering up wkup_m3
[ 75.407965] remoteproc remoteproc0: Booting fw image am335x-pm-firmware.elf, size 217148
[ 75.408253] remoteproc remoteproc0: remote processor wkup_m3 is now up
[ 78.638424] remoteproc remoteproc1: is available
[ 78.665925] remoteproc remoteproc2: is available
dmesg | grep pru
[ 78.638424] remoteproc remoteproc1: is available
[ 78.638632] pru-rproc PRU rproc node pru@4a334000 probed successfully
[ 78.665925] remoteproc remoteproc2: is available
[ 78.666083] pru-rproc PRU rproc node pru@4a338000 probed successfully
dmesg | grep pinctrl-single
[ 1.021546] pinctrl-single 44e10800.pinmux: 142 pins, size 568
[ 1.493191] pinctrl-single 44e10800.pinmux: pin PIN74 already requested by 481a6000.serial; cannot claim for leds
[ 1.503737] pinctrl-single 44e10800.pinmux: pin-74 (leds) status -22
[ 1.510163] pinctrl-single 44e10800.pinmux: could not request pin 74 (PIN74) from group pinmux_bt_pins on device pinctrl-single
dmesg | grep gpio-of-helper
[ 1.034973] gpio-of-helper ocp:cape-universal: ready
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Hi, Walter,

Do be careful that there was a bug in the remoteproc framework which caused issues with non-blocking writes.

RCN pulled my patch and fixed it (so if it’s still broken, you can blame me instead of Robert :slight_smile: ), but depending upon your version you might trip over it.

Thanks! I think I have the version that has this in it.

If I’m understanding this correctly, the problem would manifest itself if I was sending multiple messages TO the PRU. Is that correct? We send one and then seconds/minutes later we could send one more.

I don’t know if we back-ported that patch to v4.19.x/v5.4.x/v5.10.x …

I was able to change the flags in the read() function to eliminate the blocking on read and get my code to work on the ARM side. Once we get through the big push we are on, I may get the updated version and see if that fixes it. What version of 4.xx should I pull to get the fix?