Proposal for PRU User Space API project
This project aims to provide an API for different programming languages to load/unload firmware and communicate with the PRUs from User Space. A GUI application that runs on the terminal will also be provided for debugging the PRUs step by step.
Student: Pratim Ugale
Possible Mentors: Kumar Abhishek, Zubeen Tolani
In the previous years, a PyPRUSS project was made which is a Python binding for controlling the PRUs on BeagleBone. It uses the Userspace IO (UIO) driver, and has firmware examples in PASM. Nowadays, users tend to use the CLPRU compiler toolchain instead of the PASM assembler as PASM is no longer supported. Last year, there has been a project to update PyPRUSS to the Remoteproc/RPMsg interface whose code can be found here. The GSoC project was not completed for some reason. It consists of a PyPRUSS module and three firmware examples. I plan on reusing this code to make bindings for more languages and add more examples. Also, debugging functions have not yet been added in this module which I plan on adding in my GSoC project.
Github: Pratim Ugale
School: Veermata Jijabai Technological Institute (VJTI), Mumbai
Contact Number: +91 7045580782
Email ID: email@example.com
Primary language: English
Typical work hours: 08:00 to 17:00 IST (GMT+ 05:30)
Previous GSoC participation: I haven't participated in GSoC before. Having used open source technologies and programming forums before to solve my problems, I want to start contributing back to the community through GSoC and then continue on my own.
About your project
Project name: PRU User Space API
- This project will enable the control of the Beaglebone's PRUs from a User Space Client Program on the ARM. The PRU is a dual core micro-controller system present on the AM335x SoC which powers the BeagleBone. It is meant to be used for high speed jitter free IO control. Being independent from the linux scheduler and having direct access to the IO pins of the BeagleBone Black, the PRU is ideal for offloading IO intensive tasks. Now, regarding the project:
- The new Remoteproc and RPMsg drivers will be used for the ARM<->PRU communication.
- The remoteproc framework allows different platforms/architectures to control (power on, load firmware, power off) remote processors while abstracting any hardware differences.
- Rpmsg is a Linux framework designed to allow for message passing between the kernel and a remote processor. It uses a virtual ring buffer (VRING) that allows one to post messages to this buffer. Then, interrupts are used to notify the PRU/ARM that messages are in the buffer. RPMsg provides scalability for integrating individual PRU peripherals with the respective driver sub-systems.
The firmware (written by the user), consists of:
- A scalable TLV (table, length, value) Table (Resource Table): Used to inform the remoteproc driver about the remote processor’s available resources. To configure the Resource Table, one typically needs to modify up to three things.
- Event-to-channel mapping
- Channel-to-host mapping
- Number and location of vrings
- The Linker Command File - AM335x_PRU.cmd: Tells the linker where in memory to place the code and variables.
AM335x_PRU.cmd is the standard linker command file that tells the linker where to put what.
- A Makefile
- The C program that actually drives the PRU.
- The Project Deliverables
- The User Space Client Program must be able to
- Load firmware into the PRU cores
- Control PRU execution (start, stop, etc.)
- Manage resources (memory, interrupt mappings, etc.)
- Have a method to send/receive messages
The workflow of the project is:
UserSpace Client Program <-> API (UNIX Sockets / Language Bindings) <-> Daemon <-> pru_rproc, rpmsg_pru <-> Remoteproc, RPMsg drivers <-> PRU
The PRU attributes and its functions will be encapsulated into a single unit.
The functions provided by the Daemon will be:
- check_module() : Check if remoteproc is enabled using "lsmod | grep pru".
If not, enable remoteproc by editing the device tree.
#include "am33xx-pruss-rproc.dtsi" from the "am335x-boneblack-emmc-overlay.dts" file in "/opt/source/dtb-4.4-ti"
This will involve using a bit of regular expressions.
- make(parameters) : To compile using compiler (clpru) and linker (lnkpru) tools.
This will perform all the operations specified in the Makefile so that the Makefile can be omitted.
- reboot() : Reboots the PRU cores. After the firmwares are /lib/firmware/am335x-pru1(0)-fw is present, rebooting the PRU cores automatically loads the PRU with these firmwares. The sysfs bindings at the ‘/sys/bus/platform/drivers/pru-rproc/’ are to be used to reboot the PRUs
- configPinMux(): : Config-pin utility - Simply use the ‘config-pin’ utility to change the pinmux settings for a pin. (We do not need device tree overlays now (4.4+ kernel))
- shutdown(int core) : Shuts the PRU core provided in the parameter ("echo "4a334000.pru0" > /sys/bus/platform/drivers/pru-rproc/unbind" for PRU 0)
- boot(int core) : Boots the PRU core provided in the parameter ("echo "4a334000.pru0" > /sys/bus/platform/drivers/pru-rproc/bind" for PRU 0)
- reboot(int core) : To shutdown and boot the PRU core
- writemsg(), readmsg() using "/dev/rpmsg_pru30" and "/dev/rpmsg_pru31" : Read/Write message to PRU
PRU Debugging Functions: Using Remoteproc, we can actually see the content of the PRU registers; we can execute one instruction at a time on the PRU, and then wait for the user for a flag to execute the next instruction. We will implement the following functions using the pru_rproc driver:
- reg_values(int core): The values of the 32 General Purpose Registers of the PRU passed will be shown.
After disabling the PRUs, the 'regs' entry can be read to read the register content values.
Will also display the values of the control/status registers, and the contents of the constant table.
For PRU1 :- "cat /sys/kernel/debug/remoteproc/remoteproc1/regs"
REG31 is the PRU Event/Status Register (r31). When reading from REG31, it provides the state of the enhanced GPIO inputs.
REG30 is used by the PRU to set enhanced GPIO outputs.
- debug_pause(int core): This will change the mode of the PRUs to single_step mode. PRU executes one instruction and then gets paused.
For PRU0 :- "echo 1 > /sys/kernel/debug/remoteproc/remoteproc0/single_step"
- debug_nextStep(int core): Execute one next step each time invoked.
For PRU0 :- "echo 1 > /sys/kernel/debug/remoteproc/remoteproc0/single_step"
- debug_resume(int core): Internally this will bring back the PRU to continuous mode of operation.
For PRU0 :-"echo 0 > /sys/kernel/debug/remoteproc/remoteproc0/single_step"
dmesg -Hw can also be used for debugging
PyPRUSS: The Python code can be reused from last year’s project. The debugging functions are yet to be added in that code. This Python code will also be used with the ‘ncurses’ module to make the GUI for Debugging. Then I’ll write the functions in C and use SWIG to write interface files for other scripting languages such as Lua, Perl5, Tcl, Ruby, C#, C++, Java, Rust, Go, Node.js. I plan on providing API for as many languages as possible. Any other language suggested by the mentor will also be supported. If bindings are not possible, I’ll port the code to other languages.
Documentation: This is one of the most important aspects of the project. Currently, the documentation regarding the PRU remoteproc and RPMsg drivers is scattered and incomplete. Also, there is a steep learning curve to program the PRUs. I plan to provide an exhaustive Documentation along with hands-on examples so that one can utilize the PRU to its full capacity.
Examples: The PRU Cookbook’s and the examples present in Zeekhuge’s website will be used as test examples as illustrated in the timeline below.
GUI for Debugging
- I plan to provide a text based GUI-like application using the
‘ncurses’ library, that will run on the terminal and will provide efficient PRU debugging. The GUI will also implement the basic functions that the project provides. (like booting/shutdown, read/write). This will make the GUI a complete PRU controller. The Debugger will provide a menu-system and will chiefly implement the functions:- debug_pause(), debug_nextStep(), debug_resume() and reg_values(). I plan on using Steven Anderson’s prudebug (was done with UIO) as a reference. The PRUDebugger will be able to print the reg_values of the current step and the previous step and highlight the ones whose values have changed for better readability. The special registers R30 and R31 will be displayed and their implications will also be explained. When programming PRUs in Assembly, having something to peek into the contents of these registers can be a very useful tool.
Provide a development timeline with a milestone each of the 11 weeks. (A realistic timeline is critical to our selection process.)
- Community Bonding Period(6th May - 26th May)
- I have my University Exams till 15th May. (Will try my best to participate in
- Go through last year’s GSoC project thoroughly and learn how the code is
structured and how I'll modify the code.
- Week 1 (27th May - 2nd June)
- Test the python(PyPRUSS) code written in last year’s project and check if all the functions are working.
- Correct the code if any errors are encountered.
- I should finish up with the check_module(), load_firmware(), make(), reboot(), configPinMux(), shutDown(), boot(), reboot() functions.
- Parallely also write the code for these functions in C (which will be used later with SWIG for other languages)
- Add and test the Blinky example given here which requires loading firmware, configuring pinmux and rebooting the PRU cores.
- Week 2 (3rd June - 9th June)
- Test the RPMsg functions send_msg(), get_msg() for passing messages on a particular channel. Also test the wait_for_event() function which waits for an event from the PRU on a channel.
- Add an RPMsg RGB example similar to the neo4.c example in PRUCookbook
- Test the memory functions mem_writeint(), mem_readint(), mem_writebyte(), mem_readbyte()
- Add these functions in C.
- Make the Introductory Youtube Video.
- Week 3 (10th June to 16th June)
- Add the Debugging functions to PyPRUSS - reg_values(), debug_pause(), debug_nextStep(), debug_resume().
- Also add these functions in C.
- Add and test the debugging examples. (Using this as a reference)
- Week 4 (17th June - 23rd June)
- Now that all the functions are also written in C, use SWIG to connect the program with high-level programming languages described above.
- Revise ‘ncurses’ and get up to speed with it.
At the end of Phase 1, I must complete the Daemon and API for atleast three languages.
- Week 5 (24th June - 30th June)
- Start creating the framework of the GUI (how it will look) using ‘ncurses’ module in python.
- Integrate the loading/unloading, send_msg/get_msg Remoteproc, RPMsg functions and test their examples with the GUI.
- Week 6,7 (1st July - 14th July)
- Start adding the following features using a menu system:
- Load program file into instruction memory
- Set the active PRU number
- Start processor execution of instructions
- Start processor execution using automatic single stepping
- Pause the processor
- Single step the current instruction.
- Display the current PRU registers.
- Display the current PRU registers along with the values in the previous step and highlight the ones that have changed.
- Reset the current PRU.
- Write a 32-bit value to PRU data memory for current PRU.
- Write a 32-bit value to PRU instruction memory for current PRU.
- Quit the debugger and return to shell prompt
- Week 8 (15nd July - 21st July)
- Test the Debugger for both the PRUs.
- Incorporate any other functionality that the mentor suggests.
- Polish the GUI.
- If time permits, write API for other languages.
- Week 9 (22nd July - 28th July)
- Provide API for Perl, Java and other remaining languages using the C code written in the earlier weeks.
- Create a way for generating resource table for basic examples so that beginners can use the PRUs without worrying about writing the somewhat complicated resource table.
- Week 10 (29th July - 4th August)
- Integrate Maciej Sobkowski’s PRU DMA project with mine for copying of data to and from main memory (DDR), which would allow applications to use both cores for computation.
- Port some legacy PASM projects into the Remoteproc framework using clpru. I'll be using Mark Yoder's website, this site as references.
- The PASM examples will be from am335x_pru_package will be moved.
- Use the API to test these projects
- Week 11 (5th August - 11th August)
- Documentation for all the languages along with examples.
- The Documentation will also contain the errors one might expect while working with the PRU and how to resolve them.
- Week 12 (12th August - 18th August)
- Buffer Period in case of any disturbance in the timeline.
- Make the Completion Youtube Video.
- Add support for more programming languages.
Experience and approach
I am in my sophomore year of engineering, pursuing Information Technology.
I am currently enrolled in a "Computer Organisation and Architecture" course which motivated me to learn more about the PRUs.
I have worked with C, Python, Java, C++, Makefiles, Vimscript before.
I have learnt Linux driver development over the Internet in the past few months (I have implemented basic programs, and listed the errors(and solutions) I encountered on my github profile here).
I have worked with the Arduino UNO and ATMega boards before (made a self balancing and line following bot using PID algorithm in college).
I have always been using Linux(Ubuntu) as my primary OS, so getting along with Embedded Linux won't be a problem.
I have thoroughly been through the PRU Cookbook and zeekhuge's website and the resources I found there have been invaluable.
Hence, I am confident that I'll be able to complete the given project in due time.
What will you do if you get stuck on your project and your mentor isn’t around?
While working with open source software, one thing I realised for sure is that one has to be self-sufficient. Knowing how to use a search engine effectively is also an important skill. I like to give my best before asking anyone else for help when I’m stuck with any problem and I consider it to be a way I actually learn and become independent.
However, if I get terribly stuck on a problem, and the mentor isn't around, I shall:
- Work on other parts of the project so that the timeline is not disturbed. If the rest of the project is dependent on the problem, then -
- Work on the Documentation.
- Test more firmware examples with the project and do debugging.
- Some of the references I'll be using:
If successfully completed, what will its impact be on the BeagleBoard.org community?
This project will allow larger programs to be developed in the programming language of the user's choice. Right now one has to manually load the firmware and execute long commands to get things done. The API will provide simple and intuitive functions so that the user can easily read values from the PRU and use them for his/her other needs directly from the program itself.
EDIT The Debugger will provide a nice Graphical Interface for better readability.
Mar 08 05:03:15 <zeekhuge[m]>: To make it easy to use interface and standards for the PRU. Right now, we have to execute commands to get some code loaded onto the PRUs, by echoing into the sysfs entries. Also, the remoteproc mechanism allows to communicate with the PRUs using char device entries (mostly, and can be configured). The APIs need to provide a way, in different languages, to be able to read and write message to and from the PRUs within the program itself. Zubeen Tolani(zeekhuge)
Apr 04 21:22:52 <zeekhuge[m]>: pratimugale: I liked the idea of a GUI debugger. It must run on the termimal, something based on ncurse maybe. Zubeen Tolani(zeekhuge)
Benefit of using Remoteproc :- The UIO is just like random memory access while Remoteproc is more systematic and very well supported by the kernel and can be used to allow PRUs to use other resources as well like DMA access. Also, using Remoteproc, PRUs can act as different hardware devices (implemented by code on the PRU). For example, if the firmware on PRU can read/write data using SPI interface, then using Remoteproc, PRUs can act as if it was a SPI device itself, and the SPI system will just work with it. Migration of PRU development to Remoteproc gives the Linux kernel a greater knowledge of the cores.
- In the future, the project will be expanded to support many more programming languages.
- The Documentation will always be updated to use the newest methods that are developed.
Is there anything else we should have asked you?