The PRU is a real-time microcontroller co-processor that is present on some OMAP/Sitara-series processors.
The meaning of real-time is different depending on your application. How much time you have, how much there is to do in that time, … It’s not necessarily about high performance, though increasing performance may be a way to get your real-time behaviour. What is always there is that it needs to be (to some extent) deterministic and that it has to be low-latency.
In e.g. a Cortex-A based system, there are a lot of components that are bad for real-time; caches, interconnect, GPIOs that are beyond the interconnect, …. It’s really designed for throughput, not for (deterministic) latency. So TI added a Programmable Real-Time Unit (PRU). It has fast deterministic access to on-chip RAM and to GPIOs. It’s a simple 32-bit RISC instruction set, it doesn’t have a pipeline, it runs at 200MHz. It’s connected to the Cortex-A over the non-deterministic interconnect, but that doesn’t matter because at that point it’s not RT anymore. It has direct access to the GPIOs, so the pins can toggle at 100MHz. It also has some dedicated peripherals, e.g. UART, eCAP/PWM, MDIO for ethernet, and timers.
Every Cortex-A SoC from TI in the future is going to have at least one PRU.
The PRU doesn’t have real interrupts, instead it uses polling. Not good for power consumption (it’ll take about 500mW all the time), but great for determinism.
The PRU recently got a compiler, which is based on TI’s earlier DSP compilers, there are some register header files. Compiler runs in Linux/x86, they’re thinking about porting it to ARM.
How to interface between the PRU and the Linux on the Cortex-A? Linux needs to load the firmware to the PRU, it needs to manage the shared resources (memory, which CPUs are used, who uses which peripheral), it needs to start and stop the PRUs, it needs to share data and synchronize (events, interrupts). This is done through the remoteproc/rpmsg and virtio transport frameworks.
Remoteproc is a framework meant to deal with other processors in the system. It’s configured through the DTB, which specifies each PRU in the subsystem, how much memory it has, …. remoteproc has an interface for powering up the remote device and controlling it. It’s completely upstream. The probe function looks for firmware to load in /lib/firmware. A resource table is used to pass information to the remote firmware about how Linux is using it.
remoteproc has a communications framework called rpmsg. Note that sometimes you don’t need to communicate anything, because you just need to get events from the PRU and no data (e.g. temperature monitor sends an event when temperature is too high) – in that case, you can just use the interrupt provided by remoteproc. The PRU has an rpmsg library to handle the communication. rpmsg is built on top of virtio (which is meant for VMs, but this is actually similar). rpmsg has a userspace component (/dev/rpmsg-pruN) on Linux so you can use it from your application. TODO: implement a demuxing part in the kernel so that e.g. you can send debug messages from the PRU directly to the console.
There are still some core architecture changes needed in rpmsg to improve performance (e.g. avoid the 40-cycle hardware mailboxes).