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.
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.
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.