Trouble in getting started with PRU

Hi guys,

I am having some problems in getting started with PRU.

So, first of all, I installed one PRU compiler (CSS) (I follow this article: http://processors.wiki.ti.com/index.php/PRU_Training:_Hands-on_Labs

After having the compiled the file, and from what I’ve read throughout the internet, I thought that in order to run a program into the PRU I should simply do:

  • cp mycode.out /lib/firmware/am335x-pru0-fw
  • echo ‘start’ > /sys/class/remoteproc/remoteproc1/state

However, If I try it with a code to blink a led it does nothing (example of the code for blinking a LED above).

volatile register unsigned int __R30;

int main(void) {

__R30 = SET_MASK;

while(1) {
__R30 = __R30 & ~(SET_MASK);
__delay_cycles(100000000); // half-second delay
}

}

I’ve also tried to follow this tutorial: http://www.righto.com/2016/09/how-to-run-c-programs-on-beaglebones.html
and I get an error when I do: ./loader text.bin data.bin, it says an error message of “prudrv failed to open”. But I can’t quit understand what that program does.

Can anyone tell me what am I doing wrong ?

Thanks you very much,
Fred Gomes

Hi Fred!

What version of the linux kernel are you using? It makes a large
difference as the kernel interfaces have changed.
My experience may not apply to your’s but I can share it with you.
I have a beagle board black. The board booted fine and then I installed
the latest at the time “debian 9.4 lxqt”. The board booted fine. The PRU
compilers where already installed. However, I could not access the PRU
from the device tree. From
https://markayoder.github.io/PRUCookbook/

In Mark’s excellent guide, I was able to see the following instructions
in the Makefile.
“”"

Lookup PRU by address

ifeq ($(PRUN),0)
PRU_ADDR=4a334000
endif
ifeq ($(PRUN),1)
PRU_ADDR=4a338000
endif

PRU_DIR=$(wildcard /sys/devices/platform/ocp/4a32600*.pruss-soc-bus/4a300000.pruss/$(PRU_ADDR)./remoteproc/remoteproc)

“”"

I could not see these addresses despite modifications to the uEnv.txt file. I finally discovered that despite booting from the SD card,
the boot process would use information from the built-in flash chip. Once I zeroed out the on-board flash chip, (using the following)
sudo dd if=/dev/zero of=/dev/mmcblk1 count=1 seek=1 bs=128k

I could make changes to the uEnv.txt file and everything started working as one would expect.

Bill Bitner

Hi Fred!

What version of the linux kernel are you using? It makes a large
difference as the kernel interfaces have changed.
My experience may not apply to your's but I can share it with you.
I have a beagle board black. The board booted fine and then I installed
the latest at the time "debian 9.4 lxqt". The board booted fine. The PRU
compilers where *already* installed. However, I could not access the PRU
from the device tree. From
https://markayoder.github.io/PRUCookbook/
In Mark's excellent guide, I was able to see the following instructions
in the Makefile.
"""
# Lookup PRU by address
ifeq ($(PRUN),0)
PRU_ADDR=4a334000
endif
ifeq ($(PRUN),1)
PRU_ADDR=4a338000
endif

PRU_DIR=$(wildcard /sys/devices/platform/ocp/4a32600*.pruss-soc-bus/4a300000.pruss/$(PRU_ADDR).*/remoteproc/remoteproc*)
"""

I could not see these addresses despite modifications to the uEnv.txt file. I finally discovered that despite booting from the SD card,
the boot process would use information from the built-in flash chip. Once I zeroed out the on-board flash chip, (using the following)
sudo dd if=/dev/zero of=/dev/mmcblk1 count=1 seek=1 bs=128k
I could make changes to the uEnv.txt file and everything started working as one would expect.

Typically (unless the bootloader on the microSD also tries to load
from eMMC), you can hold down the BOOT/SD/S2 button when applying
power (release right after applying power) and it will force the
bootloader on the eMMC to be ignored.

Hi Jason,

Thank you very much for your answer.
I think we are running similar versions of the kernel since our PRU configurations seem to be about the same.

So, I installed the Debian 9.5 2018-10-07 4GB SD IoT image and I am using the 4.14 kernel version.

I took a look at the article from you have sent me and it seems to work. In the section “02start” I could set the USR3 led blinking, although in the section “06io” I couldn’t
set the P9.11 LED blinking, I follow his instructions and it didn’t work, do you have any inkling what might I do wrong?

From what I have seen, he separates the registers by addresses, as described above:

#define GPIO0 0x44e07000 // GPIO Bank 0
#define GPIO1 0x4804c000 // GPIO Bank 1
#define GPIO2 0x481ac000 // GPIO Bank 2
#define GPIO3 0x481ae000 //GPIO Bank 3

He says to check the Table 2.2 of TRM, do you know where it is? I think the failure might be in the address for accessing the GPIO0, which might be different on my kernel version.

Additionally, can you tell me what you’ve done with PRU? … What I do want to achieve is to build an SPI slave interface (for reading data from image sensors).

Thank you very much for your help,
Fred Gomes

Jason Kridner <jkridner@beagleboard.org> escreveu no dia quinta, 15/11/2018 à(s) 18:57:

Fred:
It’s odd that you have the code from chapter 2 working, but not the code in chapter 6. How is the LED wired to P9_11?
Did you config-pin P9_11 for gpio and not pruout? Is P9_11 configgid for output?

The Technical Reference Manual has a link in the References section at the beginning of chapter 6. (https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf)

Can you show the commands you used to run the example?

–Mark

Oh, sorry, my bad. It was related with the pin’s configurations.
Can you tell me what’s the difference between using the OCP interface or usual PRU interface? Both allow to controlling the pins at the same speed rate?

Thanks,
Fred Gomes

Mark A. Yoder <mark.a.yoder@gmail.com> escreveu no dia segunda, 19/11/2018 à(s) 17:12:

Fred:
Using the PRU interface is faster. I think my students measured it as being a couple times faster. Using the PRU interface you can toggle a pin every 5ns.

–Mark

Ok, thank you very much for your help Mark.

– Fred Gomes

Mark A. Yoder <mark.a.yoder@gmail.com> escreveu no dia terça, 20/11/2018 à(s) 22:15:

Yes, R30/R31 is about 3 times as fast and more predictable. Going through the OCP interface

has to wait sometimes if there is already CPU or DMA activity.

regards,

Gerhard

PRU writes to the direct I/O are 8 times faster than writing to a GPIO
pin via the OCP (40 ns for the GPIO vs. 5 ns for direct I/O). Note
that while the write competes on the PRU side within 40 ns, it takes
about another 100 nS until the actual GPIO pin value is updated (this
is the time needed for the write transaction to flow through the
interconnect fabric and actually update the GPIO register).

Reads, however are much worse, since they are not posted by the
interconnect fabric and stall the PRU until the read value is
returned. Reading from a GPIO pin via the OCP port takes apx. 165 ns
vs. 5 ns for a direct I/O read.

I did some tests and measurements of this when I was writing the PRU
code for Machinekit, and documented the details in some comments:

https://github.com/machinekit/machinekit/blob/master/src/hal/drivers/hal_pru_generic/pru_generic.p#L137-L165

Also note that using GPIO0 pins is slower and more unpredictable that the other GPIO’s, particularly with the TI kernel. The power management stuff is in the interconnect as GPIO0 so anything that triggers any sort of PM activity can cause longer delays for any action with GPIO0. In particular, the CPU idle state driver can add an extra 150ns or more delay to writing things to GPIO0. You can limit that by using “cpupower idle-set -d 1” to disable the idle states that take a long time to transition in/out of, but it’s still not perfect.

Dan

Ok, thank you for the feedback Daniel. However, I think I will stick by the PRU interface, to ensure that no data is loss.

– Fred Gomes

Daniel Kulp <dan@kulp.com> escreveu no dia quinta, 22/11/2018 à(s) 23:19: