EmbeddedRelated.com
Blogs

Using the Beaglebone PRU to achieve realtime at low cost

Fabien Le MentecApril 25, 20148 comments

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:

This article is available in PDF format for easy printing

PSU control application

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

bbb

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

 am335x

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

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

block diagram

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


[ - ]
Comment by texaneMay 19, 2014
I just added 2 links in the article references section for those interested in programming the PRU using the C language.
[ - ]
Comment by TonyTMay 19, 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 texaneMay 19, 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 dgrizzleJune 19, 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 leoGrabaOctober 19, 2015
Thanks for the article and sharing your knowledge, it was very helpful!
[ - ]
Comment by alekMarch 21, 2016
hi texane and thanks for your work, how did you acces to adc from prus?
[ - ]
Comment by mbparsaJanuary 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 texaneJanuary 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.

Please login (on the right) if you already have an account on this platform.

Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: