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(); u = adc_read(); 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.

Then, the PRU software development kit can be retrieved from here:

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:

pru_sw/app_loader/interface

A python version is even available in:

pru_sw/app_loader/python

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

Updates

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

http://processors.wiki.ti.com/index.php/Download_CCS#Code_Composer_Studio_Version_6_Downloads

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

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