Outline

1. Moving to the BeagleBone AI

So far all our examples have focussed mostly on the BeagleBone Black and Pocket Beagle. These are both based on the am335x chip. The new kid on the block is the BeagleBone AI which is based on the am5729. The new chip brings with it new capabilities one of which is four PRUs. This chapter details what changes when moving from two to four PRUs.

The following are resources used in this chapter.

1.1. Moving from two to four PRUs

Problem

You have code that works on the am335x PRUs and you want to move it to the am5729 on the AI.

Solution

Things to consider when moving to the AI are:

  • Which pins are you going to use

  • Which PRU are you going to run on

Knowing which pins to use impacts the PRU you’ll use.

Discission

The various System Reference Manuals (SRM’s) list which pins go to the PRUs. Here the tables are combined into one to make it easier to see what goes where.

Table 1. Mapping bit positions to pin names
PRU Bit Black pin AI PRU1 pin AI PRU2 pin Pocket pin

0

0

P9_31

P8_44

P1.36

0

1

P9_29

P8_41

P1.33

0

2

P9_30

P8_42/P8_21

P2.32

0

3

P9_28

P8_12

P8_39/P8_20

P2.30

0

4

P9_92

P8_11

P8_40/P8_25

P1.31

0

5

P9_27

P9_15

P8_37/P8_24

P2.34

0

6

P9_91

P8_38/P8_5

P2.28

0

7

P9_25

P8_36/P8_6

P1.29

0

8

P8_34/P8_23

0

9

P8_35/P8_22

0

19

P8_33/P8_3

0

11

P8_31/P8_4

0

12

P8_32

0

13

P8_45

0

14

P8_12(out) P8_16(in)

P9_11

P2.24

0

15

P8_11(out) P8_15(in)

P8_17/P9_13

P2.33

0

16

P9_41(in) P9_26(in)

P8_27

0

17

P9_26

P8_28

0

18

P8_29

0

19

P8_30

0

20

P8_46/P8_8

---

---

---------

-----------

-----------

-----

1

0

P8_45

P8_32

1

1

P8_46

P9_20

1

2

P8_43

P9_19

1

3

P8_44

P9_41

1

4

P8_41

1

5

P8_42

P8_18

P9_25

1

6

P8_39

P8_19

P8_9

1

7

P8_40

P8_13

P9_31

1

8

P8_27

P9_18

P2.35

1

9

P8_29

P8_14

P9_17

P2.01

1

10

P8_28

P9_42

P9_31

P1.35

1

11

P8_30

P9_27

P9_29

P1.04

1

12

P8_21

P9_30

1

13

P8_20

P9_26

1

14

P9_14

P9_42

P1.32

1

15

P9_16

P8_10

P1.30

1

16

P9_26(in)

P8_15

P8_7

1

17

P8_26

P8_27

1

18

P8_16

P8_45

1

19

P8_46

1

19

P8_43

The pins in bold are already configured as pru pins. See Seeing how pins are configured to see what’s currently configured as what. See Configuring pins on the AI via device trees to configure pins.

1.2. Seeing how pins are configured

Problem

You want to know how the pins are currently configured.

Solution

The show-pins.pl command does what you want, but you have to set it up first.

bone$ cd ~/bin
bone$ ln -s /opt/scripts/device/bone/show-pins.pl .

This creates a symbolic link to the show-pins.pl command that is rather hidden away. The link is put in the bin directory which is in the default command $PATH. Now you can run show-pins.pl from anywhere.

bone$ show-pins.pl
P9.19a                    16   R6 7 fast rx  up  i2c4_scl
P9.20a                    17   T9 7 fast rx  up  i2c4_sda
P8.35b                    57  AD9 e fast    down gpio3_0
P8.33b                    58  AF9 e fast    down gpio3_1
...

Here you see P9.19a and P9.20a are configured for i2c with pull up resistors. The P8 pins are configured as gpio with pull down resistors. They are both on gpio port 3. P8.35b is bit 0 while P8.33b is bit 1. You can find which direction they are set by using gpioinfo and the chip number. Unfortunately you subtract one from the port number to get the chip number. So P8.35b is on chip number 2.

bone$ gpioinfo 2
    line   0:      unnamed       unused   input  active-high
    line   1:      unnamed       unused   input  active-high
    line   2:      unnamed       unused   input  active-high
    line   3:      unnamed       unused   input  active-high
    line   4:      unnamed       unused   input  active-high
...

Here we see both (lines 0 and 1) are set to input.

Adding -v gives more details.

bone$ show-pins.pl -v
...
sysboot 14                14   H2 f fast    down sysboot14
sysboot 15                15   H3 f fast    down sysboot15
P9.19a                    16   R6 7 fast rx  up  i2c4_scl
P9.20a                    17   T9 7 fast rx  up  i2c4_sda
                          18   T6 f fast    down Driver off
                          19   T7 f fast    down Driver off
bluetooth in              20   P6 8 fast rx      uart6_rxd        mmc@480d1000 (wifibt_extra_pins_default)
bluetooth out             21   R9 8 fast rx      uart6_txd        mmc@480d1000 (wifibt_extra_pins_default)
...

The best way to use show-pins.pl is with grep. To see all the pru pins try:

bone$ show-pins.pl  | grep -i pru | sort
P8.13                    100   D3 c fast rx      pr1_pru1_gpi7
P8.15b                   109   A3 d fast    down pr1_pru1_gpo16
P8.16                    111   B4 d fast    down pr1_pru1_gpo18
P8.18                     98   F5 c fast rx      pr1_pru1_gpi5
P8.19                     99   E6 c fast rx      pr1_pru1_gpi6
P8.26                    110   B3 d fast    down pr1_pru1_gpo17
P9.16                    108   C5 d fast    down pr1_pru1_gpo15
P9.19b                    95   F4 c fast rx  up  pr1_pru1_gpi2
P9.20b                    94   D2 c fast rx  up  pr1_pru1_gpi1

Here we have nine pins configured for the PRU registers R30 and R31. Five are input pins and four are out.

1.3. Configuring pins on the AI via device trees

Problem

I want to configure another pin for the PRU, but I get an error.

bone$ config-pin P9_31 pruout
ERROR: open() for /sys/devices/platform/ocp/ocp:P9_31_pinmux/state failed, No such file or directory

Solution

The pins on the AI must be configure at boot time and therefor cannot be configured with config-pin. Instead you must edit the device tree.

Discission

Suppose you want to make P9_31 a PRU output pin. First go to the am5729 System Reference Manual and look up P9_31.

Tip

The BeagleBone AI PRU pins table may be easier to use.

P9_31 appears twice, as P9_31a and P9_31b. Either should work, let’s pick P9_31a.

Warning

When you have two internal pins attached to the same header (either P8 or P9) make sure only one is configured as an output. If both are outputs, you could damage the AI.

We see that when P9_31a is set to MODE13 it will be a PRU out pin. MODE12 makes it a PRU in pin. It appears at bit 10 on PRU2_1.

Next, find which kernel you are running.

bone$ uname -a
Linux ai 4.14.108-ti-r131 #1buster SMP PREEMPT Tue Mar 24 19:18:36 UTC 2020 armv7l GNU/Linux

I’m running the 4.14 version. Now look in /opt/source for your kernel.

bone$ cd /opt/source/
bone$ ls
adafruit-beaglebone-io-python  dtb-5.4-ti       rcpy
BBIOConfig                     librobotcontrol  u-boot_v2019.04
bb.org-overlays                list.txt         u-boot_v2019.07-rc4
dtb-4.14-ti                    pyctrl
dtb-4.19-ti                    py-uio

am5729-beagleboneai.dts is the file we need to edit. Search for P9_31. You’l see:

DRA7XX_CORE_IOPAD(0x36DC, MUX_MODE14) // B13: P9.30: mcasp1_axr10.off //
DRA7XX_CORE_IOPAD(0x36D4, MUX_MODE13) // B12: P9.31a: mcasp1_axr8.off //
DRA7XX_CORE_IOPAD(0x36A4, MUX_MODE14) // C14: P9.31b: mcasp1_aclkx.off //

Change the MUX_MODE14 to MUX_MODE13 for output, or MUX_MODE12 for input.

Compile and install. The first time will take a while since it recompiles all the dts files.

bone$ make
...
DTC     src/arm/am335x-sl50.dtb
DTC     src/arm/am5729-beagleboneai.dtb
DTC     src/arm/am335x-nano.dtb
...
bone$ sudo make install
...
'src/arm/am5729-beagleboneai.dtb' -> '/boot/dtbs/4.14.108-ti-r131/am5729-beagleboneai.dtb'
...
bone$ reboot
...
bone$ show-pins.pl -v | sort | grep -i pru
P8.13                    100   D3 c fast rx      pr1_pru1_gpi7
P8.15b                   109   A3 d fast    down pr1_pru1_gpo16
P8.16                    111   B4 d fast    down pr1_pru1_gpo18
P8.18                     98   F5 c fast rx      pr1_pru1_gpi5
P8.19                     99   E6 c fast rx      pr1_pru1_gpi6
P8.26                    110   B3 d fast    down pr1_pru1_gpo17
P9.16                    108   C5 d fast    down pr1_pru1_gpo15
P9.19b                    95   F4 c fast rx  up  pr1_pru1_gpi2
P9.20b                    94   D2 c fast rx  up  pr1_pru1_gpi1
P9.31a                   181  B12 d fast    down pr2_pru1_gpo10

There it is. P9_31 is now a PRU output pin on PRU1_0, bit 3.

1.4. Using the PRU pins

Problem

Once I have the PRU pins configured on the AI how do I use them?

Solution

In Configuring pins on the AI via device trees we configured P9_31a to be a PRU pin. show-pins.pl showed that it appears at pr2_pru1_gpo10, which means pru2_1 accesses it using bit 10 of register R30.

Discission

It’s easy to modify the pwm example from [blocks_pwm] to use this pin. First copy the example you want to modify to pwm1.pru2_1.c. The pru2_1 in the file name tells the Makefile to run the code on pru2_1. pwm1.pru2_1.c shows the adapted code.

pwm1.pru2_1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdint.h>
#include <pru_cfg.h>
#include "resource_table_empty.h"
#include "prugpio.h"

#define P9_31 (0x1<<10)

volatile register uint32_t __R30;
volatile register uint32_t __R31;

void main(void)
{
    uint32_t gpio = P9_31;  // Select which pin to toggle.;

    /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
    CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;

    while(1) {
        __R30 |= gpio;      // Set the GPIO pin to 1
        __delay_cycles(100000000);
        __R30 &= ~gpio;     // Clear the GPIO pin
        __delay_cycles(100000000);
    }
}

One line 6 P9_31 is defined as (0x1<<10), which means shift 1 over by 10 bits. That’s the only change needed. Copy the local Makefile to the same directory and compile and run.

bone$ make TARGET=pwm1.pru2_1

Attach an LED to P9_31 and it should be blinking.