Coding for the Beaglebone PRU in C

So, I've recently decided to get my head around the killer feature of the BeagleBone family - the two Programmable Realtime Units that sit alongside the ARM Cortex A8 core that you'll normally find running Linux. These PRUs are what really set the BeagleBone apart from other SBCs like the Raspberry Pi. To be honest, if you just need to run Linux on something small then the Pi may be a better choice - quad core 1.2Ghz A53 vs the BB's single core 1GHz A8. For anything that requires accurate and predictable timing though, an OS is not your friend. Anyway, enough about the PRU itself - I'm guessing that if you're here then you know what it is. Let's look at coding for it.

There is a fair bit of information on the PRU out there. A lot of it is good, but a lot of it is now a bit outdated. Things have moved on and it seems things have improved. For instance earlier guides concentrated on assembler because that was the only way back then. Now we have a PRU C compiler for a desktop IDE. Some guides talk about using UIO for interfacing, but that's now been deprecated in favour of remoteproc.

What I'll cover

I'm hoping to show you the quick and easy route to compile a simple C project in TI's Code Composer Studio and deploy and run it on the BB. I won't be doing anything tricky - just toggling a pin. What we hope to get is a nice clean square wave unaffected by whatever the A8 core is doing. I'll point you in the direction of some more complex examples but I'll leave that up to you.

Setting up your BeagleBone

Black or Green and probably other colours too. This is all done from the command line, starting with the latest Debian image on a microSD card. (I have the 2018-10-07 build Debian 9.5. My BB came with a 2016 build installed on the eMMC.)

Update your OS

This is optional but, why not. The following commands got things fully up to date.

                sudo /opt/scripts/tools/update_kernel.sh
                sudo apt update
                sudo apt upgrade
                sudo apt dist-upgrade
            

Enable FTP so you can transfer your code across

            sudo apt install vsftpd
            sudo nano /etc/vsftpd.conf
             [uncomment the line "write_enabled=YES"]
            sudo /etc/init.d/vsftpd start
        

Optional steps

I also freed up some pins that conflict with the ones that the PRU uses. I did this by editing /boot/uEnv.txt and uncommented the lines "disable_uboot_overlay_video=1" and similar for audio and wireless which I don't intend to use. Sensible, but not really needed for this example.

Setting up your PC

PRU compiler

In this guide I'll be compiling C code on my desktop using Code Composer Studio. I'm using Windows, but it should be the same for CCS on Linux. If you want to compile code on the BeagleBone itself then Mick Molloy's excellent Exploring BeagleBone book has this covered. Make sure it's the 2nd edition if you want to use remoteproc rather than UIO.

Install CCS

Download and install CCS. Make sure that you select the Sitara option as that's what we're targeting. Note that if you're adding Sitara to and existing CCS installation, you will need to make sure you have exactly the same version of the installer otherwise you'll be forced to do a new installation. Once it's installed, go to the App Center and add in the PRU compiler.

Install PRU software support package

This code is the essential stuff. It's not an installation as such, but a Git repository you'll need to clone or download. If you're going to clone it then pick a suitable folder (it will be referenced as include paths) and do:

git clone git://git.ti.com/pru-software-support-package/pru-software-support-package.git

Alternatively you can download it from here.

This support package contains the header files you need and also some nice examples in the example/am335x folder. I suggest you pick an example (such as PRU_gpioToggle) to start from. The critical part is that the include and include/am335x folders have some essential stuff.

blinky!So, here is our blinky project. The things to take note of are:

  • our main C file It's not doing much - just toggling a bit in the PRU output register R30.
  • resource_table_empty.h I haven't dug into what this file is for (yet) but it does seem to be needed.
  • other referenced header files in the PRU support package.

You can of course build your project from scratch. I did, following this TI PRU Training. However, this assumes that you'll be deploying and debugging with an XDS-110 emulator - which I'll hopefully be doing soon! Note that it also leaves out resource_table_empty.h even though I found it was required. Some very useful current info in there though.

Build and deploy

Get your code on the BeagleBone

If all goes to plan, you should be able to build in CCS by clicking the hammer icon. The fruits of your labour will be a single .out file in the Debug folder. You need to copy this file to your BeagleBone - probably via FTP - so that it can find its final resting place of the PRU. I won't go into details of copying a file over here.

Enable the PRU output

Each pin on the BB has multiple modes. In the case of our simple blinky, we're expecting pin 27 on the P9 header to be used for PRU output. From the PRU's point of view this is PRU0, register R30 bit 5, but to the BeagleBone it's P9_27. You will find all these pin mappings here. To enable it, you will need to execute the following:

config-pin P9_27 pruout

Copy your firmware to the PRU

deploy 1

Your out file needs go be copied to a special firmware folder to be accessible.

            sudo -i
            cp /home/debian/pru_blinky.out /lib/firmware/pru_blinky
        
deploy 2

Then we need to deploy it into PRU0 - confusingly referred to a remoteproc1. (PRU1 is remoteproc2. remoteproc0 is to do with the Cortex M3 co-processor.)

            cd /sys/class/remoteproc/remoteproc1
            echo 'pru_blinky' > firmware
        

Go!

deploy 3

Are you ready? It's taken us a while to get here but to finally run your cross-compiled C code in the PRU all you need is:

echo 'start' > state

See that big fat nothing that happened? That lack of an error message? That means your code is running! And look - we have a nice clean 1kHz square wave on the output pin. Hooray for square waves! My wife doesn't understand why I'm excited about this, but I'm sure you do.

a square wave

What's next?

Well, now that we have code running, it's time to do something more interesting. The examples you find in the PRU software support package are a good starting point for something more complex. It show things like communication between the PRUs and the main processor, interrupts, DMA, hardware UART, etc.

If you're ready to not just run your PRU code but step through it and debug it in CCS, you can do that too.