Beaglebone Black PRU Troubles

Hi Zach,

So, first of all. Yes removing the line , commenting it out in uEnv.txt will keep from loading the overlay at boot. As for removing it from the initramfs, I would assume if you reversed the process. e.g. remove the line from uEnv.txt. then remove the file from /lib/firmware, that the script would also remove it from the initramfs. However, I have not looked through the script in that great of detail, and have not tested it personally.

The only real issue here is that the initramfs could get much larger than you needed, in some cases. But otherwise it should be fine. So long as you do not create too many overlays, and “inject” them into the initramfs. In dire cases, where you do need to remove much fromm the initramfs, you could copy the initramfs, extract the file system, modify the file system, re-archive it, then move the old initramfs out of the way, and replace it with the new initial ram disk. It is a rather complex operation, and that would be assuming Roberts script is not already capable of removing files as well.

Thanks Robert,

I just kind of glanced at the script and saw towards the end of the
highlighted code where is chooses the file to load. Didn't see where or or
even if it does not load one based on if another overlay was chosen or
not. But that's not really all that important to me. . . I'll just disable
it in the future.

A general comment is that the Device Tree system is not robust!
I gave up on modifying Device Trees a long time ago. I’m using the “Universal IO” whenever possible:

https://github.com/cdsteinkuehler/beaglebone-universal-io

Avoid touching Device Tree files if you can! AVOID

I just set up the latest Debian IOT image, and Universal IO is already installed.

Both images I tested this morning have unstable Device Trees.
Here is the error from dmesg. This happens after

echo -4 > slots

in the directory

/sys/devices/platform/bone_capemgr

[ 73.214648] bone_capemgr bone_capemgr: slot #4: dtbo ‘univ-emmc-00A0.dtbo’ loaded; overlay id #0
[ 75.337937] eqep 48300180.eqep: ver. 1.0
[ 75.359258] eqep 48302180.eqep: ver. 1.0
[ 75.381966] eqep 48304180.eqep: ver. 1.0
[ 75.527919] CAN device driver interface
[ 75.638311] c_can_platform 481cc000.can: c_can_platform device registered (regs=fa1cc000, irq=196)
[ 75.666734] c_can_platform 481d0000.can: c_can_platform device registered (regs=fa1d0000, irq=197)
[ 274.607591] Unable to handle kernel NULL pointer dereference at virtual address 0000000d
[ 274.616173] pgd = db704000
[ 274.618938] [0000000d] *pgd=9c68a831, *pte=00000000, *ppte=00000000
[ 274.625554] Internal error: Oops: 17 [#1] SMP ARM
[ 274.630319] Modules linked in: spidev c_can_platform c_can can_dev spi_omap2_mcspi pwm_tiecap tieqep pwm_tiehrpwm usb_f_acm u_serial usb_f_rndis g_multi usb_f_mass_storage u_ether libcomposite omap_aes_driver omap_sham omap_rng rng_core evdev uio_pdrv_genirq uio 8021q garp mrp stp llc

I predict I will be able to work with this image as long as I don’t do anything to Device Tree and don’t touch the slots!!!

Regards,
Greg

This has never worked (even in 3.8.13) and will never work. :wink:

Regards

Is there a better way to get the job done? Or better “don’t touch that”?

Yeap, the reliably way to unload the cape is to reboot… this is why the cape universal with config-pin is so useful… config-pin allows us to map a pin as function A then change it to function B without rebooting.

Regards,

OK, I did not understand that about Universal IO overlays!

Another question: I see the univ-emmc cape gets loaded after activating Remoteproc kernel modules. This is correct and expected behavior? I was a little surprised to see the coupling between device tree and kernel modules in this manner.

Very big fan here of Universal IO! Device tree hassles a seriously large entry barrier for newbies like myself. Two thumbs up for Universal IO!

Good news to report here, PRU ADC project working fine with the IOT image based on 4.4.27-ti-r62.
I was trying the console image, but I am lazy and there was just too much stuff to install. So IOT it is.

The only remaining mystery is why the firmwares do not start at boot. Removing and inserting pru_rproc works around this problem.
I’ve added significant material to the section on Remoteproc and C compiler set-up for the project thanks to the info in this discussion:

https://github.com/Greg-R/pruadc1

Zach B I hope your project is going well. Let us know what happens.

Many thanks to Beagleboard and Robert Nelson for supporting this very cool development board family.
There are tons of amazing things to learn.

Regards,
Greg

Hey everyone so I took one step forward and one step back. With the last bit of help from Robert I was able to properly disable the universal overlay and load my own. It appears that my device overlay loads correctly. When I went to test things today however I can’t seem to get the remote_proc to turn on by following the elinux example like last time. I follow all of the steps. I get no errors, but nothing happens. I haven’t looked through the boot dmesg yet so it could be in there. Is there another way to manually turn on the remote_proc?

On a different note after reading some of your comments I am a bit confused. Is the device tree overlay the proper way to go about setting the header pins to the PRU or not? Also is there a command line method to working with the PRUs that would let me test the pins to ensure they are working?

I tried compiling a simple c script to run the PRU but I keep getting the error pruss/prussdrv.h: no such file or directory. Are the pruss files something that needs to be included on my LIBRARY path or LD_LIBRARY path or is it an extra package I need to download?

Just my advice, especially for a newbie PRU person (maybe even an experienced one too), don’t touch the Device Tree! At least not directly:

https://github.com/cdsteinkuehler/beaglebone-universal-io

(Note the path to slots is not the same for 4x kernels)

I’ve been using the Debian 8.6 IOT image and the “Universal IO” is already installed, ready to work its magic.
Follow the directions at the above repository. This will save you much time fiddling with the Device Tree stuff, highly recommended!
The config-pin utility is AWESOME, try it!

One thing config-pin can’t do. And that is change the pull-up/pull-down settings on the pads. In that case you may have to tweak a device tree.
But this is relatively simple and won’t waste piles of your time debugging.

Another something to be aware of which can burn time like no tomorrow: Header P8. There are pins on this header which determine how
the boot process proceeds. Not all of them, but some of the overlap possible PRU IO. I would avoid these if you can! Use config-pin and
set your PRU IO to pins on header P9 as required. Some pins on P8 are safe, but proceed with caution.
Even light resistive loading on these pins will corrupt the boot process!

You can go to the Beaglebone Black system reference manual to see this:

http://elinux.org/Beagleboard:BeagleBoneBlack#Hardware_Files

Check out page 68, diagram Figure 38. Note the “LCD_DATA” pins.
Then go to page 84, and you can see which pins on P8 to avoid.
There are probably enough PRU IO possible to route to P9 for many projects.

I think prussdrv is a UIO related kernel module, not Remoteproc related. I don’t recall seeing that one.
Activation of Remoteproc may not have happened. Use lsmod and look for pru_rproc, pruss, and pruss_intc.

With regards to manually running Remoteproc, you can

modprobe pru_rproc

to insert and start Remoteproc and

rmmod pru_rproc

to remove it (using root privilege).

To stop and start firmwares already loaded into the PRUs:

echo “4a334000.pru0” > /sys/bus/platform/drivers/pru-rproc/bind
echo “4a338000.pru1” > /sys/bus/platform/drivers/pru-rproc/bind

echo “4a334000.pru0” > /sys/bus/platform/drivers/pru-rproc/unbind
echo “4a338000.pru1” > /sys/bus/platform/drivers/pru-rproc/unbind

So this is the Debian image I am using successfully:

bone-debian-8.6-iot-armhf-2016-10-30-4gb.img

Get that here:

http://elinux.org/Beagleboard:BeagleBoneBlack_Debian

Once again, using the above image, don’t touch device tree files (except one very trivial change to activate Remoteproc) and use config-pin to change pin modes to PRU. All ready to go on this image.
Get Remoteproc activated and see if you can get the Remoteproc related kernel modules to appear in lsmod.

I’ve attempted to very carefully describe the process in the PDF file here and did a bunch of updates last weekend:
https://github.com/Greg-R/pruadc1/tree/master/doc/PRUADC1latex

Regards,
Greg

Thanks for the detailed response that helped clear up a bit of confusion I was having. I’ve also been rereading through your pdf. I got the remote_proc up and running again. I started playing around with config-pin and “Universal IO” and was able to successfully toggle the pins how I wanted. However, I still have a few questions. I am debugging with a simple led attached to some pins, ultimately I am going to be driving some ESCs and then later building a custom brushless DC motor controller but that’s another animal.

First question, when I set pin P8_11 to “pruout”, my testing led turns on, does this mean that the pin is automatically set to “out hi” until I change it again with config-pin? Is there a way to set the pin mode to PRU control and then modify it by writing the desired 1 or 0 to the corresponding register in the PRU code?

Second question, is there a way to load a PRU binary program (either compiled c or assembly) directly to the PRU’s from the command line or do I need a separate c program for that? That’s the part I seems to be stumbling over is how to get the program onto the PRU.

I have some device tree questions, even though you recommended against them. With the device trees, is there a list somewhere of the possible targets that you can set? I have seen &ocp or &pruss and a few others but I don’t fully understand what these mean. If anyone has a good link to learning about each piece of the device trees I will gladly take that as well.

Just my advice, especially for a newbie PRU person (maybe even an experienced one too), don’t touch the Device Tree! At least not directly:

https://github.com/cdsteinkuehler/beaglebone-universal-io

(Note the path to slots is not the same for 4x kernels)

I’ve been using the Debian 8.6 IOT image and the “Universal IO” is already installed, ready to work its magic.
Follow the directions at the above repository. This will save you much time fiddling with the Device Tree stuff, highly recommended!
The config-pin utility is AWESOME, try it!

One thing config-pin can’t do. And that is change the pull-up/pull-down settings on the pads. In that case you may have to tweak a device tree.
But this is relatively simple and won’t waste piles of your time debugging.

Another something to be aware of which can burn time like no tomorrow: Header P8. There are pins on this header which determine how
the boot process proceeds. Not all of them, but some of the overlap possible PRU IO. I would avoid these if you can! Use config-pin and
set your PRU IO to pins on header P9 as required. Some pins on P8 are safe, but proceed with caution.
Even light resistive loading on these pins will corrupt the boot process!

You can go to the Beaglebone Black system reference manual to see this:

http://elinux.org/Beagleboard:BeagleBoneBlack#Hardware_Files

Check out page 68, diagram Figure 38. Note the “LCD_DATA” pins.
Then go to page 84, and you can see which pins on P8 to avoid.
There are probably enough PRU IO possible to route to P9 for many projects.

I think prussdrv is a UIO related kernel module, not Remoteproc related. I don’t recall seeing that one.
Activation of Remoteproc may not have happened. Use lsmod and look for pru_rproc, pruss, and pruss_intc.

With regards to manually running Remoteproc, you can

modprobe pru_rproc

to insert and start Remoteproc and

rmmod pru_rproc

to remove it (using root privilege).

To stop and start firmwares already loaded into the PRUs:

echo “4a334000.pru0” > /sys/bus/platform/drivers/pru-rproc/bind
echo “4a338000.pru1” > /sys/bus/platform/drivers/pru-rproc/bind

echo “4a334000.pru0” > /sys/bus/platform/drivers/pru-rproc/unbind
echo “4a338000.pru1” > /sys/bus/platform/drivers/pru-rproc/unbind

So this is the Debian image I am using successfully:

bone-debian-8.6-iot-armhf-2016-10-30-4gb.img

Shouldn’t be any deltas, but can you use 2016-11-06 from https://beagleboard.org/latest-images because we are standardizing on that image for a while and pushing manufacturers to shift to it in production.

It’s generally considered good design practice to bring up GPIOs low. But there are exceptions. I’m not sure what the PRU will do when it is disabled.
I did the same thing months ago, and I do remember LEDs being lit or dimly lit after boot. Ultimately I got past that concern and it didn’t seem to be a problem.

The Remoteproc framework does the job of loading the firmware into the PRUs. This happens seamlessly and the user doesn’t do this explicitly. The firmwares should be compiled with clpru and renamed to am335x-pru0-fw and am335x-pru1-fw respectively and then copied to /lib/firmware. So you have 2 firmwares each indendently running in the PRU0 and PRU1. Of course they can interact in various ways. You could also use only one PRU if you don’t need both by only having one firmware in /lib/firmware.

There are special files which the clpru must incorporate into the compilation process and ultimately the firmware. I’ve added a little section on this in the PDF file. The TI folks gave me this info. Remoteproc and Linker involved.

Best thing to do is to examine the labs and examples in the PRU software package provided by TI. The labs instructions are designed for the CCS IDE. You can avoid that and get everything done on the Beaglebone via SSH and command line. Really not that hard and you need to be an expert at the command line anyway if you want to be an embedded systems designer. Maybe I’ll use CCS later, but for now SSH + command line is working for me well. Look at the Labs instructions anyway, as this will give a whole bunch of hints and clues on how to deal with Remoteproc and PRUs. There is also an examples directory which overlaps some of the labs. Good stuff in there, you can dig into the C code and see how to get things done.

A good start is the usual LED blinker, this will show how to manipulate the __R30 register to make the header pins go HIGH and LOW programatically from the PRUs.
You will find the compiler intrinsic __delay_cycles() to be extremely useful.

Cool, I’ll be moving to that image, thanks for the heads up!

Regards,
Greg

I understand that bringing up GPIOs low is good practice. I meant when I set the P8_11 using “config-pin P8_11 pruout” the pin is automatically pulled high it appears. Is there a way to set it as a “pruout” but as a low pruout to start. It appears to be defaulting to “HI” mode when set to “pruout”

Also I had thought that remoteproc was a program with an interface that allowed the user to load a compiled program to the PRU when the host c script was run, I didn’t realize it only kicked in at initialization and loaded specific files in /lib/firmware. I was origianlly under the assumption that I needed to enable the remote_proc and uio_pruss and then use the following API in order to load and run the PRU program.

http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader_API_Guide#prussdrv_map_prumem

Am I over complicating things? Also I have been avoiding use CCS because I wanted to avoid dependencies on automatic tools that abstract away what is running and how.

Remoteproc and RPMsg are kernel modules. Remoteproc/RPMsg live in the kernel, but they can communicate with user space via character device files and the sysfs virtual file system.

The PRUSSDRV is totally different, not related to Remoteproc in any way to my knowledge.

Best introductory page on Remoteproc and RPMsg is:

http://processors.wiki.ti.com/index.php/PRU-ICSS_Remoteproc_and_RPMsg

If you look at the Remoteproc examples, the “user space” C program reads/writes to a character device file in /dev.

I’m not sure what is going on with the GPIO coming out of boot high. If you look at the C code for the example firmwares, a lot of them set __R30 = 0 right away and this would pull out the pruouts to low. If the PRUs are inactive, not sure what defines the state. You could switch the pin mode to pruout after the firmware is running and the pruout is deterministically set to LOW. Might work, easy enough to try.

So I finally got some time to work with the PRUs again. I still seem to be having some issues with remoteproc. I got the c code for PRU0 to compile and I moved it to /lib/firmware under the correct name. I also followed the steps outlined in the e-linux exercise for enabling remote_proc as well as the steps outlined in greg’s PDF. I can’t seem to get the remoteproc to activate. Whenever I pole “/sys/bus/platform/devices” the only pru related name I get out is “ocp:pruss@4a300000”. The device not showing up also means when I try to echo the enable command to bind I get a “No such device” error.

Any suggestions on how to get remote_proc activated and working? Also the program flow as I understand is the pru code needs to be compiled and placed in /lib/firmware under the correct name. Once the remote_proc is activated once by doing a small device tree alteration I just have to call modprobe pru_rpoc to turn it on. From there I can echo “4a334000.pru0” to the bind folder and the code that was loaded onto the pru when remote_proc was enabled will execute?

Zach

Pretty much sounds correct. Did you create a file

/etc/modprobe.d/pruss-blacklist.conf

and the single line in this file is:

blacklist uio_pruss

Can you paste in your dts file change? Here is what I have:

/* pruss: pick one: */

/*

  • /etc/modprobe.d/pruss-blacklist.conf

Zach I think you mentioned you were interested in motor controllers:

http://www.ti.com/lit/ug/tidubj6/tidubj6.pdf

I just finished the Coursera course “Control of Mobile Robots”.
The course has some info on a Beaglebone based robot.
I want to implement some, but probably not all. I’m going to be drilling
into the PID controller project with the Remoteproc and see how far I can get.

Regards,
Greg

Greg,

Thanks for the link I to the motor controller. I actually ended up figuring out late last night what was preventing remote_proc from running properly. I had the line

`
dtb=am335x-boneblack-overlay.dtb

`
uncommented in my “uEnv.txt” file. I guess that device overlay prevented the remote_proc from properly loading. When I commented that line out and left the standard boot file “universaln” it came right on at startup no problem. The proper devices also show up in “/sys/bus/platform/devices” now that I fixed the issue. Without that extra overlay to disable the HDMI is there any way to reclaim all of the PRU pins on header 8? Is that something that config-pin will handle or will it require a custom overlay or altering the main overlay that is loaded at boot?

Zach