Beaglebone Black PRU Troubles

2,881 views
Skip to first unread message

Zach B

unread,
Nov 8, 2016, 11:42:25 AM11/8/16
to BeagleBoard
I have spent a solid 12 hours trying to get the PRU's on the beaglebone to work. So far I seem to be completely stuck at the getting the device overlay to work as well as enabling the remoteproc. I have tried to piece together all of the information I have found on the internet but it is either out of date or extremely fragmented. I can't seem to find a current working example or I hit a wall when following along as said previously.

Setup/Environment
I have updated the kernel on the beaglebone followed by multiple "updates", "upgrades" and "dist-upgrades". As far as I can tell I am using the most recent version of everything.
  • Beaglebone Black
  • Debian 8.6
  • kernel 4.4.30-ti-r64
  • dtc 1.4.1
Sample Code
Device Overlay File [PRU-GPIO-BLINK-00A0.dts]:
   
// Setup file for basic PRU GPIO Blinking LED
   
   
/dts-v1/;
   
/plugin/;
   
   
/ {
            compatible
= "ti,beaglebone", "ti,beaglebone-black";
   
            part
-number = "PRU-GPIO-BLINK";
            version
= "00A0";
   
           
// This overlay uses the following resources
            exclusive
-use = "P8.12";
   
            fragment@0
{
                    target
= <&am33xx_pinmux>;
                    __overlay__
{
   
                            gpio_pins
: pinmux_gpio_pins {
                                    pinctrl
-single,pins = <
                                           
0x034   0x06
                                   
>;
                           
};
                   
};
           
};
   
            fragment@1
{
                    target
= <&pruss>;
                    __overlay__
{
                            status
= "okay";
                            pinctrl
-names = "default";
                            pinctrl
-0 = <&gpio_pins>;
                   
};
           
};
   
};



The above code compiles using:  
root@beaglebone:/lib/firmware# dtc -O dts -o /lib/firmware/PRU-GPIO-BLINK-00A0.dtbo -b 0 -@ PRU-GPIO-BLINK.dts

When I go to add this to the bone_capemgr using:
root@beaglebone:/lib/firmware# echo "PRU-GPIO-BLINK" > /sys/devices/platform/bone_capemgr/slots

I end up getting either a "No Such File or Directory" error or a "File Exists" error. I have disabled the HDMI in uEnvt.txt like many people have recommended by simply uncommenting the line:
dtb=am335x-boneblack-emmc-overlay.dtb

On top of the above I tried following the exercise here: http://elinux.org/EBC_Exercise_30_PRU_via_remoteproc_and_RPMsg  
I make it through most of that exercise, up until I hit the enabling the remoteproc portion. When I go to "uncomment"
#include "am33xx-pruss-rproc.dtsi
I can't seem to find it anywhere in the file. When I simply add the line to the file and try calling `make` the compiler complains that it can't find the file and fails the build.  

If anyone is curious here is the output when I run
cat /sys/devices/platform/bone_capemgr/slots

     0: PF----  -1
     
1: PF----  -1
     
2: PF----  -1
     
3: PF----  -1
     
4: P-O-L-   0 Override Board Name,00A0,Override Manuf,univ-emmc

Question  
Does anyone have any suggestions as to why my device overlay is not working and I can't follow along with the exercise on elinux? I am pretty much stuck at this point and most of the examples online reference out of date pathing or approaches. Is there a package that I am missing? From what I have read it seems like all of the compilers and loaders come built into the new beaglebone distributions now. If anyone needs clarification or I forgot to mention something I will be happy to provide it.

Robert Nelson

unread,
Nov 8, 2016, 11:50:35 AM11/8/16
to Beagle Board, zbro...@gmail.com
With the elinux article, make sure /opt/source/dtb-4.4-ti is up-to-date..

cd /opt/source/dtb-4.4-ti ; git pull

Regards,

--
Robert Nelson
https://rcn-ee.com/

Greg

unread,
Nov 8, 2016, 1:08:59 PM11/8/16
to BeagleBoard
I think I know exactly what is wrong.  You need to activate the Remoteproc PRU framework.  This is no longer active by default.
Robert Nelson's script which is available via Github repository will fix the problem.

I have been working on detailed documentation of the entire process to activate the framework and set up the C compiler:


Go to the chapter "Setting Up the Remoteproc PRU and Compiler on the Beaglebone Green".

Now, the chapter is not completely finished.  I am still seeing a problem with the configuration
At boot, the PRU firmwares are not starting correctly.  I don't understand why this is.

However, you can do this:

rmmod pru_rproc

and then

modprobe pru_rproc

The firmwares will start running.
More investigation, required, but at least there is some path to getting things working for now.

I will do some more work on this later today.

Regards,
Greg

Zach B

unread,
Nov 8, 2016, 1:09:58 PM11/8/16
to BeagleBoard, zbro...@gmail.com
Thanks Robert! I'll give that a try when I get a chance later today. Will that possibly also solve my issue with my device overlay not applying to the slot. Everything I have looked at says that there should be no error messages when applying the overlay but that's all I get.

Zach

William Hermans

unread,
Nov 8, 2016, 1:51:43 PM11/8/16
to beagl...@googlegroups.com
On Tue, Nov 8, 2016 at 11:08 AM, Greg <soapy...@comcast.net> wrote:
I think I know exactly what is wrong.  You need to activate the Remoteproc PRU framework.  This is no longer active by default.
Robert Nelson's script which is available via Github repository will fix the problem.

I have been working on detailed documentation of the entire process to activate the framework and set up the C compiler:


Go to the chapter "Setting Up the Remoteproc PRU and Compiler on the Beaglebone Green".

Now, the chapter is not completely finished.  I am still seeing a problem with the configuration
At boot, the PRU firmwares are not starting correctly.  I don't understand why this is.

Probably because the device tree file you're trying to load at boot is not in the initramfs.

However, you can do this:

rmmod pru_rproc

and then

modprobe pru_rproc

The firmwares will start running.
More investigation, required, but at least there is some path to getting things working for now.

I will do some more work on this later today.

Regards,
Greg


On Tuesday, November 8, 2016 at 11:42:25 AM UTC-5, Zach B wrote:
I have spent a solid 12 hours trying to get the PRU's on the beaglebone to work. So far I seem to be completely stuck at the getting the device overlay to work as well as enabling the remoteproc. I have tried to piece together all of the information I have found on the internet but it is either out of date or extremely fragmented. I can't seem to find a current working example or I hit a wall when following along as said previously.

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/ce0bf666-a685-4e22-adc6-6bab07d7b73d%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Greg

unread,
Nov 8, 2016, 6:05:42 PM11/8/16
to BeagleBoard
The problem is common to both boards, one with kernel a few months old, and another newer one:

Older:
4.4.12-ti-r31
Newer:
4.4.27-ti-r62

The older board I have used for many hours of experimentation with the Remoteproc/PRUs, and never had a problem.
I never noticed the firmwares were not starting at boot!

Looking at dmesg, these lines stand out:

[    4.746736] ti-pruss 4a300000.pruss: creating PRU cores and other child platform devices
[    4.747946] irq: no irq domain found for /ocp/pruss@4a300000/intc@4a320000 !
[    4.748539] irq: no irq domain found for /ocp/pruss@4a300000/intc@4a320000 !

And then a bunch of lines indicating that the firmwares did not load and start, here are the lines for PRU0:

[    4.796962]  remoteproc1: 4a334000.pru0 is available
[    4.796990]  remoteproc1: Note: remoteproc is still under development and considered experimental.
[    4.796999]  remoteproc1: THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.
[    4.797306]  remoteproc1: Direct firmware load for am335x-pru0-fw failed with error -2
[    4.797326]  remoteproc1: failed to load am335x-pru0-fw
[    4.832461] pru-rproc 4a334000.pru0: booting the PRU core manually
[    4.832497]  remoteproc1: powering up 4a334000.pru0
[    4.832614]  remoteproc1: Direct firmware load for am335x-pru0-fw failed with error -2
[    4.832630]  remoteproc1: request_firmware failed: -2
[    4.837857] pru-rproc 4a334000.pru0: rproc_boot failed
[    4.959415]  remoteproc1: releasing 4a334000.pru0
[    4.959590] pru-rproc: probe of 4a334000.pru0 failed with error -2

There was a change a while back from "mailboxes" to system interrupts.  Hmmmmm...

But even after all of this, the PRUs can be started up using either modprobe pru_rproc, or commands to sysfs:

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

So the above commands could be put in .profile or other start-up sequence, but still would like to root cause the kernel log messages.

Regards,
Greg




Brett Hamilton

unread,
Nov 9, 2016, 1:15:13 PM11/9/16
to BeagleBoard
I think your device tree overlay is not quite right, I see P8.11 set as mode 6 with internal pull down, but you've set exclusive use on P8.12.

I usually use http://kilobaser.com/blog/2014-07-28-beaglebone-black-devicetreeoverlay-generator to look up pinmux settings because it's easier and less error prone than doing it manually.

For reference because it's not especially easy to find, the pinmux register bits are defined in the AM335x TRM section 9.2.2, page 1356. My version is dated Feb. 2015, TI doc # SPRUH73L.


On Tuesday, November 8, 2016 at 11:42:25 AM UTC-5, Zach B wrote:

Zach B

unread,
Nov 10, 2016, 8:28:23 AM11/10/16
to BeagleBoard
Hey everyone, I wanted to give an update. I got the remote_proc to turn on last night. It was as simple as updating my repo like Robert had mentioned. I also made the correction that Brett mentioned about the pins. There is still something wrong in my device overlay file that is causing an "invalid arguement" error but I am going to try and sort that out tonight. I'll post again with the corrected version once I get it working and can use the PRU.

Thanks again for your help.

Greg

unread,
Nov 10, 2016, 9:27:47 AM11/10/16
to BeagleBoard
Once you get everything solid, please take a look at dmesg after boot.
I'm curious to see if you get successful PRU firmware start-up.

Greg

Zach B

unread,
Nov 11, 2016, 1:27:22 PM11/11/16
to BeagleBoard
Hi everyone,

So I messed around with my beaglebone a little bit last night. I worked out the issues in my device tree source file so it is now compiled but I can't seem to get anything to echo properly to "slots"
I compile my ".dtb" file but when I go to call the comman:
echo PRU-GPIO-BLINK > /sys/devices/platform/bone_capemgr/slots
I continually get the error:
-bash: echo: write error: No such file or directory
Is there are a different way to enable my device overlay or set the pins to the correct mode for the PRU? I have even tried copying, compiling and attempting to export the device tree overlay example from adafruit and still no luck.

The names of my files in /lib/firmware are as follows:
PRU-GPIO-BLINK.dts
PRU
-GPIO-BLINK-00A0.dtb
The part-number name in the .dts file is "PRU-GPIO-BLINK". Am I still missing something? I can post the updated ".dts" file if it would help.

P.S. I have two questions since I am still relatively new at this:
1) What is a blacklist and why was it necessary to export to the .conf file to enable the remote_proc?
2) What is dmesg and where do I check them? Are you referring to "/var/log/syslog"?

Zach

Zach B

unread,
Nov 11, 2016, 1:42:02 PM11/11/16
to BeagleBoard
I wanted to add on to this that when I switch the Device Tree Blob file extension to ".dtbo" instead of ".dtb" I get the error:
-bash: echo: write error: File exists
instead of the file not found error I was getting previously.

Robert Nelson

unread,
Nov 11, 2016, 1:44:22 PM11/11/16
to Beagle Board
On Fri, Nov 11, 2016 at 12:42 PM, Zach B <zbro...@gmail.com> wrote:
> I wanted to add on to this that when I switch the Device Tree Blob file
> extension to ".dtbo" instead of ".dtb" I get the error:
> -bash: echo: write error: File exists
> instead of the file not found error I was getting previously.

if you type "dmesg" after that, the kernel should give you a hint of
what happend..

Zach B

unread,
Nov 11, 2016, 1:53:16 PM11/11/16
to BeagleBoard
wow that is incredible useful, I didn't even realize that is what dmesg did. Here is the output I got:
[ 2117.571792] bone_capemgr bone_capemgr: part_number 'PRU-GPIO-BLINK', version 'N/A'
[ 2117.571876] bone_capemgr bone_capemgr: slot #10: override
[ 2117.571920] bone_capemgr bone_capemgr: Using override eeprom data at slot 10
[ 2117.571967] bone_capemgr bone_capemgr: slot #10: 'Override Board Name,00A0,Override Manuf,PRU-GPIO-BLINK'
[ 2117.573674] bone_capemgr bone_capemgr: slot #10: PRU-GPIO-BLINK conflict P8.11 (#4:univ-emmc)
[ 2117.582657] bone_capemgr bone_capemgr: slot #10: Failed verification

It looks like I am having a conflict with the emmc on the beaglebone, so I assumes that means I should disable the emmc in my uEnv.txt? Also I am a bit confused as to why it says the version is 'N/A' when I have it set to '00A0' in my dts file.

Zach B

unread,
Nov 11, 2016, 2:05:37 PM11/11/16
to BeagleBoard
I just tried the various combinations of enabling and disabling the HDMI, emmc, both and neither and regardless of what it is set to I get a conflict on P8.11 every time. Is there a key component that I am missing somewhere or a different way I should be going about this?

Robert Nelson

unread,
Nov 11, 2016, 2:27:08 PM11/11/16
to Beagle Board
On Fri, Nov 11, 2016 at 12:53 PM, Zach B <zbro...@gmail.com> wrote:
> wow that is incredible useful, I didn't even realize that is what dmesg did.
> Here is the output I got:
> [ 2117.571792] bone_capemgr bone_capemgr: part_number 'PRU-GPIO-BLINK',
> version 'N/A'
> [ 2117.571876] bone_capemgr bone_capemgr: slot #10: override
> [ 2117.571920] bone_capemgr bone_capemgr: Using override eeprom data at slot
> 10
> [ 2117.571967] bone_capemgr bone_capemgr: slot #10: 'Override Board
> Name,00A0,Override Manuf,PRU-GPIO-BLINK'
> [ 2117.573674] bone_capemgr bone_capemgr: slot #10: PRU-GPIO-BLINK conflict
> P8.11 (#4:univ-emmc)
> [ 2117.582657] bone_capemgr bone_capemgr: slot #10: Failed verification

univ-emmc is the userspace overlay we automatically load on bootup

open /boot/uEnv.txt

you'll notice a cape_universal=enable

remove that and reboot

William Hermans

unread,
Nov 11, 2016, 2:34:11 PM11/11/16
to beagl...@googlegroups.com
What does that actually do Robert ? I've done this myself in the past, and haven't noticed a difference one way or another. Granted, I am using a heavily modified universal overlay. . . but with only specific pins muxed the way I need it, and everything else stripped out.

Robert Nelson

unread,
Nov 11, 2016, 2:46:26 PM11/11/16
to Beagle Board
>> univ-emmc is the userspace overlay we automatically load on bootup
>>
>> open /boot/uEnv.txt
>>
>> you'll notice a cape_universal=enable
>>
>> remove that and reboot
>>
>> Regards,
>>
>
> What does that actually do Robert ? I've done this myself in the past, and
> haven't noticed a difference one way or another. Granted, I am using a
> heavily modified universal overlay. . . but with only specific pins muxed
> the way I need it, and everything else stripped out.

It's the hint to load it on bootup:

https://github.com/RobertCNelson/boot-scripts/blob/master/boot/am335x_evm.sh#L442-L531

Zach B

unread,
Nov 11, 2016, 3:14:41 PM11/11/16
to BeagleBoard
Thanks Robert! That solved the problem I have been having. The overlay loaded and everything looks to be working. One follow up question I do have is what is the proper way to load a custom overlay on startup? Is there a way to enable multiple overlays as long as they don't try to use the same pins?

Robert Nelson

unread,
Nov 11, 2016, 3:22:17 PM11/11/16
to Beagle Board
On Fri, Nov 11, 2016 at 2:14 PM, Zach B <zbro...@gmail.com> wrote:
> Thanks Robert! That solved the problem I have been having. The overlay
> loaded and everything looks to be working. One follow up question I do have
> is what is the proper way to load a custom overlay on startup? Is there a
> way to enable multiple overlays as long as they don't try to use the same
> pins?

Add it /boot/uEnv.txt:

##Example v4.1.x
#cape_disable=bone_capemgr.disable_partno=
#cape_enable=bone_capemgr.enable_partno=

##Example v4.1.x
#cape_disable=bone_capemgr.disable_partno=
cape_enable=bone_capemgr.enable_partno=PRU-GPIO-BLINK

You'll need to copy PRU-GPIO-BLINK-00A0.dtbo to /lib/firmware/

then run:

sudo /opt/scripts/tools/developers/update_initrd.sh

To copy the new *.dtbo object into the initrd..

Then just reboot, and you should see your overlay loaded..

Zach B

unread,
Nov 11, 2016, 4:01:42 PM11/11/16
to BeagleBoard
Great, thanks! And not to be a pest but I assume in order to undo that change I simply comment the line that I add to the uEnv.txt and that's it? Should I worry about removing the *.dtbo object from the initrd?

William Hermans

unread,
Nov 11, 2016, 7:53:46 PM11/11/16
to beagl...@googlegroups.com
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.

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscribe@googlegroups.com.

William Hermans

unread,
Nov 11, 2016, 7:57:04 PM11/11/16
to beagl...@googlegroups.com
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.

Greg

unread,
Nov 12, 2016, 9:13:10 AM11/12/16
to BeagleBoard
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


Robert Nelson

unread,
Nov 12, 2016, 11:17:58 AM11/12/16
to Beagle Board
On Sat, Nov 12, 2016 at 8:13 AM, Greg <soapy...@comcast.net> wrote:
> 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

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

Regards

Greg

unread,
Nov 12, 2016, 11:39:00 AM11/12/16
to BeagleBoard
Is there a better way to get the job done?  Or better "don't touch that"?

Robert Nelson

unread,
Nov 12, 2016, 11:53:26 AM11/12/16
to Beagle Board

On Nov 12, 2016 10:39 AM, "Greg" <soapy...@comcast.net> wrote:
>
> 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,

Greg

unread,
Nov 12, 2016, 12:14:52 PM11/12/16
to BeagleBoard
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!

Greg

unread,
Nov 12, 2016, 4:03:09 PM11/12/16
to BeagleBoard
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:


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

Zach B

unread,
Nov 14, 2016, 10:17:40 PM11/14/16
to BeagleBoard
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?

Greg

unread,
Nov 15, 2016, 8:06:38 AM11/15/16
to BeagleBoard

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:


(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:


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:


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:

Regards,
Greg

Zach B

unread,
Nov 15, 2016, 10:13:32 AM11/15/16
to BeagleBoard
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.

Jason Kridner

unread,
Nov 15, 2016, 10:49:41 AM11/15/16
to beagl...@googlegroups.com
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. 


Get that here:


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:

Regards,
Greg

On Monday, November 14, 2016 at 10:17:40 PM UTC-5, Zach B wrote:
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?


--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/3fbe8061-3943-4180-b56a-d8998af92af9%40googlegroups.com.

Greg

unread,
Nov 15, 2016, 10:52:08 AM11/15/16
to BeagleBoard
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.

Greg

unread,
Nov 15, 2016, 12:44:18 PM11/15/16
to BeagleBoard
Cool, I'll be moving to that image, thanks for the heads up!

Regards,
Greg

Zach B

unread,
Nov 15, 2016, 1:16:43 PM11/15/16
to BeagleBoard
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.

Greg

unread,
Nov 15, 2016, 2:29:46 PM11/15/16
to BeagleBoard
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.

Zach B

unread,
Nov 17, 2016, 11:56:00 PM11/17/16
to BeagleBoard
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

Greg

unread,
Nov 18, 2016, 7:26:49 AM11/18/16
to BeagleBoard
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
 *
 * blacklist uio_pruss
 */

#include "am33xx-pruss-rproc.dtsi"

/*
 * /etc/modprobe.d/pruss-blacklist.conf
 *
 * blacklist pruss
 * blacklist pruss_intc
 * blacklist pru-rproc
 */

/* #include "am33xx-pruss-uio.dtsi" */

The above is at this path on my board:

/opt/scripts/tools/dtb-rebuilder/src/arm/am335x-bonegreen.dts

So the only change is to unquote a single line in the file:  #include "am33xx-pruss-rproc.dtsi"

I git cloned the dtb-rebuilder into the same directory as the other utility scripts.
You ran make and then make install in the dtb-rebuilder directory?

I went through this process again on the latest IOT image and it worked:

Greg

unread,
Nov 18, 2016, 7:33:30 AM11/18/16
to BeagleBoard
Zach I think you mentioned you were interested in motor controllers:


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

Zach B

unread,
Nov 18, 2016, 8:56:36 AM11/18/16
to BeagleBoard
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
Message has been deleted

Zach B

unread,
Nov 18, 2016, 10:06:07 AM11/18/16
to BeagleBoard
In trying to test my code for the PRUs is there a good way to check and see if binary is being loaded into the PRU properly and check whether or not it is executing. I have a simple LED circuit running some basic blink code but nothing seems to be occurring. Also with everything activated, the pru_rproc running and the devices showing up as they should I still sometimes get "no such device" when I try to bind pru0, have you ever run into this issue?

When attempting to bind pru0 I get the following outpur from dmesg:
[  697.537395]  remoteproc1: 4a334000.pru0 is available
[  697.537435]  remoteproc1: Note: remoteproc is still under development and considered experimental.
[  697.537450]  remoteproc1: THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.
[  697.537926]  remoteproc1: Unsupported class: 254
[  697.546973] pru-rproc 4a334000.pru0: booting the PRU core manually
[  697.547013]  remoteproc1: powering up 4a334000.pru0
[  697.547250] pru-rproc 4a334000.pru0: rproc_boot failed
[  697.557946]  remoteproc1: releasing 4a334000.pru0
[  697.559696] pru-rproc: probe of 4a334000.pru0 failed with error -12
does this mean it's an error in the code I am trying to load into it?

Below is a copy of the assembly code that I am attempting to load if it helps
Enter code here...; blink.p: demonstration of PRU on the BeagleBone Black
; blink LED connected to P8_11 ten times
.origin 0
.entrypoint TOP

TOP
:
  MOV r1
, 10 ; blink counter

BLINK
:
    SET r30
, r30, 15 ; set GPIO output 15
    MOV r0
, 0x00a00000 ; delay counter

DELAY
:
    SUB r0
, r0, 1
    QBNE DELAY
, r0, 0 ; loop until r0 == 0 (delay)
    CLR r30
, r30, 15  ; clear GPIO output 15
    MOV r0
, 0x00a00000 ; delay counter

DELAY2
:
    SUB r0
, r0, 1
    QBNE DELAY2
, r0, 0 ; loop until r0 == 0 (delay)
    SUB r1
, r1, 1
    QBNE BLINK
, r1, 0 ; loop until r1 = 0 (blink counter)
    MOV r31
.b0, 32 + 3
    HALT



Zach
(Deleted the old one because I forgot to include the error messages)

Greg

unread,
Nov 18, 2016, 10:12:08 AM11/18/16
to BeagleBoard
How did you compile the assembly code?  The compilation has to be done with the Remoteproc and linker files.
Remoteproc will look for certain code in the firmwares, and if it is not there, nothing will happen.

Zach B

unread,
Nov 18, 2016, 10:39:06 AM11/18/16
to BeagleBoard
ooooh that's my problem. I was only using
pasm -b blink2.asm
which doesn't link against anything. I had missed that because most of the other examples that I had read where using the UIO pru loader, which doesn't require any linking of the remoteproc. I had planned on switching to C in the future but I was using my simple assembly program to start. I guess I will just try modifying the example pru code gpio_toggle to toggle the pin I want as a first attempt. What is the proper way to link those files in during the assembly compilation process?

Sorry if some of these questions are pretty basic I'm learning as I go through all of this.

Greg

unread,
Nov 18, 2016, 12:51:05 PM11/18/16
to BeagleBoard
Go into the PRU support package examples directory.  See if you can get the PRU_Halt to compile.  This is the simplest possible C program for the PRU.
All you have to do is the command make, and this will kick off the process.

You will need to have the PRU_CGT environment variable set and also a very simple addition to the PRU compiler library directory (add a bin directory and link to clpru).
I've got this covered in my PDF file.

After these two changes, the Makefile included with the project should successfully compile and produce a firmware binary.  This will create a gen directory.  In the gen directory, there will be a .o file which you rename to am335x-pru0-fw, and then copy this to /lib/firmware.  You should be able to rmmod pru_rproc, then modprobe pru_rproc, and then look at dmesg and see a successful start of the firmware.

You can look at the Makefile and reverse engineer the options used with the clpru compiler to create a working firmware.
You can run clpru at the command line with all the options, but it is a real mess!
Get out the PRU C Compiler manual to decode what all of the options do.
Then you can make a shell script to run the compiler.  I used a shell script initially, and then made it into a primitive Makefile.
I really could have stuck with the shell script, but I wanted to learn about the make system.

You will be developing your own "tool chain" which I don't think is too different from that used to develop a "bare metal" C program.
You also get to deal with kernel modules and also the Linux operating system.  I think if you work through this, you will have
a good introduction to Linux embedded system design.   Be warned that it can really eat up hours and hours of your time!

Zach B

unread,
Nov 19, 2016, 9:27:38 PM11/19/16
to BeagleBoard
Thank you for all of the help Greg, I was finally able to get one of the examples to compile and execute. I'm still doing a bit of reading with regards to the reference manuals to figure out the proper registers and values for everything. I did have a few left over questions though.

1) Is "config-pin" able to override the HDMI allocation on pin header 8 or is that something that needs to be taken care of in the master device tree that gets loaded? It seems whenever I activate the HDMI/emmc disable portion of the uEnv.txt it disables my ability to start and stop the PRUs with the echo command. The device is just no longer found, but if I can simply override those pin settings and switch them to PRU outputs without having to use anything in the uEnv.txt then that works just as well, even better if I don't have to mess with the device tree again haha.

2) My second question, is there a better way to execute tasks at specific timing intervals that having one PRU count and set bits in shared memory for the other PRU? I guess I am asking if there are internal timer interrupts that I could use to trigger events or ISRs?

3) Has anyone ever put a simplified RTOS on the PRUs or are they not capable of handling that? Seems like you could use a combination of both PRUs to accomplish some pretty cool timing or interrupt driven real time tasks.

Thanks again for all of the help, I couldn't have done it with you guys!

Greg

unread,
Nov 20, 2016, 7:51:36 AM11/20/16
to BeagleBoard
Excellent!  It's challenging to get Remoteproc to work and remember it is still experimental, still evolving.  So remember what works today may not work tomorrow when you update your OS.
But I think that is more or less true with all of Linux!

The only question I can even halfway answer is #1.  The Universal IO has more than one possible overlay.  I think a different overlay might solve this problem.
Looking in /lib/firmware, I see 5 different "univ" overlays.  How to change them?  I don't know.  My boards are booting up with univ-emmc in slot 4.
That overlay has been sufficient for my projects so far, but it might not be enough for the next.
I tried a few experiments, and only got errors.  I'm sure the process is simple, but I can't tell you what it is.

We really need to find more documentation on how to use the Universal IO.  The README on github seems to be a bit behind the current design.

The other questions I have no idea!  Hopefully a PRU expert can comment on those.

I've made some progress on translating the motor controller to BBG non-CCS and latest interrupt scheme.  The code in that project is way more complex than anything I have seen so far.
I wonder if it represents something close to the upper limit of how much code you can jam in a single PRU?  I'll get it to github, hopefully pretty soon.

Zach B

unread,
Nov 20, 2016, 6:31:41 PM11/20/16
to BeagleBoard
Thanks for the information Greg.

Robert & everyone,
I was digging into that link you sent about which universal overlay gets loaded at boot. I have tried modifying my uEnv.txt file to enable different overlays but i cant' seem to get config-pin to work for P9_31 and P9_29. It responds that config-pin isn't set up for those pins but when I run
config-pin overlay cape-univversala

it seems to load just fine but when I call either:
config-pin-q P9_31
config
-pin P9_31 pruout

it says that it is unable to access the "state" of that pin or set the "pinmux". What's the right way to enable config-pin on all of the pins so that I can set the PRU pins I need to "pruout"?

Zach


William Hermans

unread,
Nov 20, 2016, 7:25:06 PM11/20/16
to beagl...@googlegroups.com
On Sun, Nov 20, 2016 at 4:31 PM, Zach B <zbro...@gmail.com> wrote:
Thanks for the information Greg.

Robert & everyone,
I was digging into that link you sent about which universal overlay gets loaded at boot. I have tried modifying my uEnv.txt file to enable different overlays but i cant' seem to get config-pin to work for P9_31 and P9_29. It responds that config-pin isn't set up for those pins but when I run
config-pin overlay cape-univversala

it seems to load just fine but when I call either:
config-pin-q P9_31
config
-pin P9_31 pruout

it says that it is unable to access the "state" of that pin or set the "pinmux". What's the right way to enable config-pin on all of the pins so that I can set the PRU pins I need to "pruout"?

Zach

Most likely this is because the universal IO overlay you're loading does not have those pins muxed. I have run into this myself when working with a custom cape( physical hardware ). So, I have to create a custom overlay based on more than one universal IO overlay. Then once I gleaned how the structure for each pin had to be in the overlay, I modified the overlay further to only define the exact mux for each pin. That is, removing all the extra mux modes I did not need.

So, in short, you're going to have to create your own overlay file based on multiple universal IO overlays, if you want to use config-pin to mux the pins. If you just want to use config-pin to load an overlay, then your overlay does not *have* to be based on a universal IO overlay.

Message has been deleted

Zach B

unread,
Nov 21, 2016, 10:52:43 AM11/21/16
to BeagleBoard
Sorry for the deleted post I forgot a piece of information...

So I'm not exactly sure what modifications I made that fixed my problem because I made a few and somewhere it resolved my issue. I ended up modifying the files listed below. I don't think I had to modify all of them but I figured I would enable the pru_rproc for all variations of device trees that load for future use (whether this is good or bad idk).
Uncomment '#include "am33xx-pruss-rproc.dtsi"' in the following files as desired

/opt/source/dtb-4.4-ti/src/arm/am335x-boneblack-overlay.dts
/opt/source/dtb-4.4-ti/src/arm/am335x-boneblack-audio.dts

/opt/source/dtb-4.4-ti/src/arm/am335x-boneblack-hdmi-overlay.dts
/opt/source/dtb-4.4-ti/src/arm/am335x-boneblack-emmc-overlay.dts

be sure to run "make" followed by "make install" after making the above modifications.

I then modified my uEnv.txt file as follows:
Change
##BeagleBone Black: HDMI (Audio/Video)/eMMC disabled:
#dtb=am335x-boneblack-overlay.dtb
to
##BeagleBone Black: HDMI (Audio/Video)/eMMC disabled:
dtb=am335x-boneblack-overlay.dtb
this should enable the device tree file "cape-universala-00A0.dts" on boot. The "cape-universala-00A0.dts" has all of the pins pinmuxed and configured for all modes, so it should blow everything wide open for use with config-pin. it worked for all of the pins I wanted to configure. The universal capes can be found (at least for me) at
/opt/source/beaglebone-universal-io/

or you can check them out on this github link:
https://github.com/cdsteinkuehler/beaglebone-universal-io

Doing those 2 things seems to have allowed me to configure any pin I want and starts the pru_rproc on boot ensuring all of the required devices are there to start and stop the PRUs. I ended up not having to mess around with any custom device trees. Hopefully that information helps someone else struggling with the same thing I was.

William Hermans

unread,
Nov 21, 2016, 12:03:54 PM11/21/16
to beagl...@googlegroups.com
Of these 3 capes shown, only cape-universala will work unmodified. This is because this pin in the other two cape overlay's is commented out.

#2
Going by the ball info /* P9_31 (ZCZ ball A13) Audio */, this must be an HDMI audio pin too ? So you'll probably want to edit /boot/uEnv.txt to load this board file.

##BeagleBone Black: HDMI (Audio/Video) disabled:
dtb=am335x-boneblack-emmc-overlay.dtb


Initially the line dtb=am335x-boneblack-emmc-overlay.dtb will be commented out. Then once you make sure you have that uncommitted, make sure no other board file is left uncommitted after this line. Otherwise it may load at boot instead.

Once that is done, you should be able to configure the pin via config-pin to mux the pin for mode 5, or 6 depending on whether you want GPI, or GPO through the PRU.


--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/41cefc20-ff0c-49ba-a780-8d25bf4216da%40googlegroups.com.

Zach B

unread,
Nov 27, 2016, 5:36:15 PM11/27/16
to BeagleBoard
Has anyone compiled a straight assembly file for the PRU? I know you can program in C but I can't accurately predict how long each C command takes to run and I have a time critical portion of my code.

I have been attempting to use the clpru compiler but I keep getting linking errors as it is looking for a main function call and not finding one, since it's just an assembly file. Is it possible to compile assembly with clpru and link to all of the proper files to ensure it compiles and runs correctly on the PRUs? I know I ran into that issue in the past when tried to use pasm and didn't add any linked files.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.

Zach B

unread,
Nov 27, 2016, 6:14:02 PM11/27/16
to BeagleBoard
I guess a better question would be, what libraries or other files need to be linked to create a file that will load and execute on the PRU? I can compile my code but the linking is a bit of a black box to me. I have been reading a lot of PRU reference documentation and haven't come across the answer yet. I'm still working my way through "PRU Optimizing C/C++ User Guide".

Greg

unread,
Nov 27, 2016, 10:01:37 PM11/27/16
to BeagleBoard
Here is a primer on linker files:

I haven't done anything with assembly other than reverse engineer what it is doing.
You can put assembly inline with your C code.  That is described in the manual.

There are "intrinsics" which I think are chunks of assembly code which don't quite fit nicely into the C language.  There is a list in the compiler manual.

Also, there is a clpru option which will create a file with the assembly code generated from the C code.
With this you could get an idea of how much more efficiency you can achieve with assembly.
Then there are optimization levels of the C compiler you could experiment with.

You found the assembly compiler asmpru?

Zach B

unread,
Nov 28, 2016, 4:49:46 PM11/28/16
to BeagleBoard
Greg,

Thanks for the info. That linker primer helped a bit with what is exactly going on inside of the linker, at least to the level that I can understand. I'm still working through getting a single assembly file to work but for now I figured out a workaround with an empty c file. What is asmpru? I only know about "clpru" and "pasm".


Is it possible to load firmware into the PRU, start and stop it for testing and then reload new software without having to reboot? Whenever I stop the PRU and go to remove pru_rproc with "rmmod" or "modprobe -r" I get a message that it is still in use. In order to get around that I just restart the system after copying my new firmware file to /lib/firmware, but is there another way around this? As far as I can tell the PRU is not running when I try to unload/remove pru_rproc. Also when exactly is the pru firmware loaded into the PRU, is it when the system boots or when "modprobe pru_rproc" is called and the remoteproc is started?

Greg

unread,
Nov 28, 2016, 8:52:16 PM11/28/16
to BeagleBoard
I believe asmpru is the assembler code compiler which is part of the PRU compilation system which is described in the C/C++ Compiler manual.

pasm is the older assembler which existed prior to the C compiler.
There are differences in the assembly instructions used with pasm versus the more recent asmpru.

I believe clpru actually uses asmpru in the compilation process of C code.

Check out this discussion, especially the link to the pasm to clpru porting guide:

Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Jason Reeder

unread,
Nov 28, 2016, 11:52:36 PM11/28/16
to BeagleBoard
Greg and Zach,


  • PRU_Halt_Assembly.tar.gz
    • Contains a project to drop into /opt/source/pru-software-support-package/examples/am335x/ that is an assembly only project
    • There are only two parts to the main.asm file: an empty resource table at the top (mandatory for RemoteProc loading) and a main function that writes '0xdeadbeef' to address 0x4a310000 and then halts.
    • I created this assembly file by first writing the program in C, compiling it with the '-k' compiler option to keep the generated assembly, and then removing all the unnecessary generated comments
    • Make it on target using the included Makefile (I modified the Makefile to build both .c and .asm files before linking)
      • cd /opt/source/pru-software-support-package/examples/am335x/PRU_Halt_Assembly/
      • export PRU_CGT=/usr/share/ti/cgt-pru
      • ln -s /usr/bin/ /usr/share/ti/cgt-pru/bin
      • make
      • (generated files will be in the 'gen' folder
    • Add a symbolic link from /lib/firmware/am335x-pru1-fw
      • cd /lib/firmware/
      • rm am335x-pru1-fw
      • ln -s /opt/source/pru-software-support-package/examples/am335x/PRU_Halt_Assembly/gen/PRU_Halt_Assembly.out am335x-pru1-fw
    • Reload the firmware in PRU 1
      • echo 4a338000.pru1 > /sys/bus/platform/drivers/pru-rproc/unbind
      • echo 4a338000.pru1 > /sys/bus/platform/drivers/pru-rproc/bind
    • Check that the firmware actually ran by seeing if '0xdeadbeef' has been written to 0x4a310000 (I use devmem2 for this and I am logged in as root)
  • PRU_Halt_Mixed.tar.gz
    • Contains a project to drop into /opt/source/pru-software-support-package/examples/am335x/ that is a C program that calls a function that is defined in an assembly file
    • main.c contains a C program that calls a function that takes an integer as a parameter and returns an integer as a result
    • assembly_loop.asm is an assembly file that contains a single function which can be called by a C program (which is what main.c does)
      • the loop is mostly nonsense but shows how to take a parameter in an assembly function as well as how to return a result
    • Make it on target using the included Makefile (I modified the Makefile to build both .c and .asm files before linking)
      • cd /opt/source/pru-software-support-package/examples/am335x/PRU_Halt_Mixed/
      • export PRU_CGT=/usr/share/ti/cgt-pru
      • ln -s /usr/bin/ /usr/share/ti/cgt-pru/bin
      • make
      • (generated files will be in the 'gen' folder
    • Add a symbolic link from /lib/firmware/am335x-pru1-fw
      • cd /lib/firmware/
      • rm am335x-pru1-fw
      • ln -s /opt/source/pru-software-support-package/examples/am335x/PRU_Halt_Mixed/gen/PRU_Halt_Mixed.out am335x-pru1-fw
    • Reload the firmware in PRU 1
      • echo 4a338000.pru1 > /sys/bus/platform/drivers/pru-rproc/unbind
      • echo 4a338000.pru1 > /sys/bus/platform/drivers/pru-rproc/bind
    • Check that the firmware actually ran by seeing if address 0x4a310000 contains the integer passed to the function in the C file minus 1 (I use devmem2 for this and I am logged in as root)
      • ./devmem2 0x4a310000
      • (output should be the parameter passed to the C function in main.c minus 1)
Let me know if any of this doesn't make sense. These two projects should cover assembly only projects, as well as C programs where you want to write one of the functions in assembly.

Jason Reeder

Greg

unread,
Nov 29, 2016, 7:25:34 AM11/29/16
to BeagleBoard
Hi Jason, this is awesome, much appreciated!  Is it going to become part of the PRU Support Package examples?

I'll run through the process soon and report on the result.
I also have some questions on the interrupt examples for some time in the future.

Meanwhile, I assume you ran the demo on a recent Debian distribution on a Beaglebone.
I was wondering if you see this in the dmesg log.  This is for PRU0, and there is a repeated instance of these messages for PRU1.

It's not a big deal as the firmwares can be started reliably after boot.  I was not seeing this on the Beaglebones a few months ago, as the firmwares would be up and running automatically
after boot.  Just curious what is going on...

[    4.705647] irq: no irq domain found for /ocp/pruss@4a300000/intc@4a320000 !
[    4.742790] irq: no irq domain found for /ocp/pruss@4a300000/intc@4a320000 !
[    4.836176]  remoteproc1: 4a334000.pru0 is available
[    4.836201]  remoteproc1: Note: remoteproc is still under development and considered experimental.
[    4.836210]  remoteproc1: THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.
[    4.836500]  remoteproc1: Direct firmware load for am335x-pru0-fw failed with error -2
[    4.836520]  remoteproc1: failed to load am335x-pru0-fw
[    4.847402] pru-rproc 4a334000.pru0: booting the PRU core manually
[    4.847433]  remoteproc1: powering up 4a334000.pru0
[    4.847543]  remoteproc1: Direct firmware load for am335x-pru0-fw failed with error -2
[    4.847559]  remoteproc1: request_firmware failed: -2
[    4.852787] pru-rproc 4a334000.pru0: rproc_boot failed
[    4.969567]  remoteproc1: releasing 4a334000.pru0
[    4.969746] pru-rproc: probe of 4a334000.pru0 failed with error -2

Jason Reeder

unread,
Nov 29, 2016, 10:16:37 AM11/29/16
to BeagleBoard
Greg,

Yes, I'd like to get assembly only and mixed c and assembly examples in the support package using TI's compiler tools. I'd like to clean it up a bit and make it a little more useful first though. I put those examples together last night for you and Zach and figured I'd get them in your hands first. Let me know if you run into any issues.

I was running on a recent-ish version of the Debian distro on my BBGW. I'm fairly certain that I am seeing the same dmesg output that you are reporting. I don't think it happens with our TI Processor SDK distro so I haven't looked too closely at it yet. If I get a chance tonight after work I'll try to update to the latest Debian and see if I can't root cause the PRU boot loading issues.

Jason Reeder
Message has been deleted

Zach B

unread,
Dec 4, 2016, 4:16:30 PM12/4/16
to BeagleBoard
Thanks Jason, those were two great examples.

Has anyone had any trouble with the scratch pad between PRUs? I'm using it to pass values between the two systems and it doesn't appear to be working at all. I even created a test script that has a PRU load a value into bank 0 and then read it back out into a separate register and it doesn't appear to be working. I get nothing back out of bank0. Is there some control register that you have to set to activate these banks?
Here is the code I am using to test
init:    
    LDI32 R21, 0x55555555
    LDI32 R1, 0x00000000
    LDI32 R2, 0x00000020
    XOUT 10, &R21, 4
    NOP
    XIN 10, &R1, 4
;    MOV R1, R21

    SUB R2, R2, 1
    MOV R30, R1
    NOP

read_loop:
    SUB R2, R2, 1
    LSR R30, R30, 1
    NOP
    QBNE read_loop, R2, 0
    QBA init
    HALT


The MOV command works just fine but the XIN command does nothing. The register remains empty. Any thoughts?


Zach

Laurel Watts - NOAA Affiliate

unread,
Dec 5, 2016, 9:05:36 AM12/5/16
to beagl...@googlegroups.com
Hi Zach,

Are you compiling with the -V3 switch? This should enable the scratch pad correctly. I've had not problems with it this way.

Laurel

On Sun, Dec 4, 2016 at 9:03 PM, Zach B <zbro...@gmail.com> wrote:
Thanks Jason, those were two great examples.

Has anyone had any trouble with the scratch pad between PRUs? I'm using it to pass values between the two systems and it doesn't appear to be working at all. I even created a test script that has a PRU load a value into bank 0 and then read it back out into a separate register and it doesn't appear to be working. I get nothing back out of bank0. Is there some control register that you have to set to activate these banks?
Here is the code I am using to test
init:    
    LDI32 R21, 0x55555555
    LDI32 R1, 0x00000000
    LDI32 R2, 0x00000020
    XOUT 10, &R21, 4
    NOP
    XIN 10, &R1, 1
;    MOV R1, R21

    SUB R2, R2, 1
    MOV R30, R1
    NOP

read_loop:
    SUB R2, R2, 1
    LSR R30, R30, 1
    NOP
    QBNE read_loop, R2, 0
    QBA init
    HALT


The MOV command works just fine but the XIN command does nothing. The register remains empty. Any thoughts?

Zach

On Tuesday, November 29, 2016 at 10:16:37 AM UTC-5, Jason Reeder wrote:

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/77f4936f-70fa-49b5-b45b-8d6c38b3937e%40googlegroups.com.

Zach B

unread,
Dec 5, 2016, 5:21:00 PM12/5/16
to BeagleBoard
Hi Laurel,

Yeah I have the -V3 flags sent. I think I found the issue that I was having. I may have misread the PRU Reference guide as well as the assembly language documentation on elinux. I had thought that the register address passed in the XIN and XOUT was what register in the PRU the system should start reading or writing too. That appears to be true but it also appears to be directly tied to the banks.
For example, when I was telling it to write &R21 data to bank0 it was writing to R21 in bank0 instead of the start of bank0 memory (R1). When I went to read the data back out I was attempting to write the data to &R1 on the PRU but that also means, as far as I understand, that it was reading directly from &R1 in bank0 when the data was actually in &R21 in bank0.

I could be wrong but my few tests with both c and assembly seem to show that's what was occuring.

Zach
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages