BeagleBoard/GSoC/2023 Proposal/PRU-based USB stack

Proposal - PRU-based_USB_stack

 * Student: Rohan Joshi
 * Mentor: Giulio Moro
 * Proposal: PRU-based_USB_stack
 * Wiki: N/A
 * GSoC: GSoC

Status
This project is currently just a proposal.

About You

 * IRC:
 * GitHub: Rohan Joshi
 * School: Vishwakarma Institute of Technology, Pune.
 * Country: India
 * Primary Language: Marathi, Hindi, English
 * Typical Work Hours: 9am - 5pm (IST)
 * Previous GSoC participation: First time participation

About Project
Name: PRU-based_USB_stack

Description
The project aims to implement entire USB stack (host/device) for PRU subsystems. The USB system on board will have to be implemented as DRD (Dual Role Device) so that PRU-controlled USB interface can act as host and device for transmitting high-bandwidth audio data. According to description, it will be optimized for audio devices (HID and MIDI) which can later be integrated into other software like bela.io. In order to optimize it for audio applications, apart from one control endpoint, multiple Isochronous endpoints can be implemented in order to utilize available memory bandwidth in most efficient way.

Image depicts a generic architectural view of USB implemented under linux. Following the same, and as mentioned is official USB specification

Implementation Details
In order to implement a USB stack, one must know about organization and architecture of USB host and USB device. One must understand underlying protocol which will help tremendously. USB has various versions which mainly differ in speed and some other things. A USB 1.x spec can communicate at 1.5Mbps on low speed bus and 12Mbps on full speed bus and a USB 3.2 which can communicate at 20Gbps which is backward compatible. A negotiation method can be used on the bus which will enable the communication at maximum possible rate where host and device use different spec. The USB subsystem should work with PRUs available on BeagleBones (BeagleBone, BeagleBone Black, BeagleBone Green, etc.) with minimum possible latency. For that


 * I will try to remove a USB port from linux device tree and use it exclusively with PRU (Not sure at the moment how to do that but will figure it out) which will eliminate over-head of linux kernel.


 * Create a data pipeline connecting PRU and host through USB device endpoints with no linux kernel intervention.

This way a PRU can be exclusively used for this purpose with other one being free for other use.

Generally, all USB work is done using ISR. USB routines and subprograms are bundled into a library. What we can do is include USB library in main program and then call subprograms in initialization phase. Mostly a 64-byte buffer is used for transferring data to USB bus or fetching data from the bus. The two buffers implies two endpoints (one IN and other OUT). Up-to 4 more endpoints i.e total of 6 (max) can be added.

For sending data on the bus, generally load-store kind of instructions are used. Here what are we doing is get x bytes of data to be written. Write it into EP buffer and then write it to bus by setting a flag to let the bus know data is available and cane be read. The short pseudo-code is

The similar process but reverse is used to receive (read) the data from the bus. The pseudo-code is

Also, python provides a package to simply test the controller under Linux and Windows.

Here we'll use USB 2.0 Isochronous Endpoints on high speed bus, as we need to transfer real-time data stream. It has theoretical maximum data rate of 60MB/s. It has no error detection or correction mechanism (it will take a lot of time) and even if a packet is dropped or not read, user will hardly notice any difference. This method needs user to have root access. Might be possible to do this even without root access by creating a /etc/udev rule.

Experience and Approach

 * I've previously work on AVR microcontrollers. (ATmega 328p, ATmega 32U4)
 * I've experience working on ARM based microprocessors. (ARM Cortex A-53)
 * I've worked on Linux Device Driver for 16x2 LCD Display. (Available on my GitHub)
 * I've worked with different type of compilers for different target platform. (E.g Avrgcc)
 * I can adopt and work with new hardware.
 * I can collaborate and work with others.
 * I know version control systems. (git)
 * Currently I'm an intern at Cadence Design Systems where I work on USB and PCI/PCIe IPs.
 * I like and use open source software and would really like to officially be a part of one.
 * The project approach will be clean and simple and is to just follow timeline and try to be ahed of timeline.

Contingency
In case of any unseen roadblock and if my mentor isn't around, what I can do is
 * 1) Considering the tremendous available information on internet, I'll lookup for solution on internet.
 * 2) Refer to official documentation/specification.
 * 3) Refer to a book called USB in a nutshell which is really a great resource.
 * 4) Ask for help on open source forums, stack-overflow, reddit, etc.
 * 5) Ask on BB community.

Benefit

 * We'll have a full functioning USB stack which works with PRUs.
 * Can be made to work with different architectures.
 * Enables to connect HID, MIDI and other devices over USB.