Difference between revisions of "BeagleBoard/GSoC/PyPRUSS"

From eLinux.org
Jump to: navigation, search
(Added DMA in description and detailed examples)
 
(8 intermediate revisions by the same user not shown)
Line 6: Line 6:
  
 
''Student'': [http://elinux.org/User:Muneeb17 Mohammed Muneeb]<br>
 
''Student'': [http://elinux.org/User:Muneeb17 Mohammed Muneeb]<br>
''Mentors'': Jason Kridner, Kumar Abhishek<br>
+
''Mentors'': Kumar Abhishek, ZeekHuge, Patryk Mezydlo, S. Lockwood-Childs <br>
 
''Code'': https://bitbucket.org/muneeb17/pypruss<br>
 
''Code'': https://bitbucket.org/muneeb17/pypruss<br>
 
''Wiki'': http://elinux.org/BeagleBoard/GSoC/PyPRUSS<br>
 
''Wiki'': http://elinux.org/BeagleBoard/GSoC/PyPRUSS<br>
<!-- ''GSoC'': [ GSoC entry]<br> -->
+
<!-- ''GSoC'': [https://summerofcode.withgoogle.com/projects/#6673723025784832]<br> -->
 
<div style="clear:both;"></div>
 
<div style="clear:both;"></div>
 +
{{#ev:youtube|vHxpa6JwqqI||right|PyPRUSS}} <!-- latest video will go here -->
  
 
=Status=
 
=Status=
Line 31: Line 32:
  
 
===Description===
 
===Description===
The PyPRUSS is a python binding/API for controlling the [http://beagleboard.org/pru PRUs]. It provides an easy to use python-based interface for loading firmware, controlling execution and interrupts/memory management for the PRUs, therefore shortening the learning curve for users new to PRU programming. Currently, the PyPRUSS uses PASM for its examples and communicates using the older Userspace IO (UIO) Driver. The goal of this project is to update the API to use the remoteproc/rpsmg sysfs interfaces for interacting with the PRUs and port the existing examples to [https://github.com/dinuxbg/gnupru gnupru](since PASM is [http://processors.wiki.ti.com/index.php/PRU_Assembly_Instructions#pasm_vs._clpru no longer supported] by TI) to work on the latest images. I also plan to add DMA Support to the API, since it will enable the users to program both the PRUs for their application, instead of reserving one for ARM-PRU communication(as needed in case of rpmsg).
+
The PyPRUSS is a python binding/API for controlling the [http://beagleboard.org/pru PRUs]. It provides an easy to use python-based interface for loading firmware, controlling execution and interrupts/memory management for the PRUs, therefore shortening the learning curve for users new to PRU programming and also allowing seamless integration of PRU functionality to a larger python projects. Currently, the PyPRUSS uses PASM for its examples and communicates using the older Userspace IO (UIO) Driver. The goal of this project is to update the API to use the remoteproc/rpsmg interfaces for interacting with the PRUs, port the existing examples to [https://github.com/dinuxbg/gnupru gnupru](since PASM is [http://processors.wiki.ti.com/index.php/PRU_Assembly_Instructions#pasm_vs._clpru no longer supported] by TI) and also add DMA Support to the API, since it will enable the users to program both the PRUs for their application, instead of reserving one for ARM-PRU communication(as needed in case of rpmsg).
 
====The API====
 
====The API====
Essentially, the API will provide the following functions:
+
Essentially, the API will provide the following functions: <br> <br>
*Remoteproc functions: Load Firmware into the PRU Cores, Control PRU Execution(start/stop) using the remoteproc sysfs interface accessible at /sys/class/remoteproc/remoteprocX
+
'''Remoteproc functions''':
*Memory Read/Write functions: Read/Write to the PRU Data RAM,PRU Shared RAM, and the external DDR memory using /dev/mem + mmap()
+
*''modprobe()/modunprobe()'': Load/unload the pru_rproc module (using modprobe/rmmod)
*RPMsg functions: Sending/receiving messages using the rpmsg character device file found at /dev/rpmsg_pru{CHAN_PORT} which will be configured by the RPMsg framework once the channel is created. PRU->ARM interrupts can be implemented using the poll interface of the character device file.
+
*''exec_program()'': Load Firmware into the PRU Cores (the firmware should be copied to ''/lib/firmware/am335x-pruX-fw'') and enable the PRUs.
*PRU DMA functions: Alternatively, the PRU memory read/write functions and the ARM-PRU communication functions can be implemented using the EDMA controller on the SoC. The PRU DMA project from last year provides a Kernel level API to transfer data between ARM-PRU using the EDMA along with a few examples. Now, I plan on implementing a general purpose driver which will expose a sysfs interface, which can then be used by the Python API for communication/data transfer.
+
*''pru_enable(), pru_disable(), pru_reset()'': Control PRU Execution State(start/stop) using the remoteproc sysfs interface (using ''echo 'start/stop'>/sys/class/remoteproc/remoteprocX/state'')
*Miscellaneous functions: Pin configuration/DTO generation and Resource Table generation functions
+
 
 +
'''Memory Read/Write functions''': <br>
 +
Read/Write to the PRU Data RAM,PRU Shared RAM(''map_prumem()''/''write_prumem()''), and the external DDR memory read(''map_extmem()''), access(''get_ddr_addr()''/''get_ddr_size()'') using ''/dev/mem + mmap()''
 +
 
 +
'''RPMsg functions''':
 +
*''send_msg()/get_msg()'': Sending/receiving messages using the rpmsg character device file found at /dev/rpmsg_pru{CHAN_PORT} which will be configured by the RPMsg framework once the channel is created.
 +
*''wait_for_event()/clear_event()'': PRU->ARM interrupts/event control can be implemented using the poll interface of the rpmsg character device file.
 +
 
 +
'''PRU DMA functions''': <br>
 +
Alternatively, the PRU memory read/write functions and the ARM-PRU communication functions can be implemented using the EDMA controller on the SoC. The PRU DMA project from last year provides a Kernel level API to transfer data between ARM-PRU using the EDMA along with a few examples. Now, I plan on implementing a general purpose driver which will expose a sysfs interface, which can then be used by the Python API for communication/data transfer.
 +
 
 +
'''PRU Debug functions''': <br>
 +
The remoteproc driver provides a debugfs interface for PRU Code Debugging. Using it, we can activate the SINGLE_STEP mode, using which will allow users to step through PRU Code one line at a time and also examine the register contents at the steps(kind of like trace in gdb). The functions will include:
 +
*''pru_pause(), pru_resume(), pru_next_step()'': Using the debugfs interface at ''/sys/kernel/debug/remoteproc/remoteprocX/single_step''
 +
*''view_regs()'': Pause the PRU(''pru_pause()'') and the cat the contents of ''/sys/kernel/debug/remoteproc/remoteprocX/regs''.
 +
 
 +
'''Miscellaneous functions''':  
 +
*''pru_pinset()'': Configures the pinmux settings for the pins specified. If universal cape not enabled, it will build and load a Device Tree Overlay(DTO) to change the pinmux settings.
 +
*''pru_dma_overlay()'': Builds and loads the DTO to configure DMA and load the general purpose dma driver.
 +
*''generate_resctable()'': A function to generate resource table for basic examples(The basic examples have most of the part of the resource table similar. For interrupts/event control examples, the script will provide an easy way to generate the resource_table.h file taking in a few parameters as required)
 +
*''generate_dma_resctable()'': Generates resource table for DMA examples(taking in buffer address/size, EDMA channel, etc. as parameters)
  
 
====Examples====
 
====Examples====
1.BeagleScope and pru-software-support package examples: Writing scripts for these examples using the PyPRUSS API(Mainly for testing the remoteproc/rpsmg functions).
+
1. [https://github.com/ZeekHuge/BeagleScope/tree/port_to_4.4.12-ti-r31%2B/examples/firmware_exmples BeagleScope] and pru-software-support package examples: Writing scripts for these examples using the PyPRUSS API(Mainly for testing the remoteproc/rpsmg functions).
  
2.Moving the existing PASM examples to pru-as(the assembler in the [https://github.com/dinuxbg/gnupru gcc-pru] toolchain) to use remoteproc:  The gnupru is the unofficial gcc port for the PRUs. The community would like to eventually shift to gcc and this is a step in that direction. The examples include
+
2. Moving the existing PASM examples to pru-as(the assembler in the [https://github.com/dinuxbg/gnupru gcc-pru] toolchain) and to use remoteproc:  The gnupru is the unofficial gcc port for the PRUs. The community would like to eventually shift to gcc and this is a step in that direction. The examples include:
 
*blinkleds  - loads a program which blinks the user leds 10 times and sends a notification to the host.
 
*blinkleds  - loads a program which blinks the user leds 10 times and sends a notification to the host.
 
*mem_write  - writes to the PRU DRAM and Shared RAM  
 
*mem_write  - writes to the PRU DRAM and Shared RAM  
 
*ddr_write  - passes the target DDR address to PRU DRAM and then the PRU writes some data to the DDR.
 
*ddr_write  - passes the target DDR address to PRU DRAM and then the PRU writes some data to the DDR.
*speed_test - performs a speed test by toggling an led for some cycles and passing an interrupt.
+
*speed_test - performs a speed test by toggling an led for some cycles and passing an interrupt upon completion.
 
   
 
   
3.PRU DMA Examples: Modifying the existing PRU DMA examples to use the API(For testing the dma functions). The examples include
+
3. PRU DMA Examples: Modifying the existing [https://github.com/maciejjo/beaglebone-pru-dma/tree/master/examples PRU DMA examples] to use the API(For testing the dma functions). The firmware will still use the PRU-side library, the kernel module functions will be replaced by a sysfs interface. The examples include:
 
*led_pattern  - the leds blink with a pattern sequence given by the user, transferred to the PRU through DMA.  
 
*led_pattern  - the leds blink with a pattern sequence given by the user, transferred to the PRU through DMA.  
 
*sensor_data  - transfers the sensor data from PRU memory to the DDR and outputs the data.
 
*sensor_data  - transfers the sensor data from PRU memory to the DDR and outputs the data.
 
*loopback_test - transfers the data from RAM to PRU memory and back, to test if DMA is working correctly.
 
*loopback_test - transfers the data from RAM to PRU memory and back, to test if DMA is working correctly.
 +
 +
4. Other Examples
 +
---TODO----
  
 
====Documentation====
 
====Documentation====
Line 60: Line 84:
 
*A quick start guide to programming the PRUs in assembly with gcc-pru (as it is not well documented as of now)
 
*A quick start guide to programming the PRUs in assembly with gcc-pru (as it is not well documented as of now)
 
*Setup/build instructions for the project.
 
*Setup/build instructions for the project.
 +
 +
====Support for other Languages====
 +
I also plan on extending the project to support other languages, namely C/C++ and nodejs.
  
 
===Timeline===
 
===Timeline===
 +
 +
====Community Bonding Period: April 23 - May 13====
 +
*Re-Read remoteproc/rpmsg and PRU DMA documentation thoroughly.
 +
*Go through the [https://github.com/beagleboard/linux/blob/4.9-rt/drivers/remoteproc/remoteproc_sysfs.c rproc sysfs], [https://github.com/beagleboard/linux/blob/4.9-rt/drivers/rpmsg/rpmsg_rpc_sysfs.c rpmsg sysfs] and [https://github.com/maciejjo/beaglebone-pru-dma/blob/master/kernel-patch/0001-Add-pru-dma-driver-to-Linux-tree.patch dma drivers].
 +
*Go through the [https://bitbucket.org/intelligentagent/pypruss PyPRUSS] thoroughly.
 +
*Get the PRU DMA project up and running on the board.
 +
*Read about implementing a driver to expose sysfs interface, read about Device attributes, kobjects.
 +
 
====Week 1: May 14 - May 20====
 
====Week 1: May 14 - May 20====
*Go through the kernel [https://www.kernel.org/doc/Documentation/remoteproc.txt documentation] and the [https://github.com/beagleboard/linux/blob/4.4/drivers/remoteproc/pru_rproc.c driver].
+
*Implement the Remoteproc functions: ''modprobe()'', ''modunprobe()'', ''pru_enable()'', ''pru_disable()'', ''pru_reset()'', ''exec_program()''
*Go through the PyPRUSS codebase thoroughly, github forks, look up existing bugs/issues.
+
*Implement the RPMsg functions: ''send_msg()'', ''get_msg()''
 +
*Write bindings to implement the above functions using C, C++ and nodejs as well.
  
 
====Week 2: May 21 - May 27====
 
====Week 2: May 21 - May 27====
*Implement basic PRU Control functions (power on/off, load firmware, reset, enable/disable).
+
*Implement the RPMsg functions: ''wait_for_event()'', ''clear_event()''
 +
*Implement the Memory Functions: ''map_prumem()/write_prumem()'', ''map_extmem()'', ''get_ddr_addr()/get_ddr_size()''
 +
*Write bindings to implement the above functions using C, C++ and nodejs.
 +
*Test the implemented Remoteproc/RPMsg using a few firmware examples in the BeagleScope repo. Fix Bugs(if any).
 +
 
 +
====Week 3: May 28 - June 3====
 +
*Write a simple general purpose driver which will communicate with the [https://github.com/maciejjo/beaglebone-pru-dma/blob/master/kernel-patch/0001-Add-pru-dma-driver-to-Linux-tree.patch pru dma kernel driver] to expose a sysfs interface to userspace. It will mostly involve modifying drivers from the PRU DMA examples to provide a generalised sysfs interface.
 +
*Test the driver using the DMA examples.
  
====Weeks 3-4: May 28 - June 10, End of Phase I====
+
====Week 4: June 4 - June 10, End of Phase I====
*Implement Data Memory Read/Write functions.
+
*Use the sysfs interface provided by the general purpose driver to implement the DMA functions for the PyPRUSS API.
*Implement External Memory/DDR access functions.
+
*Also add C/C++ and nodejs bindings to use the DMA sysfs interface.
*Implement the Interrupts/Event Control functions.
+
*Test the DMA API functions using the DMA examples.  
*Preliminary test the API with available examples.
 
  
'''By the Phase I evaluation, I would deliver a basic API tested with available remoteproc examples.'''
+
'''By the Phase I evaluation, I would deliver the basic PyPRUSS API with Remoteproc/RPMsg functions tested with a few [https://github.com/ZeekHuge/BeagleScope/tree/port_to_4.4.12-ti-r31%2B/examples/firmware_exmples BeagleScope Examples] and DMA functions tested with an existing [https://github.com/maciejjo/beaglebone-pru-dma/tree/master/examples/01_leds PRU DMA example]. Support for C/C++ and nodejs will also be provided.'''
  
 
====Week 5: June 11 - June 17, Start of Phase II====
 
====Week 5: June 11 - June 17, Start of Phase II====
*Port the existing PASM examples to clpru (TI C Compiler).
+
Implement the Miscellaneous functions: ''pru_pinset()'', ''pru_dma_overlay()'', ''generate_resctable()'', ''generate_dma_resctable()''. Also, write C/C++ and nodejs code for these functions as well. These functions will reduce a few hurdles a beginner can get stuck at. User doesn't need to worry about dealing with DTOs and Resource tables, and can concentrate more on the code/functionality.  
*Test the examples on the API.
 
  
 
====Week 6: June 18 - June 24====
 
====Week 6: June 18 - June 24====
*Port the examples to pru-as (pru-gcc).
+
*Implement the PRU Debug functions: ''pru_pause()'', ''pru_resume()'', ''pru_next_step()'', ''view_regs()''
*Fix Bugs (Not exactly sure how complete pru-as is. I tried some working examples. Had a conversation with dinuxbg, according to him, pru-as and pru-ld are stable and also there is a major release coming up to align gnupru with the TI ABI). Nevertheless, I can use the buffer week to fix major bugs in pru-gcc (if any).
+
*Add C/C++ and nodejs support for these functions.
 +
*Port the existing PASM examples(outlined in the description) to asmpru (TI Assembler)(just to be on a safe side, as it has been tested extensively) and the scripts to use the new API.
 +
*Test the examples on the API.
 +
*Move the examples to pru-as(pru-gcc).
  
 
====Week 7: June 25 - July 1====  
 
====Week 7: June 25 - July 1====  
 
*Complete the work on pru-as examples.
 
*Complete the work on pru-as examples.
*Work on a little more advanced additional (C) examples (demonstrating interrupt/events, shared memory).
+
*Fix Bugs (Shouldn't be having major issues with pru-gcc. Had a conversation with dinuxbg, according to him, pru-as and pru-ld are stable and also there is a major release coming up to align gnupru with the TI ABI). Nevertheless, I can use the buffer week to fix major bugs in pru-gcc (if any).
 +
*Write scripts for the PRU DMA examples (outlined in the description) and also the remaining BeagleScope/pru-software-support-package examples using the API.
  
 
====Week 8: July 2 - July 8, End of Phase II====
 
====Week 8: July 2 - July 8, End of Phase II====
*Work on a script to generate resource table for basic examples (The basic examples have most of the part of the resource table similar. For interrupts/event control examples, the script will provide a beginner friendly way to generate the resource_table.h file taking in a few parameters required.)(Details will be included in the documentation).
+
*Convert the snprintf() implementations in the [https://github.com/beagleboard/linux/blob/4.9-rt/drivers/rpmsg/rpmsg_rpc_sysfs.c rpmsg sysfs driver] to use [http://processors.wiki.ti.com/index.php/DSP_BIOS_FAQ#Q:_How_can_I_convert_printf.28.29_statements_to_LOG_printf.28.29.3F LOG_printf()]. LOG_printf() is a very minimal and less disruptive way to print strings to the rpmsg character device file since the formatting is done on the host-side, whereas the snprintf() performs it on the target-side(PRU) which induces a significant performance overhead on the PRUs.  
  
'''By the Phase II evaluation, I would deliver a set of working assembly/C remoteproc examples to use with the API'''
+
'''By the Phase II evaluation, I would deliver a set of working assembly/C examples(as outlined in the description) along with the python scripts demonstrating the use of the API'''
  
 
====Week 9-10: July 9 - July 22, Start of Phase III====
 
====Week 9-10: July 9 - July 22, Start of Phase III====
Write Documentation, which will include
+
*Write Documentation(outlined in the description)
*Detailed explanation of the API functions
+
*Run Final Tests, Receive Mentor Feedback.  
*Step-by-Step Walkthrough of the examples.
+
*Final Bug Fixes.  
*Quick Start guide to start assembly programming with pru-as.
+
*Cleaning/refactoring the code.
*Setup and build instructions for the project.
 
  
 +
'''After the above is completed, I would like to work on a stretch goal which is adding ELF support to PASM.'''
 
====Week 11: July 22 - July 28====
 
====Week 11: July 22 - July 28====
*Run Final Tests
+
*Work on a script to convert bin files to ELF files, so that PASM can be used with remoteproc. Although PASM is no longer supported, it was the mainline PRU assembler for a long time and there are people who still prefer using it. I found some steps [https://groups.google.com/d/msg/beagleboard/cYHCN3GWw_E/VraPc0YwCQAJ here] which will help.
*Receive Mentor Feedback, Final Bug Fixes.
 
*Cleaning/refactoring the code.
 
  
 
====Week 12: July 29 - Aug 5====
 
====Week 12: July 29 - Aug 5====
Buffer Week
+
*Buffer week for the project.
  
 
===Experience and approach===
 
===Experience and approach===
I am a junior-year electronics engineering undergraduate and had a fair amount of coursework related to embedded development. I have experience with programming microcontrollers(AVRs, Arm Cortex M0/3) in C and I've also worked on BeagleBone Black . I have been using linux as my primary OS for some time now, so I can work my way around embedded linux quite easily. Most of my software related coursework has been done in C and python, & therefore I am fairly proficient in both these languages.
+
I am a junior-year electronics engineering undergraduate and have had a fair amount of coursework related to embedded development. I have experience with programming microcontrollers(AVRs, Arm Cortex M0/3) in C and I've also worked on BeagleBone Black . I have been using linux as my primary OS for some time now, so I can work my way around embedded linux quite easily. Most of my software related coursework has been done in C and python, & therefore I am fairly proficient in both these languages.
 
====Projects====
 
====Projects====
 
* [https://github.com/MuneebMohammed/Snakeplusplus/blob/master/src/snake.c Retro Snake Game] using AVR Microcontroller : The classic snake game implemented using an Atmega, Dot Matrix Display & joystick and programmed in C. [https://hackaday.io/project/27912-snake Project Page], [https://github.com/MuneebMohammed/Snakeplusplus github]
 
* [https://github.com/MuneebMohammed/Snakeplusplus/blob/master/src/snake.c Retro Snake Game] using AVR Microcontroller : The classic snake game implemented using an Atmega, Dot Matrix Display & joystick and programmed in C. [https://hackaday.io/project/27912-snake Project Page], [https://github.com/MuneebMohammed/Snakeplusplus github]
Line 117: Line 160:
  
 
====Approach====
 
====Approach====
My summer break starts exactly from the GSoC start date and will go on until the first week of August, until when all the work will be essentially completed. I have no other engagements during the summer, so I can devote whole of my time to the project. I plan on dedicating 7-8 hrs per day for the project on weekdays and 4-5 hrs on weekend days which makes the time commitment around 45-50 hrs per week. Since I wont be starting from scratch, I think the timeline above is quite realistic and doable in the time available.  
+
My summer break starts exactly from the GSoC start date and will go on until the first week of August, until when all the work will be essentially completed. I have no other engagements during the summer, so I can devote whole of my time to the project. I plan on dedicating 7-8 hrs per day for the project on weekdays and 4-5 hrs on weekend days which makes the time commitment around 45-50 hrs per week. Since I wont be starting from scratch, I think the timeline above is quite realistic and doable in the available time.  
  
 
===Contingency===
 
===Contingency===
There is an abundance of quality documentation on PRUs and remoteproc/rpmsg like the [https://elinux.org/images/d/da/Am335xPruReferenceGuide.pdf PRU-ICSS] guide, remoteproc/rpmsg kernel [https://www.kernel.org/doc/Documentation/remoteproc.txt documentation], [http://processors.wiki.ti.com/index.php/PRU-ICSS_Remoteproc_and_RPMsg wiki], PRU Assembly [http://processors.wiki.ti.com/index.php/PRU_Assembly_Instructions Guide], etc. One can always resort to IRC/mailing list and also the community forums like TI E2E but the response time may be high. Though, sometimes a thoughtful google search may suffice.
+
There is an abundance of quality documentation on PRUs and remoteproc/rpmsg like the [https://elinux.org/images/d/da/Am335xPruReferenceGuide.pdf PRU-ICSS] guide, remoteproc/rpmsg kernel [https://www.kernel.org/doc/Documentation/remoteproc.txt documentation], [http://processors.wiki.ti.com/index.php/PRU-ICSS_Remoteproc_and_RPMsg wiki], [http://processors.wiki.ti.com/index.php/PRU_Assembly_Instructions PRU Assembly Guide], etc. One can always resort to IRC/mailing list and also the community forums like TI E2E but the response time may be high. Though, sometimes a thoughtful google search may suffice.
  
 
===Benefit===
 
===Benefit===
PRUs are a tough nut to crack for beginners. The ARM to PRU communication is a somewhat complex process and users are expected to know about the low level details upto some level before starting to write any code. Also, using the remoteproc interface tends to be difficult and timetaking for beginners.This project attempts to shorten the learning curve for users new to programming with PRUs by providing an abstraction over the loading, control and communication process with the PRUs so that they can start focusing on the functionality/app instead and get started with minimum time and effort.
+
PRUs are a tough nut to crack for beginners. The ARM to PRU communication is a somewhat complex process and users are expected to know about the low level details upto some level before starting to write any code. Also, using the remoteproc/rpmsg interface tends to be difficult and timetaking for beginners.This project attempts to shorten the learning curve for users new to programming with PRUs by providing an abstraction over the loading, control and communication process with the PRUs so that they can start focusing on the functionality/app instead and get started with minimum time and effort. The project will also enable users who are working on a larger python project to incorporate PRU functionality in their code seamlessly.

Latest revision as of 11:42, 9 May 2018


Update to PyPRUSS

Student: Mohammed Muneeb
Mentors: Kumar Abhishek, ZeekHuge, Patryk Mezydlo, S. Lockwood-Childs
Code: https://bitbucket.org/muneeb17/pypruss
Wiki: http://elinux.org/BeagleBoard/GSoC/PyPRUSS

{{#ev:youtube|vHxpa6JwqqI||right|PyPRUSS}}

Status

PyPRUSS is a python binding/API for loading firmware and communicating with the PRUs easily. Currently, the project uses PASM which is no longer supported in latest versions and communicates over the older UIO interface.

Proposal

I have completed the requirements listed on the ideas page and created a pull request here.

About me

IRC: muneeb17
Github: https://github.com/MuneebMohammed
School: Birla Institute of Technology and Science, Pilani
Country: India
Primary language: English
Typical work hours: 9:00 - 21:00 IST (GMT+5:30)
Previous GSoC participation: This is my first GSoC participation. I really like the open source ideology and have been using linux and open source hardware/software for some time. The power and impact of open source hardware/software became evident to me during the 'Arduino boom' and how it triggered the Maker Movement. I have always enjoyed doing DIY projects on community-supported platforms, so I feel that it's my turn now to contribute back to the community and GSoC is the ideal place to get started.

About the project

Project name: Update to PyPRUSS

Description

The PyPRUSS is a python binding/API for controlling the PRUs. It provides an easy to use python-based interface for loading firmware, controlling execution and interrupts/memory management for the PRUs, therefore shortening the learning curve for users new to PRU programming and also allowing seamless integration of PRU functionality to a larger python projects. Currently, the PyPRUSS uses PASM for its examples and communicates using the older Userspace IO (UIO) Driver. The goal of this project is to update the API to use the remoteproc/rpsmg interfaces for interacting with the PRUs, port the existing examples to gnupru(since PASM is no longer supported by TI) and also add DMA Support to the API, since it will enable the users to program both the PRUs for their application, instead of reserving one for ARM-PRU communication(as needed in case of rpmsg).

The API

Essentially, the API will provide the following functions:

Remoteproc functions:

  • modprobe()/modunprobe(): Load/unload the pru_rproc module (using modprobe/rmmod)
  • exec_program(): Load Firmware into the PRU Cores (the firmware should be copied to /lib/firmware/am335x-pruX-fw) and enable the PRUs.
  • pru_enable(), pru_disable(), pru_reset(): Control PRU Execution State(start/stop) using the remoteproc sysfs interface (using echo 'start/stop'>/sys/class/remoteproc/remoteprocX/state)

Memory Read/Write functions:
Read/Write to the PRU Data RAM,PRU Shared RAM(map_prumem()/write_prumem()), and the external DDR memory read(map_extmem()), access(get_ddr_addr()/get_ddr_size()) using /dev/mem + mmap()

RPMsg functions:

  • send_msg()/get_msg(): Sending/receiving messages using the rpmsg character device file found at /dev/rpmsg_pru{CHAN_PORT} which will be configured by the RPMsg framework once the channel is created.
  • wait_for_event()/clear_event(): PRU->ARM interrupts/event control can be implemented using the poll interface of the rpmsg character device file.

PRU DMA functions:
Alternatively, the PRU memory read/write functions and the ARM-PRU communication functions can be implemented using the EDMA controller on the SoC. The PRU DMA project from last year provides a Kernel level API to transfer data between ARM-PRU using the EDMA along with a few examples. Now, I plan on implementing a general purpose driver which will expose a sysfs interface, which can then be used by the Python API for communication/data transfer.

PRU Debug functions:
The remoteproc driver provides a debugfs interface for PRU Code Debugging. Using it, we can activate the SINGLE_STEP mode, using which will allow users to step through PRU Code one line at a time and also examine the register contents at the steps(kind of like trace in gdb). The functions will include:

  • pru_pause(), pru_resume(), pru_next_step(): Using the debugfs interface at /sys/kernel/debug/remoteproc/remoteprocX/single_step
  • view_regs(): Pause the PRU(pru_pause()) and the cat the contents of /sys/kernel/debug/remoteproc/remoteprocX/regs.

Miscellaneous functions:

  • pru_pinset(): Configures the pinmux settings for the pins specified. If universal cape not enabled, it will build and load a Device Tree Overlay(DTO) to change the pinmux settings.
  • pru_dma_overlay(): Builds and loads the DTO to configure DMA and load the general purpose dma driver.
  • generate_resctable(): A function to generate resource table for basic examples(The basic examples have most of the part of the resource table similar. For interrupts/event control examples, the script will provide an easy way to generate the resource_table.h file taking in a few parameters as required)
  • generate_dma_resctable(): Generates resource table for DMA examples(taking in buffer address/size, EDMA channel, etc. as parameters)

Examples

1. BeagleScope and pru-software-support package examples: Writing scripts for these examples using the PyPRUSS API(Mainly for testing the remoteproc/rpsmg functions).

2. Moving the existing PASM examples to pru-as(the assembler in the gcc-pru toolchain) and to use remoteproc: The gnupru is the unofficial gcc port for the PRUs. The community would like to eventually shift to gcc and this is a step in that direction. The examples include:

  • blinkleds - loads a program which blinks the user leds 10 times and sends a notification to the host.
  • mem_write - writes to the PRU DRAM and Shared RAM
  • ddr_write - passes the target DDR address to PRU DRAM and then the PRU writes some data to the DDR.
  • speed_test - performs a speed test by toggling an led for some cycles and passing an interrupt upon completion.

3. PRU DMA Examples: Modifying the existing PRU DMA examples to use the API(For testing the dma functions). The firmware will still use the PRU-side library, the kernel module functions will be replaced by a sysfs interface. The examples include:

  • led_pattern - the leds blink with a pattern sequence given by the user, transferred to the PRU through DMA.
  • sensor_data - transfers the sensor data from PRU memory to the DDR and outputs the data.
  • loopback_test - transfers the data from RAM to PRU memory and back, to test if DMA is working correctly.

4. Other Examples ---TODO----

Documentation

Documentation is a very crucial part of the project since the project is mainly directed towards beginners. I would like to spend a significant amount of time on this. It'll include

  • Detailed explanation of the API functions.
  • Walkthrough of the examples.
  • A quick start guide to programming the PRUs in assembly with gcc-pru (as it is not well documented as of now)
  • Setup/build instructions for the project.

Support for other Languages

I also plan on extending the project to support other languages, namely C/C++ and nodejs.

Timeline

Community Bonding Period: April 23 - May 13

  • Re-Read remoteproc/rpmsg and PRU DMA documentation thoroughly.
  • Go through the rproc sysfs, rpmsg sysfs and dma drivers.
  • Go through the PyPRUSS thoroughly.
  • Get the PRU DMA project up and running on the board.
  • Read about implementing a driver to expose sysfs interface, read about Device attributes, kobjects.

Week 1: May 14 - May 20

  • Implement the Remoteproc functions: modprobe(), modunprobe(), pru_enable(), pru_disable(), pru_reset(), exec_program()
  • Implement the RPMsg functions: send_msg(), get_msg()
  • Write bindings to implement the above functions using C, C++ and nodejs as well.

Week 2: May 21 - May 27

  • Implement the RPMsg functions: wait_for_event(), clear_event()
  • Implement the Memory Functions: map_prumem()/write_prumem(), map_extmem(), get_ddr_addr()/get_ddr_size()
  • Write bindings to implement the above functions using C, C++ and nodejs.
  • Test the implemented Remoteproc/RPMsg using a few firmware examples in the BeagleScope repo. Fix Bugs(if any).

Week 3: May 28 - June 3

  • Write a simple general purpose driver which will communicate with the pru dma kernel driver to expose a sysfs interface to userspace. It will mostly involve modifying drivers from the PRU DMA examples to provide a generalised sysfs interface.
  • Test the driver using the DMA examples.

Week 4: June 4 - June 10, End of Phase I

  • Use the sysfs interface provided by the general purpose driver to implement the DMA functions for the PyPRUSS API.
  • Also add C/C++ and nodejs bindings to use the DMA sysfs interface.
  • Test the DMA API functions using the DMA examples.

By the Phase I evaluation, I would deliver the basic PyPRUSS API with Remoteproc/RPMsg functions tested with a few BeagleScope Examples and DMA functions tested with an existing PRU DMA example. Support for C/C++ and nodejs will also be provided.

Week 5: June 11 - June 17, Start of Phase II

Implement the Miscellaneous functions: pru_pinset(), pru_dma_overlay(), generate_resctable(), generate_dma_resctable(). Also, write C/C++ and nodejs code for these functions as well. These functions will reduce a few hurdles a beginner can get stuck at. User doesn't need to worry about dealing with DTOs and Resource tables, and can concentrate more on the code/functionality.

Week 6: June 18 - June 24

  • Implement the PRU Debug functions: pru_pause(), pru_resume(), pru_next_step(), view_regs()
  • Add C/C++ and nodejs support for these functions.
  • Port the existing PASM examples(outlined in the description) to asmpru (TI Assembler)(just to be on a safe side, as it has been tested extensively) and the scripts to use the new API.
  • Test the examples on the API.
  • Move the examples to pru-as(pru-gcc).

Week 7: June 25 - July 1

  • Complete the work on pru-as examples.
  • Fix Bugs (Shouldn't be having major issues with pru-gcc. Had a conversation with dinuxbg, according to him, pru-as and pru-ld are stable and also there is a major release coming up to align gnupru with the TI ABI). Nevertheless, I can use the buffer week to fix major bugs in pru-gcc (if any).
  • Write scripts for the PRU DMA examples (outlined in the description) and also the remaining BeagleScope/pru-software-support-package examples using the API.

Week 8: July 2 - July 8, End of Phase II

  • Convert the snprintf() implementations in the rpmsg sysfs driver to use LOG_printf(). LOG_printf() is a very minimal and less disruptive way to print strings to the rpmsg character device file since the formatting is done on the host-side, whereas the snprintf() performs it on the target-side(PRU) which induces a significant performance overhead on the PRUs.

By the Phase II evaluation, I would deliver a set of working assembly/C examples(as outlined in the description) along with the python scripts demonstrating the use of the API

Week 9-10: July 9 - July 22, Start of Phase III

  • Write Documentation(outlined in the description)
  • Run Final Tests, Receive Mentor Feedback.
  • Final Bug Fixes.
  • Cleaning/refactoring the code.

After the above is completed, I would like to work on a stretch goal which is adding ELF support to PASM.

Week 11: July 22 - July 28

  • Work on a script to convert bin files to ELF files, so that PASM can be used with remoteproc. Although PASM is no longer supported, it was the mainline PRU assembler for a long time and there are people who still prefer using it. I found some steps here which will help.

Week 12: July 29 - Aug 5

  • Buffer week for the project.

Experience and approach

I am a junior-year electronics engineering undergraduate and have had a fair amount of coursework related to embedded development. I have experience with programming microcontrollers(AVRs, Arm Cortex M0/3) in C and I've also worked on BeagleBone Black . I have been using linux as my primary OS for some time now, so I can work my way around embedded linux quite easily. Most of my software related coursework has been done in C and python, & therefore I am fairly proficient in both these languages.

Projects

  • Python Based Information-Retrieval System with Sentiment Classification: In this project, a large corpus of tweets is indexed locally and the ranked retrieval of tweets is performed in response to a search query, with tweets classified according to their sentiment.

Approach

My summer break starts exactly from the GSoC start date and will go on until the first week of August, until when all the work will be essentially completed. I have no other engagements during the summer, so I can devote whole of my time to the project. I plan on dedicating 7-8 hrs per day for the project on weekdays and 4-5 hrs on weekend days which makes the time commitment around 45-50 hrs per week. Since I wont be starting from scratch, I think the timeline above is quite realistic and doable in the available time.

Contingency

There is an abundance of quality documentation on PRUs and remoteproc/rpmsg like the PRU-ICSS guide, remoteproc/rpmsg kernel documentation, wiki, PRU Assembly Guide, etc. One can always resort to IRC/mailing list and also the community forums like TI E2E but the response time may be high. Though, sometimes a thoughtful google search may suffice.

Benefit

PRUs are a tough nut to crack for beginners. The ARM to PRU communication is a somewhat complex process and users are expected to know about the low level details upto some level before starting to write any code. Also, using the remoteproc/rpmsg interface tends to be difficult and timetaking for beginners.This project attempts to shorten the learning curve for users new to programming with PRUs by providing an abstraction over the loading, control and communication process with the PRUs so that they can start focusing on the functionality/app instead and get started with minimum time and effort. The project will also enable users who are working on a larger python project to incorporate PRU functionality in their code seamlessly.