AI64 - PRU Basics (very)

First of all I am not a PRU expert in anyway, I just need to get some code running so I thought I would post some basics about getting something running on one of the PRUs to toggle a gpio on the pin headers. I will follow this up with some more posts about getting pasm and prudebug running on the AI64.

Everything here should be done as root

This file is your friend: /opt/source/dtb-5.10-ti-arm64/src/arm64/k3-j721e-beagleboneai64.dts

Search for #define BONE_PIN(XX,ZZ,QQ)

Under that line are all the definitions for the headers, so we can see for instance:

BONE_PIN(P8_16, default,   P8_16(PIN_INPUT, 7))
BONE_PIN(P8_16, pruout,    P8_16(PIN_OUTPUT, 0))
BONE_PIN(P8_16, pruin,     P8_16(PIN_INPUT, 1))
BONE_PIN(P8_16, gpio,      P8_16(PIN_INPUT, 7))
BONE_PIN(P8_16, gpio_pu,   P8_16(PIN_INPUT_PULLUP, 7))
BONE_PIN(P8_16, gpio_pd,   P8_16(PIN_INPUT_PULLDOWN, 7))

So we can use P8_16 for output from the pru.

In order to do this we need to change cape_header: pinmux_dummy to choose what muxing we want.

So we change




Now make all the dts stuff, install it and reboot:

cd /opt/source/dtb-5.10-ti-arm64/
make install

Now we can output to P8_16, to test this we will modify one of the pru examples that is on the AI64

cd /usr/lib/ti/pru-software-support-package/examples/j721e/PRU_RPMsg_Echo_Interrupt0
cp main.c main_backup.c

This example creates a device /dev/rpmsg_pru30, if we write data to that device the data will be echoed back to it.

We will change it to toggle all the GPIOs whenever it receives a message, this then should then toggle P8_16.

__R30 is used for the GPIOs so we add in:

volatile register uint32_t __R30;

in main() we add:

	volatile uint32_t gpio;

	gpio = 0xFFFFFFFF;

Then whenever we receive a message we flip __R30

while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) {

  //toggle gpios
  __R30 ^= gpio;

  /* Echo the message back to the same address from which we just received */
  pru_rpmsg_send(&transport, dst, src, payload, len);

now build it and copy to the correct place, we are using the first pru PRU0 with is remoteproc0
the firmware name that is set can be found like this:

cat /sys/class/remoteproc/remoteproc0/firmware 


cp gen/icssg0/PRU_RPMsg_Echo_Interrupt0_0.out /lib/firmware/j7-pru0_0-fw

Now the firmware is in the correct place we can set it running:

echo 'start' >  /sys/class/remoteproc/remoteproc0/state

we can use dmesg to check that everything has loaded, you should see:

[  644.802576] remoteproc remoteproc0: powering up
[  644.808380] remoteproc remoteproc0: Booting fw image j7-pru0_0-fw, size 122156
[  644.822303] virtio_rpmsg_bus virtio6: creating channel rpmsg-pru addr 0x1e
[  644.829311] virtio_rpmsg_bus virtio6: rpmsg host is online
[  644.836014]  remoteproc0#vdev0buffer: registered virtio6 (type 7)
[  644.842165] remoteproc remoteproc0: remote processor is now up
[  644.852919] rpmsg_pru virtio6.rpmsg-pru.-1.30: new rpmsg_pru device: /dev/rpmsg_pru30

So we now have our echo device /dev/rpmsg_pru30

Each time you write a message to it P8_16 should toggle and you should also be able to see the echoed data:

echo 1 > /dev/rpmsg_pru30 
echo 2 > /dev/rpmsg_pru30 
cat /dev/rpmsg_pru30 

Edit: I have included the main.c file to copy into /usr/lib/ti/pru-software-support-package/examples/j721e/PRU_RPMsg_Echo_Interrupt0

main.c (4.1 KB)


To build PASM:

git clone
cd am335x_pru_package/pru_sw/utils/pasm_source
gcc -Wall -D_UNIX_ pasm.c pasmpp.c pasmexp.c pasmop.c pasmdot.c pasmstruct.c pasmmacro.c path_utils.c -o ../pasm
sudo cp ../pasm /bin

I did a hack using clpru, not pasm, but this example doesn’t go very far:

Let me know if the Makefile in /var/lib/cloud9/BeagleBone/AI-64/pru makes sense or not how to use. This little hack just toggles all the PRU pins. I’ve gone and tested individual pins after that.

Ultimately, I’m working on updating librobotcontrol that should make a better example. We’ll also be doing examples under Visual Studio Code moving forward.

1 Like


Nice thanks for that, the first thing I looked for on the AI64 was the cloud9 stuff and it wasn’t there!


Had a look through looks good, I wish I had have had that a few days ago :slight_smile:

The symbolic links for the c files don’t seem to work when cloning though.

You haven’t by any chance looked at getting anything running on the R5 cores have you?

Using CCS and the J721E_DRA829_TDA4VM target I can’t seem to get anything that will load up in remoteproc.

Probably worth looking at the TI RTOS SDK and see what and how they build the R5 code. We are still unrolling stuff to eliminate the “SDK” process and simply provide a suitable ARM-hosted build environment and example code.

I have spent hours and hours looking at that RTOS SDk, it’s like something the devil made!

I did manage to get the extra R5 cores built in the vision apps and got them loaded up on the AI64 but working out what is going on in that labyrinth of code is beyond me.

Is the custom R5 code working? If so, the steps to compile and load the same would help a lot.

Note: End objective is to include UI library (TouchGFX or LVGL) & SPI LCD driver support in FreeRTOS code of R5 core