Enabling the UIO PRU Driver in Recent Kernels

Catch22.eu

Introduction

The AM335x processor used on the Beaglebone, hosts next to the ARM main CPU two additional CPU cores called PRU (Programmable Realtime Units). This brings next to mainline linux and connectivity, also real-time, lightning fast GPIO. A driver is needed to accommodate interaction between the ARM host processor and the PRU remote processors. Although the Remoteproc driver is now standard, the UIO driver is still used because of it's simplicity (compare this example with this one). This guide is intended to document how to enable the UIO PRU driver in newer Debian Beaglebone images.

Prerequisite: a working and compatible image

First off, this guide is based on a known to be working Beaglebone image. Testing shows that there's actually only one image on Beaglebone.org that is suitable, at least, in combination with a Beaglebone Green, which is used here (see also note 1 and 2 below regarding kernels and making bootable sd-cards):

image (beaglebone.org) UIO Remoteproc Remark
bone-debian-8.7-lxqt-armhf-2017-03-19-4gb.img no yes Remoteproc hard-coded in kernel
bone-debian-8.7-iot-armhf-2017-03-19-4gb.img no yes Remoteproc hard-coded in kernel
bone-debian-8.6-lxqt-4gb-armhf-2016-11-06-4gb.img yes yes Only usable image for BBG at time of writing
bone-debian-8.6-iot-armhf-2016-11-06-4gb.img ? ? Did not boot on BBG
bone-debian-8.6-iot-armhf-2016-12-09-4gb.img ? ? Did not boot on BBG
bone-debian-8.3-lxqt-4gb-armhf-2016-01-24-4gb.img no yes Does not have .dts source files that can be used
shown as "Debian 8.5 2016-05-13 4GB SD LXQT"


After downloading the image, writing it to an sd-card and booting the Beaglebone from it, the status of the uio driver can be polled:

lsmod | grep uio

which reveals:

uio_pdrv_genirq 3923 0
uio             10524 1 uio_pdrv_genirq

This could lead to the incorrect conclusion the uio driver has already been inabled. Therefore, the uio driver needs to be enabled, and the remoteproc driver disabled.

How to Enable the UIO driver

The steps essentially boil down to the following main steps:

  • enable the UIO driver and disable the Remoteproc driver in the device tree binary (dtb)
  • modify eUnv.txt to use the modified dtb
  • blacklist the Remoteproc drivers

The first step indicates that next to the normal way of enabling and disabling kernel drivers, modifying the device tree is needed to enable the UIO driver. As a side note, this also is the case for enabling the Wireless driver on a Beaglebone Green Wireless - it took a while to figure that out.

Locate the source files of the device tree binaries

When using the Beaglebone image downloaded from Beaglebone.org, at least the version used here, the source of the device tree binaries (dtb's) is provided in the /opt/source/ directory:

cd /opt/source/dtb-4.4-ti/

It's well possible this is also provided by the factory installed image on the EMMC of your Beaglebone. Otherwise the git repository can be cloned as well, but make sure the correct branch is selected (in this case the "4.4-ti" branch matching the kernel version of the image), by issuing the command "git clone -b 4.4-ti https://github.com/RobertCNelson/dtb-rebuilder dtb-4.4-ti --depth=1" in a suitable empty directory, e.g. /opt/source/.

Modify your dtb to enable the UIO driver

Check which board file you need to modify. As explained in the prerequisites above, each Beaglebone has it’s own .dtb file. It’s the corresponding source file that has to be modified to enable the UIO driver, for which the filename ends with .dts. In this case, the am335x-bonegreen.dts is modified as an example:

nano src/arm/am335x-bonegreen.dts

Then locate and uncomment the pruss uio part, and disable the remoteproc part:

#include "am33xx-pruss-uio.dtsi"
/* #include "am33xx-pruss-rproc.dtsi" */

Compile the board files and install by issuing the make command (assuming your're still in the /opt/source/dtb-4.4-ti directory where the Makefile is located:

make
sudo make install

Modify your uEnv.txt to use the modified dtb

Ensure the adapted device tree binary is used during boot by editing the /boot/uEnv.txt: sudo nano /boot/uEnv.txt

and uncomment the empty "#dtb=" by mentioning the corrected dtb in there:

dtb=am335x-bonegreen.dts

Blacklist the Remoteproc drivers:

Edit or add a blacklist file /etc/modprobe.d/pruss-blacklist.conf:

sudo nano /etc/modprobe.d/pruss-blacklist.conf

By adding the the 3 lines to this file:

blacklist pruss
blacklist pruss_intc
blacklist pru-rproc

And ensure uio_pruss is of course not mentioned here as blacklisted. Then reboot the Beaglebone:

sudo reboot

Check if UIO is enabled

Test to see if the device tree file loaded successfully:

lsmod |grep uio

This should now show:

uio_pruss       4928 0
uio_pdrv_genirq 3539 0
uio             8822 2 uio_pruss,uio_pdrv_genirq

Instead of the response shown earlier. As next step, check these additional guides how to code the PRU in C, and how to share memory between the ARM host and PRU processors. To support and or give feedback, feel free to comment on the beagleboard.org forum.

Closing Remarks

The Beaglebone is a challenging, open source Single Board Computer, with huge potential, but has a steep learning curve given it's complexity and way things are dealt with and change over time causing out of date guides and the like. Hopefully this guide remains to help out long enough and gets you going with the real interesting part - programming the PRU's themselves. Enjoy!

Notes

1) Apart from using an image for the complete OS, a kernel upgrade might also be workable. The linux-image-4.4.30-ti-r64 is the kernel used in the working image mentioned above, and linux-image-4.4.14-ti-r34 is the kernel used in another project mentioned on this site. Check beaglebone.org forum for more info as it's kind of a hit and miss what's working or not due to it's ongoing development.

2) Some brief instructions how to make a bootable sd-card in Debian after downloading the preferred image. First decompress the downloaded image:

unxz bone-debian-8.6-lxqt-4gb-armhf-2016-11-06-4gb.img.xz

Then copy the disk image to the micro-sd by the easiest method found so far:

sudo dd bs=4M if=bone-debian-8.6-lxqt-4gb-armhf-2016-11-06-4gb.img of=/dev/the_device you_found_with_lsblk && sync

3) It is also worth noting, that work is ongoing to be able to select either uio or remoteproc in uEnv.txt directly. It's unclear as for now if this will make the instruction on this page still applicable or not.