Skip to content
Pratim Ugale edited this page Aug 14, 2019 · 27 revisions

PRU User Space API

This is a Google Summer of Code 2019 project under BeagleBoard.org aimed at providing:

  1. An API for different programming languages to load/unload firmware, start/stop the PRUs and communicate with them from the Linux User Space using the RemoteProc, RPMsg drivers.
  2. Sample PRU firmware and User Space software to demonstrate the use of the project.

Project Details:

Code: https://www.github.com/pratimugale/PRUSS-Bindings
Mentors: Kumar Abhishek, Zubeen Tolani(ZeekHuge), Patryk Mężydło.
GSoC Project Page: https://summerofcode.withgoogle.com/projects/#5163407328673792
Introduction Video explaining about the project: https://www.youtube.com/watch?v=3Z2PxDIoCpE
Final Video: TBA

Introduction

PRU_ICSS_1
Starting with the PRU, a Programmable Real-Time Unit (PRU) is a low-latency microcontroller subsystem present on BeagleBoard devices, which provides real-time processing capability lacking in Linux. PRUs are part of the PRU-ICSS, “Industrial Communications SubSystem”. They are free from running on an operating system, so can be dedicated to a single function.
The PRU cores were created to be non-pipelined, single-cycle execution engines. This means that all instructions (except for memory reads and writes) complete in a single cycle. Since there is no pipeline, the PRU cores are completely deterministic: the PRU cores will not rearrange instructions during execution.
The PRU-ICSS can also read from or write to external pins in a single cycle using a PRU core register (R30). With a PRU core running at 200 MHz, this means that an external signal change can be detected in as little as 5 nanoseconds. This also means that the PRU can toggle external pins with a frequency of 5 nanoseconds. PRU_ICSS_2

How to develop firmware

Although not required while using this project, before creating general purpose Linux PRU firmware, one must understand the basics of how the RemoteProc and RPMsg frameworks work.

RemoteProc

The RemoteProc Linux driver is responsible for taking the PRU firmware from the Linux filesystem, parsing it for any resources that it must provide for the PRU (for example, interrupts or shared memory), loading the firmware into PRU instruction memory and data memory, and then start running the PRUs and stop them as required.

The resource table is necessary for the RemoteProc driver to work, even if it is empty.

RPMsg

User applications can require communication between the PRUs and the Arm core. Linux provides a method for this communication called RemoteProc Messaging (RPMsg). RPMsg fits into the RemoteProc framework. (CONTINUE ADD)

Now writing the firmware for PRU

PRU firmware can be written using C code or assembly language. C code is more approachable to new users, but it may not get the absolute best performance achievable. This is because the number of PRU clock cycles that will be used is unpredictable while using C. While using assembly, we are sure that every instruction will take exactly 5ns i.e. 1 PRU cycle to execute (except memory access).
Inline assembly code can be used while running the C firmware. Otherwise, a whole different R3.w2, which is a special register used by the compiler. The recommendation is to use C code in your firmware, and then see how well the provided C compiler optimizes the code by looking into the generated .asm file.

To check exactly how many clock cycles are being used for a particular task, the PRU can be run in the single_step mode by echoing into /sys/kernel/debug/remoteproc/remoteproc1 and /sys/kernel/debug/remoteproc/remoteproc2

debian@beaglebone:/sys/kernel/debug/remoteproc/remoteproc1$ echo 1 | sudo tee single_step

This functionality is also present in the PRUSS-Bindings.

Note: The entry remoteproc0 in /sys/kernel/debug/remoteproc/ relates to the Wakeup M3 (CM3) remoteproc driver that helps with low power tasks on the Cortex M3 co-processor in the AM33xx family of devices-it has no role in controlling the PRU-ICSS.

About the project and how it simplifies things

Although the PRUs are extremely useful for offloading deterministic tasks, using these processors has quite a learning curve. cpp-bindings-uml
An example of how the API can be used to accurately control stepper motors:
Code: https://github.com/pratimugale/PRUSS-Bindings/tree/master/examples/firmware_examples/example7-stepper-control https://github.com/pratimugale/pratimugale.github.io/blob/master/_posts/stepper_driver-uml.jpg

Installing and Using the API

Work that can further be done

Conclusion and Acknowledgement

Additional Details

Clone this wiki locally