So I want to control some GPIO pins using the Gpio class.

I've written the following device tree overlay (
/opt/bb.org-overlays/src/arm/BB-WARD-00A0.dts) to make the pins accessible as GPIO outputs

/* 2022, Ward Slager */
/dts-v1/;
/plugin/;

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

        // Free pins used by the pinmux helpers
        fragment@0 {
                target = <&ocp>;
                __overlay {
                        P8_38_pinmux { status = "disabled"; };  // gate 3
                        P8_39_pinmux { status = "disabled"; };  // gate 4
                        P8_40_pinmux { status = "disabled"; };  // gate 5
                        P9_20_pinmux { status = "disabled"; };  // OLED SPI CS
                        P9_23_pinmux { status = "disabled"; };  // OLED SPI DC
                        P9_17_pinmux { status = "disabled"; };  // ADC SPI CS A
                        P9_15_pinmux { status = "disabled"; };  // ADC SPI CS B
                };
        };

        // Free pins used by i2c2 (BELA)
        fragment@1 {
                target = <&i2c2>;
                __overlay {
                        status = "disabled";
                };
        };

        // Configure pins so that they can be used by the Gpio library
        fragment@2 {
                target = <&am33xx_pinmux>;
                __overlay {
                        bb_ward_gpio_pins: pinmux_bb_ward_gpio_pins {
                                pinctrl-single,pins = <
                                        0x8C4 0x17      /* P8.38, all set to GPIO output pullup */
                                        0x8B8 0x17      /* P8.39 */
                                        0x8BC 0x17      /* P8.40 */
                                        0x978 0x17      /* P9.20 */
                                        0x844 0x17      /* P9.23 */
                                        0x95C 0x17      /* P9.17 */
                                        0x840 0x17      /* P9.15 */
                                >;
                        };
                };
        };

        fragment@3 {
                target-path = "/";
                __overlay {
                        ward_gpio_pins {
                                compatible = "gpio-leds";
                                pinctrl-names = "default";
                                pinctrl-0 = <&bb_ward_gpio_pins>;
                        };
                };
        };
};

I compiled the file and ran the install.sh script in bb.org-overlays so the dtbo is placed in /lib/firmware/

Then I added the file to uEnv.txt which looks like this:

uenvcmd=echo loading ${fdtfile}; load mmc ${mmcid}:2 ${fdtaddr} boot/dtbs/${uname_r}/${fdtfile}; if env exists uboot_overlay_addr0; then setenv overlay ${uboot_overlay_addr0}; run bela_loadoverlay; fi; if env exists uboot_overlay_addr1; then setenv overlay ${uboot_overlay_addr1}; run bela_loadoverlay; fi; if env exists uboot_overlay_addr2; then setenv overlay ${uboot_overlay_addr2}; run bela_loadoverlay; fi; if env exists uboot_overlay_addr3; then setenv overlay ${uboot_overlay_addr3}; run bela_loadoverlay; fi; if env exists uboot_overlay_addr4; then setenv overlay ${uboot_overlay_addr4}; run bela_loadoverlay; fi; if env exists uboot_overlay_addr5; then setenv overlay ${uboot_overlay_addr5}; run bela_loadoverlay; fi; if env exists uboot_overlay_addr6; then setenv overlay ${uboot_overlay_addr6}; run bela_loadoverlay; fi; if env exists uboot_overlay_addr7; then setenv overlay ${uboot_overlay_addr7}; run bela_loadoverlay; fi; load mmc ${mmcid}:2 ${loadaddr} /boot/vmlinuz-${uname_r}; setenv bootargs console=${console} root=/dev/mmcblk${mmcid}p2 ro rootfstype=ext4 rootwait coherent_pool=1M net.ifnames=0 quiet; bootz ${loadaddr} - ${fdtaddr};
bela_loadoverlay=echo loading ${overlay}; load mmc ${mmcid}:2 ${rdaddr} ${overlay}; fdt addr $fdtaddr; fdt resize 0x60000; fdt apply ${rdaddr}; fdt resize 0x60000;

uboot_overlay_addr2=/lib/firmware/BB-BELA-00A1.dtbo
uboot_overlay_addr3=/lib/firmware/BB-BELA-CTAG-SPI-00A0.dtbo
uboot_overlay_addr4=/lib/firmware/BB-SPIDEV0-00A0.dtbo
uboot_overlay=addr5=/lib/firmware/BB-WARD-00A0.dtbo

console=ttyS0,115200n8
uname_r=4.14.108-ti-xenomai-r143
mmcid=1

Inside render.cpp:

void setup()
{
	// (...)

	gateOUT[0].open(pinGpioGate3, Gpio::OUTPUT);
	gateOUT[1].open(pinGpioGate4, Gpio::OUTPUT);
	gateOUT[2].open(pinGpioGate5, Gpio::OUTPUT);

	// (...)
}

void render(BelaContext *context, void *userData)
{
	if ((gFrame % 256) > 128)
	{
		gateOUT[0].set();
		gateOUT[1].set();
		gateOUT[2].set();
	}
	else
	{
		gateOUT[0].clear();
		gateOUT[1].clear();
		gateOUT[2].clear();
	}
	
	gFrame++;
}

The compilation of the .dts file gave no errors, and the Beaglebone works. When hit run the .open() function even returns 0 but still calling .write() does not change the GPIO voltage..

Check dmesg immediately after boot to check whether the overlay loaded properly

dmesg doesn't print anything indicating that loading the overlay failed. It also doesnt print anything indicating that the overlay did load, should it?

So I found this edited my overlay to be this:

/* 2022, Ward Slager */
/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/am33xx.h>

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

        // Free pins used by the pinmux helpers
        fragment@0 {
                target = <&ocp>;
                __overlay__ {
                        cape-universal { status = "disabled"; };

                        P8_38_pinmux { status = "disabled"; };  // gate 3
                        P8_39_pinmux { status = "disabled"; };  // gate 4
                        P8_40_pinmux { status = "disabled"; };  // gate 5

                        P9_20_pinmux { status = "disabled"; };  // OLED SPI CS
                        P9_23_pinmux { status = "disabled"; };  // OLED SPI DC
                        P9_17_pinmux { status = "disabled"; };  // ADC SPI CS A
                        P9_15_pinmux { status = "disabled"; };  // ADC SPI CS B
                };
        };

        // Free pins used by i2c2 (BELA)
        fragment@1 {
                target = <&i2c2>;
                __overlay__ {
                        status = "disabled";
                };
        };

        // Configure pinmux
        fragment@2 {
                target = <&am33xx_pinmux>;
                __overlay__ {
                        bb_ward_gpios: pinmux_bb_ward_gpios {
                                pinctrl-single,pins = <
                                        0x8C4 0x17      /* P8.38, all set to GPIO output pullup */
                                        0x8B8 0x17      /* P8.39 */
                                        0x8BC 0x17      /* P8.40 */
                                        0x978 0x17      /* P9.20 */
                                        0x844 0x17      /* P9.23 */
                                        0x95C 0x17      /* P9.17 */
                                        0x840 0x17      /* P9.15 */
                                >;
                        };
                };
        };

        fragment@3 {
                target = <&ocp>;
                __overlay__ {
                        leds {
                                compatible = "gpio-leds";

                                P8_38 {
                                        gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
                                        default-state = "off";
                                };

                                P8_39 {
                                        gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
                                        default-state = "off";
                                };

                                P8_40 {
                                        gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>;
                                        default-state = "off";
                                };

                                P9_20 {
                                        gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
                                        default-state = "off";
                                };

                                P9_23 {
                                        gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
                                        default-state = "off";
                                };

                                P9_17 {
                                        gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
                                        default-state = "off";
                                };

                                P9_15 {
                                        gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
                                        default-state = "off";
                                };
                        };
                };
        };
};

Still doesn't work tho..

The pins are not set to 0x17 when I check with grep xxx $PINS, and the GPIO pin does not toggle.

Now I know most of these pins have different functionality normally but as I'm not using a Bela Cape or HDMI they should be usable I thought.

P8_38: lcd / hdmi / uart5
P8_39: lcd / hdmi
P8_40: lcd / hdmi

P9_20: I2C2 Bela cape audio codec
P9_23: -
P9_17: CS SPI0 for Bela cape
P9_15: -

config-pin -q prints the following for each pin (but that is to be expected if I configure pins via a DTO right?)

xx_xx pinmux file not found!
Pin has no cape: xx_xx

    Ward (but that is to be expected if I configure pins via a DTO right?)

    yes. In general, config-pin only works if some cape universal is loaded and that's not the case by default on the BBB. Even if it was, you are disabling the cape universal for those pins in your first fragment.

    I am not an expert of dtb syntax to the point where I'd necessarily understand at a glance what's wrong, but your fragment@2 is only defining some pins settings which do not get applied anywhere:L you need to reference bb_ward_gpios from within a different fragment. Cf https://github.com/BelaPlatform/bb.org-overlays/blob/master/src/arm/BB-BELA-00A1.dts , where groups of pins are defined, each of which is then referenced from a different fragment. The most relevant to your case is bb_digitals and fragment@9 :

    	fragment@9 {
    		target-path="/";
    		__overlay__ {
    			bela_digitals {
    				compatible = "gpio-leds";
    				pinctrl-0 = <&bb_digitals>;
    				pinctrl-1 = <&bb_digitals>;
    				pinctrl-names = "default", "sleep";
    			};
    		};
    	};

    This suggests that if you changed your fragment@3 to look like this, you should be set:

    	fragment@3 {
    		target-path="/";
    		__overlay__ {
    			ward_gpios {
    				compatible = "gpio-leds";
    				pinctrl-0 = <&bb_ward_gpios>;
    				pinctrl-1 = <&bb_ward_gpios>;
    				pinctrl-names = "default", "sleep";
    			};
    		};
    	};
    • Ward replied to this.

      giuliomoro This suggests that if you changed your fragment@3 to look like this, you should be set:

      Okay so this worked after I discovered that I should use the GPIO number. After reading this article I thought I was supposed to use the $PINS number as it explains how to retrieve that number using grep ... $PINS.

      edit: P9_20 doesn't work tho. This is the I2C2 SDA pin used by the Bela cape. it seems I have made a mistake on my PCB.

      It works! Thanks for the help!

      3 years later

      Turns out when setting the GPIO mode with pinctrl-single,pins in a device tree overlay you need to use the OFFSET column instead of ADDR. How I only found this out now and haven't run into issues before I could not tell you...

      This document is also nice to ctrl+f against when checking pin offsets.
      https://github.com/RobertCNelson/bb.org-overlays/blob/master/include/dt-bindings/board/am335x-bbw-bbb-base.h

      Also note that on Pins used by bela there is a incorrect link:

      The BeagleBone provides two expander headers: P8 and P9, while the PocketBeagle has (P1 and P2). Details for the functions of all the pins are available in this somewhat hard-to-parse document.

      Both P8 and P9 link to the pdf of P8.

        Ward Both P8 and P9 link to the pdf of P8.

        fixed, thanks

        Ward Turns out when setting the GPIO mode with pinctrl-single,pins in a device tree overlay you need to use the OFFSET column instead of ADDR. How I only found this out now and haven't run into issues before I could not tell you

        It really depends on how the base address is specified, but yes in most cases you should use OFFSET instead of ADDR there. Any time I have to deal with pinmux addresses in different contexts I decide whether I have to use one or the other by looking at what's already there: if it starts with 8 or 9 I know it's ADDR, if it starts with 0 or 1 I know it's OFFSET.