Step04 – GPIO

Pin Muxes

The BeagleBone Black (BBB) differs from the standard BeagleBone with respect to accessing the pin muxing registers. The mux registers are altered through Device Tree’s in the BBB, whereas previously you could use file system drivers to alter the IO pin muxing. If you have a standard BeagleBone and not a BBB then you should look at the old article instead.

Device Tree Overlays

If you want to know where Device Tree Overlays come from, you’ll first need to understand how Device Trees fit into the Linux Kernel. Have a look at the Device Tree specification first, read it so that you understand the dts format syntax and some of the layout and meanings of nodes and values, etc. The BBB way of altering pin mux’s requires us to create, compile and activate a device tree overlay. The overlay will only adjust the pins we enter into our device tree overlay. Multiple device tree overlays can be layered on top of each other. In this way, each Cape requires a device tree overlay which configures the pins it requires.

NOTE: If all you’re after doing is changing the direction and/or value of a line that is already configured to be a GPIO line, then you can jump straight to “Getting Some IO” below. This works in exactly the same way as the previous BeagleBone. The BBB implements device tree overlay’s through the cape manager which is part of the system. As with almost everything Linux – there are device files that we can interact with in order to monitor, add and remove device tree overlays within the cape manager. What we’re interested in is the cape manager, which is found at /sys/devices/bone_capemgr.9 Let’s look to see what’s currently loaded:

root@beaglebone:~# cat /sys/devices/bone_capemgr.9/slots
0: 54:PF---
1: 55:PF---
2: 56:PF---
3: 57:PF---
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI

The BBB has some additional hardware that the original Beaglebone didn’t have – namely the HDMI interface and eMMC interfaces. There was however, a Cape that gave DVI-D output, and the HDMI on the BBB has been implemented as a virtual cape using a Device Tree Overlay to configure the IO necessary to use it. This means that if you want to use the pins associated with the HDMI framer for some other purpose, you can dynamically unload the HDMI cape Device Tree Overlay and you can have access to those pins. If you wish to disable the HDMI overlay, you can negate it’s slot number from the cape manager:

echo -5 > /sys/devices/bone_capemgr.9/slots

For examples of device tree overlays, you can look in the /lib/firmware directory

root@beaglebone:/lib/firmware# ls *.dts

In order to understand what the system is currently configured to on a pin-by-pin basis, the following steps are required: To see the current pinmux setting, you can check the pinmux module to see what the pinmux settings are. You’ll need the manual close by to decipher the output!

cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins

If the pinctrl directory is not present on your system, you can mount the debug fs using the following command:

mount -t debugfs none /sys/kernel/debug/

After the cat command you’ll get an output similar to:

registered pins: 142
pin 0 (44e10800) 00000031 pinctrl-single
pin 1 (44e10804) 00000031 pinctrl-single
pin 2 (44e10808) 00000031 pinctrl-single
pin 3 (44e1080c) 00000031 pinctrl-single

The Beaglebone Black makes it harder to figure out what kernel pin number relates to which processor pad; one that’s not easy to work through. One of the easiest ways is to use grep again. But first, we need to consult the Sitara Cortex A8 Technical Reference Manual. Section 9.3.50 details the pin control registers (pinctrl/pinmux) registers. This is what we’re trying to control. Table 9-10 (On page 886) details the CONTROL_MODULE registers. The control module is located at 44e10000. Look at the registers that start at address 44e10800 which is the start of the pin configuration registers. Below is a table detailing the GPIO number to the relevant pin configuration register offset against the GPIO number:

P8 Pin Register Description GPIO Designation Register Offset
3 gpmc_ad6 gpio1[6] 818
4 gpmc_ad7 gpio1[7] 81C
5 gpmc_ad2 gpio1[2] 808
6 gpmc_ad3 gpio1[3] 80C
7 gpmc_advn_ale gpio2[2] 890
8 gpmc_oen_ren gpio2[3] 894
9 gpmc_be0n_cle gpio2[5] 89C
10 gpmc_wen gpio2[4] 898
11 gpmc_ad13 gpio1[13] 834
12 gpmc_ad12 gpio1[12] 830
13 gpmc_ad9 gpio0[23] 824
14 gpmc_ad10 gpio0[26] 828
15 gpmc_ad15 gpio1[15] 83C
16 gpmc_ad14 gpio1[14] 838
17 gpmc_ad11 gpio0[27] 82C
18 gpmc_clk_mux0 gpio2[1] 88C
19 gpmc_ad8 gpio0[22] 820
20 gpmc_csn2 gpio1[31] 884
21 gpmc_csn1 gpio1[30] 880
22 gpmc_ad5 gpio1[5] 814
23 gpmc_ad4 gpio1[4] 810
24 gpmc_ad1 gpio1[1] 804
25 gpmc_ad0 gpio1[0] 800
26 gpmc_csn0 gpio1[29] 87C
27 lcd_vsync gpio2[22] 8E0
28 lcd_pclk gpio2[24] 8E8
29 lcd_hsync gpio2[23] 8E4
30 lcd_ac_bias_en gpio2[25] 8EC
31 lcd_data14 gpio0[10] 8D8
32 lcd_data15 gpio0[11] 8DC
33 lcd_data13 gpio0[9] 8D4
34 lcd_data11 gpio2[17] 8CC
35 lcd_data12 gpio0[8] 8D0
36 lcd_data10 gpio2[16] 8C8
37 lcd_data8 gpio2[14] 8C0
38 lcd_data9 gpio2[15] 8C4
39 lcd_data6 gpio2[12] 8B8
40 lcd_data7 gpio2[13] 8BC
41 lcd_data4 gpio2[10] 8B0
42 lcd_data5 gpio2[11] 8B4
43 lcd_data2 gpio2[8] 8A8
44 lcd_data3 gpio2[9] 8AC
45 lcd_data0 gpio2[6] 8A0
46 lcd_data1 gpio2[7] 8A4
P9 Pin Register Description GPIO Designation Register Offset
11 gpmc_wait0 gpio0[30] 870
12 gpmc_be1n gpio1[28]
13 gpmc_wpn gpio0[31] 874
14 gpmc_a2 gpio1[18] 848
15 gpmc_a0 gpio1[16] 840
16 gpmc_a3 gpio1[19] 84C
17 spi0_cs0 gpio0[5] 95C
18 spi0_d1 gpio0[4] 958
19 uart1_rtsn gpio0[13] 97C
20 uart1_ctsn gpio0[12] 978
21 spi0_d0 gpio0[3] 954
22 spi0_sclk gpio0[2] 950
23 gpmc_a1 gpio1[17] 844
24 uart1_txd gpio0[15] 984
25 mcasp0_ahclkx gpio3[21] 9AC
26 uart1_rxd gpio0[14] 980
27 mcasp0_fsr gpio3[19] 9A4
28 mcasp0_ahclkr gpio3[17] 99C
29 mcasp0_fsx gpio3[15] 994
30 mcasp0_axr0 gpio3[16] 998
31 mcasp0_aclkx gpio3[14] 990

Using the above table, or else, the BBB SRM (Table 11. Expansion Header P8 and P9 Pinout) we can now get the kernel pin number from the configuration register offset.

There’s also a handy Cheat Sheet here!

We can look at the state of this pin individually by searching for it’s configuration register offset:

cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep "884"

Which gives:

pin 33 (44e10884) 00000032 pinctrl-single

44e10884 is the address of the config register for GPIO1_31, which tells us that kernel pin 33 is GPIO1_31. The configuration for GPIO1_31 is 0x32. To know what this setting means, we can look to the Technical Reference Manual again.

Section 9.3.50 describes what this value means. Table 9-60 shows us each bit:

Bit 1 0
5 Receive Enable Receive Disable
4 Pullup Pulldown
3 Pullup/down Disabled Pullup/down Enabled
2, 1, 0 Mode

Before we start using this pin as an GPIO, we can make sure that nothing else is using the pin:

cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pinmux-
pins | grep "pin 7 "

An output similar to:

pin 33 (44e10884): (MUX UNCLAIMED) (GPIO UNCLAIMED)

Actually, my Beaglebone Black has the HDMI and eMMC modules disabled at startup so this is why this pin is available for me.

We need to re-purpose this pin. It’s current use is set to Mode 2. We require it to be in Mode 7 in order to mux the GPIO to the pin. To achieve this, we need to write a Device Tree Overlay, compile and install it.

First, we need to write a Device Tree Overlay:


/ {
    compatible = "ti,beaglebone", "ti,beaglebone-black";

    part-number = "VALVERS-IO";

    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            valversled: pinmux_valversled {
                pinctrl-single,pins = <
                            0x084 0x7  // GPIO1_31 Mode7, GPIO

    fragment@1 {
        target = <&ocp>;
        __overlay__ {
            valversled_helper {
                compatible = "bone-pinmux-helper";
                pinctrl-names = "default";
                pinctrl-0 = <&valversled>;
                status = "okay";

I’m not going to teach the syntax of Device Tree Overlays here, it’s a subject that can wait for another day.

This Device Tree Overlay can be compiled on the Beaglebone Black itself, using the command:

dtc -O dtb -o VALVERS-IO-00A0.dtbo -b O -@ VALVERS-IO-00A0.dts

It is very important that you keep the filename accurate. The part-number should be reflected in the filename. Copy the compiled file (*.dtbo) to the /lib/firmware directory.

If dtc complains about not recognising the -@ option, follow Robert Nelson’s device tree compiler update process.

Install the device tree overlay using the cape manager driver like so:

echo VALVERS-IO > /sys/devices/bone_capemgr.*/slots

Make sure the device tree overlay has been loaded:

root@arm:/home/debian# cat /sys/devices/bone_capemgr.9/slots
 0: 54:PF---
 1: 55:PF---
 2: 56:PF---
 3: 57:PF---
 4: ff:P-O-- Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN
 7: ff:P-O-L Override Board Name,00A0,Override Manuf,VALVERS-IO

As you can see I have the HDMI and eMMC modules disabled on my Beaglebone Black – this is visible by the missing L on those slot lines because they’re not currently loaded. However, the valvers-io overlay is now loaded. Let’s see what the state of our pin is now:

root@arm:/home/debian# cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep "884"
pin 33 (44e10884) 00000007 pinctrl-single

Excellent, we’ve successfully got GPIO1_31 (pin 33) to mode 7, which means the pinmux is set to GPIO. Now, go Get some IO!

Get some IO

Now, let’s get controlling IO lines! Firstly, using the system filesystem driver from the command line, we can control a pin. I will carry on using GPIO1_0 which we just setup to be mode 7 (GPIO). You’ll need an oscilloscope or multimeter on this pin in order to see the difference in the output.

root@beaglebone:/sys/class/gpio# ls
export gpiochip0 gpiochip32 gpiochip64 gpiochip96 unexport

We need to navigate to the system GPIO class. Here we get a list of files for the GPIO driver. A pin cannot be controlled until it has been exported. If your application requires control of a pin, it should export it in order to get access to the pin. If export is unsuccessful some other resource is already using that pin. In order to export a pin on BeagleBone we write the pin number to the GPIO export file. The pin number comes from its GPIO designation, not the IC pin number. Each IO port has 32-bits, and the ports are concatenated, so the first number of a GPIO designation (the port number) is multiplied by 32, and then the bit number of the port is added to get the GPIO pin number. For example, to export GPIO1_31 we write (1*32) +  31 = 63 to the export file:

root@beaglebone:/sys/class/gpio# echo 63 > export
root@beaglebone:/sys/class/gpio# ls
export gpio63 gpiochip0 gpiochip32 gpiochip64 gpiochip96 unexport

Once we’ve exported the pin, we’re ready to configure it and use it. As you can see above, when we look at the filesystem after the pin has been exported, we see there is a new file (directory!) for GPIO1_31 (63). So go ahead and have a look inside the the pins directory to find yet more files relating the GPIO1_31 pin:

root@beaglebone:/sys/class/gpio# cd gpio63/
root@beaglebone:/sys/class/gpio/gpio63# ls
active_low direction edge power subsystem uevent value

The direction and value files are the most important for us during standard GPIO use where we just want to set a direction and value (Obviously!) The direction and value files are extremely easy to use. We can set direction to either in, or out, and we can set the value file to either 0 (for logic low) or 1 (for logic high). For example, to set the GPIO to an output with logic high:

root@beaglebone:/sys/class/gpio/gpio63# echo out > direction
root@beaglebone:/sys/class/gpio/gpio63# echo 1 > value

The code for doing this will come soon. We’ll just develop a quick file which will write to these files to control IO lines from C. There is some more to learn for special functions (modes other than 0x07) for GPIO lines when we want to control peripherals like I2C and UART. Code Example in C Here is an example you can compile for the BeagleBone Black. If you’re not sure how to compile for the BeagleBone Black, you can see the Cross-Compiling page.

4 thoughts on “Step04 – GPIO

    1. wilhem

      Pay attention because you should calculate the offset, in this case the difference:
      44e10884 – 44e10800 = 0x084

      what you did is:
      44e10884 – 44e10000 = 0x884
      which is not right

Leave a Reply