I found the information in this tutorial well written and valuable:
modprobe uio_prussThis "just works", but be haven't tried to do anything with it yet.
Since I don't want to remember to do this modprobe every time I reboot, I edit the file /etc/modules and add one line to the end:
uio_prussAfter a reboot, lsmod shows the driver loaded, so this is fine.
Just for the record, the driver lives at:
/lib/modules/3.8.13/kernel/drivers/uio/uio_pruss.koMy copy of the 3.8.13 kernel source has:
kernel/kernel/drivers/uio/uio_pruss.c kernel/kernel/include/linux/platform_data/uio_pruss.hA quick scan through this tells me that the uio_pruss module does no more than allow access to the PRU, but doesn't really set it up to do anything.
In the /boot partition are a bunch of file with ".dtb" extensions. These are inscrutable binary files that can be manipulated using the "dtc" utility. You decompile them to a ".dtc" file, edit that text file, then convert it back to a ".dtb" file as in the following procedure:
su cd /boot cp am335x-boneblack.dtb am335x-boneblack.dtb_ORIG dtc -I dtb -O dts am335x-boneblack.dtb > bb.dts vi bb.dts dtc -I dts -O dtb bb.dts > am335x-boneblack.dtb rebootThe key thing to edit is a single line below the entry pruss@4a300000 (search for this). Below this make the following change to enable the PRU:
status = "disabled"; -- change to: status = "okay";While you are at it, turn off the heartbeat behavior for the usr0 LED by changing a single line. Find a section that looks like this:
led0 { label = "beaglebone:green:usr0"; gpios = <0x9 0x15 0x0>; linux,default-trigger = "heartbeat"; default-state = "off"; };And change the word "heartbeat" to "none". This will make it easier to run a PRU demo later that will blink this LED.
And indeed, after the reboot the LED stays out.
I am told that there is a new scheme that allows you to have small files that are "device tree fragments" in lieu of modifying the entire device tree file like this, but this works and I don't find it bothersome. It is probably of more interest to people who want to have installable packages (such as to support some kind of "cape").
Note that this includes all the source, so you can run (the assembler anyway) as a cross-assembler hosted on a system of your choice. There are components that need to be built on the BBB, and as far as I am concerned you might as well do everything on the BBB.
The first thing is the somewhat misnamed "prussdrv" -- it is really a library and not a driver, but it will cause less trouble to just leave it named as it is. And in fact once built it becomes libprussdrv.a which satisfies me. It does need to be compiled, and the Makefile has a bizarre setting for the CROSSCOMPILE variable. I edit the Makefile and change an obvious line near the top to make the value for this a blank string:
CROSSCOMPILE=You can also do this externally by setting an environment variable. Then I do this:
su cd am335x_pru_package/pru_sw/app_loader/interface ntpdate -b -s -u pool.ntp.org make cp ../lib/libprussdrv.a /usr/libNotice that I set the time (since my BBB is not yet doing this on its own and if you forget you get clock skew warnings from make). Also I am copying the most useful of the output files to a system location where it will be easy to find.
su cd am335x_pru_package/pru_sw/app_loader/include cp *.h /usr/includeThis copies the two files:
su cd am335x_pru_package/pru_sw/utils/pasm_source sh linuxbuild cd .. cp pasm /usr/binThere was already a pre-built pasm_2.arm executable, identical to pasm, but it does no harm to build it again. Also I once again go ahead and copy the assembler to a proper system directory.
The Makefile also looks for the PRU assember at ../utils/pasm_2, so I change that to /usr/bin/pasm.
su cd am335x_pru_package/pru_sw/example_apps -- edit the Makefile make clean ; makeThis produces a ./bin directory with 7 files:
-rw-r--r-- 1 root root 64 Dec 14 23:14 PRU_PRU0toPRU1_Interrupt.bin -rw-r--r-- 1 root root 56 Dec 14 23:14 PRU_PRU1toPRU0_Interrupt.bin -rwxr-xr-x 1 root root 18022 Dec 14 23:14 PRU_PRUtoPRU_Interrupt -rwxr-xr-x 1 root root 17403 Dec 14 23:14 PRU_memAccessPRUDataRam -rw-r--r-- 1 root root 56 Dec 14 23:14 PRU_memAccessPRUDataRam.bin -rwxr-xr-x 1 root root 18092 Dec 14 23:14 PRU_memAccess_DDR_PRUsharedRAM -rw-r--r-- 1 root root 64 Dec 14 23:14 PRU_memAccess_DDR_PRUsharedRAM.binFor each example there are two files (well there are three files for the first example). The file with the ".bin" extension is the binary image that will go into the PRU, which is quite tiny. The other file is an executable, which links to code in libprussdrv.a and will run on the arm processor and communicate with the PRU code.The reason why the first example has three files is that it has code images for both PRU cores as well as code that runs on the ARM to talk to them.
Run an example
This is easily done:su cd am335x_pru_package/pru_sw/example_apps cd bin ./PRU_PRUtoPRU_InterruptThis produces the following output.INFO: Starting PRU_PRUtoPRU_Interrupt example. AM33XX AM33XX INFO: Initializing example. INFO: Executing example on PRU0. File ./PRU_PRU0toPRU1_Interrupt.bin open passed INFO: Executing example on PRU1. File ./PRU_PRU1toPRU0_Interrupt.bin open passed INFO: Waiting for HALT command. INFO: PRU0 completed transfer. INFO: Waiting for HALT command. INFO: PRU1 completed transfer. Example executed succesfully.As near as I can tell this has worked just fine, and when I run the other two examples, it works fine too.Conclusion
At this point I am done with this stage. I have a working PRU development system.
Feedback? Questions? Drop me a line!Tom's Computer Info / tom@mmto.org