Using the Beaglebone PRU to achieve realtime at low cost
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
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:
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://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:
- Comments
- Write a Comment Select to add a comment
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.
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.
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?
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: