Understanding vrings for PRU
The PRU subsystem comprises of 2 32bit RISC processors running at 200MHz. This allows us to run programs independent of the main ARM core. However all AMP configurations require some mechanism for inter processor communication. Most interactions can be broadly classified into categories :-
1. Instructions or commands which range from single to couple of bytes. Such instructions are designed by the programmer to instruct the other processor ( We are not referring to processor instruction set here ). Example : Sending flags to start capture, wait for some task completion, mark process as running, end capture or simply small data packets lets say direction and step values for a stepper motor in a 3D printer making use of PRU. Such data transfer is possible through
a. Directly writing to shared memory address spaces ( DDR, PRU DRAMs, PRU SRAM )
b. Make use of prussdrv library which is linux UIO driver ( userspace driver framework for generic memory mapped devices ).
d. libpru library for 3.14+ kernel. This was written as part of this project.
At most times prussdrv and libpru will serve the purpose.
2. The second type of interaction is streaming data between ARM and PRU. This is necessary for a different class of PRU implementations such as streaming input data from high speed sensor, output custom/existing protocols from PRU pins ( DMX example ), logic analyser ( BeagleLogic ) and several others you might think of. The PRU can even access the Ethernet controller to process rx/tx packets on the fly and and them over to ARM. Possibilities are huge.
This is possible using vrings ( virtio_ring ) which is a part of linux virtio ( Virtual IO ) drivers.
Virtio was originally designed to provide a common implementation for virtual IO device drivers in different hypervisor environment. The virtio ecosystem provide a Linux API to handle vdevs (virtio devices) such as registering device, probe,remove, configurations, interrupt handling, etc and secondly it provides a transport layer ( since virtio before everything else, is all about IO ). The transport mechanism consists of an abstraction layer provided by 'virtqueue' and implementation of this abstraction provided by 'vring'. Hence vrings are an implementation of virtqueue. But since vring was the only available implementation of virtqueue, both were collapsed into one [ virtio_ring ]. [ lkml merger discussion ].
So vdevs could eventually be a virtual PCI, virtual network device, virtual block device etc for the guest VM. This briefly explains virtio which is essential to understand what follows. More details on virtio for further reading [ 1 ] [ 2 ] [ 3 ].
Now, virtio when combined with linux remoteproc and rpmsg frameworks can be used for communication between processors. For the PRU, instead of going for rpmsg, the underlying vring has been used for this project. The reason being that rpmsg being a framework requires significant code on both participating processor. It provides for a bus with each processor assigned an address, thus providing a src-dest address based communication model for AMP configurations. It is best suited for hardwares such as OMAP4 which has a dual Cortex-A9, a dual Cortex-M3 and a C64x+ mini-DSP. Whereas the PRU not meant for heavy computation, has a limited code space ( 8KB for each core ). Thus, making using of vring and avoiding rpmsg code space and latency overhead seems logical.
This brings us to the pruss_remoteproc driver which is available for kernel 3.14 ( beagleboard's fork ).
Continued in next post ....