# Introduction

I work as an engineer in a synchrotron facility. A few weeks ago, I helped the people in charge of the power supply developments to integrate a realtime control algorithm on a prototype platform: a BeagleBone Black (BBB) running Linux. I had already worked with this board in the past, and I found it very interesting given its excellent resources versus price ratio (around 40 euros). This time, I was impressed by its realtime capabilities. I thought it would be a good idea to share my experience here.

In this application, the control loop core algorithm looks as follows:

while (1)
{ timer_wait();
d = update_pid(pid_state, u);
pwm_set_duty(d);
}

The standard Linux operating system can not be used as the control loop has realtime constraints too hard to be met. Thus, typical designs run the loop an on a dedicated unit, either a FPGA or even a specialized microcontroller. This unit communicates with the main CPU over a PCIe serial point to point link. A user application can interact with the power supply interface over the network using a TCP channel. This architecture is depicted in the diagram below:

While this architecture works well, the power supply unit (PSU) control board may cost several hundred euros, or even more if a specific design is made in low quantities. This is why the BBB was investigated: it is shipped with an am335x CPU that integrates 2 independant realtime units. By using these units to run the control loop, the FPGA and related communication links are removed and the overall costs is largely reduced. Also, the level of integration eases iteration during the development process.

# Platform overview

The BBB board is often compared with the raspberry PI (RPI):

http://beagleboard.org/Products/BeagleBone+Black

http://www.raspberrypi.org

Both are cheap boards using ARM CPUs. However, I find the BBB a much more interesting platform than the RPI, both from a peripheral and hardware documentation point of view. The BBB relies around the Texas Instruments am335x CPU:

http://www.ti.com/product/am3359

This CPU integrates 2 realtime units, known as the PRUs:

http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem

Strangely enough, Texas Instruments does not support the PRU. Instead, there is a community driven effort that provides a full development kit which includes documentation and code:

https://github.com/beagleboard/am335x_pru_package

A PRU has its own execution core (clocked at 200MHz) and memory. As I understand, its main purpose was to implement the equivalent of software bitbanging (ie. SPI ...) in dedicated hardware units instead of busying the main CPU. However, the PRU is much more powerful than that: it has a rich instruction set, and even a multiply accumulate unit. It can trigger or receive interrupts, access the main memory for sharing with the CPU. In our application, it also accesses the PWMs and read ADCs values. It also has a limited set of integrated peripherals. The following section details how to setup the PRU.

# Software setup

First, you have to configure linux so that it supports the PRU module. I personnally use LFS, a tool to generate minimal linux based system disk images:

https://github.com/texane/lfs

A documentation is available in:

doc/tex/main.pdf

There are still some hardcoded values here and there that prevent LFS to be used as is, but you may find it useful.

https://github.com/beagleboard/am335x_pru_package

It contains all the documentation, tools and examples to get started with the PRU. The assembler is in:

pru_sw/utils/pasm_source

It generates binary files from assembly source code. The generated files are then uploaded to the PRU using a library known as the application loader, available in:

A python version is even available in:

The following section shows an exemple on how to use the PRU.

# Examples

As an example, I will use the following repository:

https://github.com/texane/pru_sdk

Here again, some variables are hardcoded but it is quite usable. The documentation directory contains the 4 pdf files that I used during this project. The example directory contains unit tests showing how to use the different hardware modules required by the project (shared memory, ADCs, PWMs, MAC and timers). We will invesigate the timer example.

First, the Makefile is here:

example/pruss_iep/Makefile

It compiles 3 different files:

• a device tree script,
• the main program,
• the PRU program.

The device script is here:

example/pruss_iep/pru_enable-00A0.dts

It is compiled as an object file:

pru_enable-00A0.dtbo

dtbo files must be copied in the firmware directory, in this case:

/lib/firmware/pru_enable-00A0.dtbo

This object file is required by the linux kernel to enable the PRU. More generally, device tree files are used to describe device resources, as it can be seen in other examples from this repository. Those interested to know more can find a good introduction about the kernel device tree here:

http://free-electrons.com/pub/conferences/2013/elce/petazzoni-device-tree-dummies/

The main program file is here:

example/pruss_iep/main.c

It is a typical C program in charge of loading the PRU program in the PRU unit. It periodically reads values from a memory shared between the CPU and the PRU, and eventually terminates the PRU program upon user signal reception.

Then comes the actual PRU program code. It can be found here:

example/pruss_iep/iep.p

As you can see, the assembler comes with a preprocessor, handling comments and directives. Also, those of you familiar with the GNU assembler syntax should feel at home. I wont detail the code here, but feel free to ask questions. Note however that the PRU reference guide contains all the materials related to the instruction set.

Finally, running the application is done using the script:

example/pruss_iep/run.sh

It assumes that you copied the device tree object into:

/lib/firmware/pru_enable-00A0.dtbo

# Conclusion and further references

I hope this post sparked the interest to investigate the BBB as a platform for application with realtime requirements. The PRU may not be supported by TI, but there are plenty of communauty supported materials available on the web. Here are some of them I found interesting:

http://analogdigitallab.org/articles/beaglebone-black-introduction-pru-icss

http://elinux.org/BeagleBone_PRU

https://github.com/modmaker/BeBoPr

TI recently released a version of their Code Composer Studio for both Linux and Windows which allows to compile C code for the PRU. It ships with a standard library, and has float type support. I tested it only briefly, so any feedback is welcome. You can find more information here:

http://www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2014/04/30/bbb--pru-c-compiler

I published an article on how to use the C language to program the PRU:

//www.embeddedrelated.com/showarticle/603.php

Previous post by Fabien Le Mentec:
Using a RTLSDR dongle to validate NRF905 configuration
Next post by Fabien Le Mentec:
Using the C language to program the am335x PRU

[ - ]
Comment by May 20, 2014
I just added 2 links in the article references section for those interested in programming the PRU using the C language.
[ - ]
Comment by May 20, 2014
TI does provide some support (maybe not on Linux) such as a compiler.
The PRU's full name is PRU-ICSS (Programmable Realtime Unit and Industrial Communication Sub System) and was originally intended to implement real time industrial fieldbuses such as Profibus, EtherCAT, and Ethernet PowerLink; in fact, TI's AM335x-based ICE dev kit ships with sample code for these protocols.
[ - ]
Comment by May 20, 2014
Thanks for the comments. I read that TI does not provide support for the PRU on LINUX. I can find the reference if requested. Thanks for the tips regarding the PRU C compiler ... I am already on my way to test it !
[ - ]
Comment by June 20, 2014
Thanks for this.

I have investigated using the BBB for real-time applications but didn't find it suitable for the same reasons you listed.

Think I will spend some time investigating the PRU.
[ - ]
Comment by October 20, 2015
Thanks for the article and sharing your knowledge, it was very helpful!
[ - ]
Comment by March 22, 2016
hi texane and thanks for your work, how did you acces to adc from prus?
[ - ]
Comment by January 14, 2017

Thank for this great article, I have been always looking for such possibility to use PRU. One big problem for my is the 100 MB network is not suitable for my application and I am looking for a board  with 1GB Ethernet for realtime application, do u have any suggestion?

[ - ]
Comment by January 15, 2017

If you really need 1GB, I do not have a simple solution, sorry ...

To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.