EBC Exercise 17 Switching a GPIO to an LED

Most GPIOs are accessed through. The builtin LEDs are accessed through. LEDs accessed this way have special powers (the trigger).

This exercise shows how to make an LED attached to on of the GPIO to appear in the interface.

Setup
First wire an LED with a 220Ω current limiting resistor to P9_14. Test it using the interface. Do this by first seeing which GPIO number corresponds to P9_14. bone$ gpioinfo ... gpiochip1 - 32 lines: line  0:   "GPMC_AD0"      "P8_25"   input  active-high [used] line  1:   "GPMC_AD1"      "P8_24"   input  active-high [used] ...  line  17:    "GPMC_A1"      "P9_23"   input  active-high [used] line 18:    "GPMC_A2"      "P9_14"   input  active-high [used] line 19:    "GPMC_A3"      "P9_16"   input  active-high [used] I've left out a bunch of output, but you see the P9_14 is on gpiochip 1 and line 18. You convert this to the GPIO number used in  by multipying the chip number by 32 and adding it to the line number. Here we get 1*32+18=50.

So check out GPIO 50. bone$ cd /sys/class/gpio bone$ ls ... gpio112 gpio13   gpio23  gpio33  gpio4   gpio5   gpio65  gpio71  gpio78  gpio88  unexport gpio113 gpio14   gpio26  gpio34  gpio44  gpio50  gpio66  gpio72  gpio79  gpio89 If you don't see gpio50 do the following: bone$ echo 50 > export Then bone$ cd gpio50 bone$ ls active_low device  direction  edge  label  power  subsystem  uevent  value bone$ cat direction in We see it defaults to an input. Switch it to an output. bone$ echo out > direction Now turn it on. bone$ echo 1 > value The LED should be on. If not, check your wiring.

Finding which device tree to edit
We will switch the P9_14 GPIO to an LED by editing the device tree. But which one? This happens at boot time, so you need to follow the directions at Boot_Sequence to setup the serial port to watch the boot sequence. You'll see something like the following if you are on a BeagleBone Black.

U-Boot SPL 2019.04-00002-gc9b3922522 (Aug 24 2020 - 16:42:18 -0500) Trying to boot from MMC1 Loading Environment from EXT4... ** File not found /boot/uboot.env ** ** Unable to read "/boot/uboot.env" from mmc0:1 ** ... debug: [enable_uboot_overlays=1] ... debug: [enable_uboot_cape_universal=1] ... debug: [uboot_base_dtb_univ=am335x-boneblack-uboot-univ.dtb] ... uboot_overlays: [uboot_base_dtb=am335x-boneblack-uboot-univ.dtb] ... uboot_overlays: Switching too: dtb=am335x-boneblack-uboot-univ.dtb ... loading /boot/dtbs/4.19.94-ti-r50/am335x-boneblack-uboot-univ.dtb ...

Here we see am335x-boneblack-uboot-univ.dtb is being used. The source for this is already on the Bone.

Note: If you want to edit the source using cloud9 use the following trick to make the file visible in your home directory. bone$ cd # Change to your home directory bone$ ln -s / root # create a symbolic link from root in your home directory to / the root of the filesystem.

Now find the file to edit. bone$ cd /opt/source  # There are a bunch of source files here bone$ ls adafruit-beaglebone-io-python dtb-4.14-ti  librobotcontrol  py-uio           u-boot_v2020.10-rc2 BBIOConfig                    dtb-4.19-ti  list.txt         rcpy bb.org-overlays               dtb-5.4-ti   pyctrl           u-boot_v2019.04 The directory we want starts with dtb, but there are three of them. The one you pick depends on which kernel you are running. We are running: bone$ uname -r 4.19.94-ti-r50 We are running the 4.19 kernel, so cd to that directory. bone$ cd dtb-4.19-ti It's a git repo, so be sure it's up to date. bone$ git pull Already up to date.

Compiling the device trees
Good. First lets compile all the device trees. bone$ make DTC    src/arm/am335x-chiliboard.dtb DTC    src/arm/am335x-boneblack-bbb-exp-c.dtb ...  DTC     src/arm/am335x-boneblack-bbbmini.dtb DTC    src/arm/am335x-boneblack-uboot-univ.dtb DTC    src/arm/am335x-baltos-ir3220.dtb ... We see that the one we were looking for compiled.

Finding the source
Now the source is in: bone$ cd src/arm bone$ ls am335x-boneblack-uboot* am335x-boneblack-uboot.dtb am335x-boneblack-uboot-univ.dtb am335x-boneblack-uboot.dts am335x-boneblack-uboot-univ.dts The dts file is the source and the dtb file is the compiled version.

Edit this file with you favorite editor and look for a definition of led.

You won't find any, but you do find: One of these include files must have the leds defined. Look in each one.
 * 1) include "am33xx.dtsi"
 * 2) include "am335x-bone-common.dtsi"
 * 3) include "am335x-bone-common-univ.dtsi"
 * 4) include "bbb-bone-buses.dtsi"

In am335x-bone-common.dtsi you will find:

leds { pinctrl-names = "default"; pinctrl-0 = <&user_leds_s0>; compatible = "gpio-leds"; led2 { label = "beaglebone:green:usr0"; gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; default-state = "off"; }; 		led3 { label = "beaglebone:green:usr1"; gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; linux,default-trigger = "mmc0"; default-state = "off"; }; 		led4 { label = "beaglebone:green:usr2"; gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; linux,default-trigger = "cpu0"; default-state = "off"; }; 		led5 { label = "beaglebone:green:usr3"; gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; linux,default-trigger = "mmc1"; default-state = "off"; }; 	}; This is where the four internal LEDs are defined. Each has a label, the name the appears in , gpios which tells which chip and line the LED appears on, default-trigger which tells how to blink and the default-state.

Adding our LED
All we have to do is copy one of these and edit it to do what we want it to. Here's mine: led6 { label = "red:indicator"; gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; default-state = "off"; }; How did I know to use gpio1 and 18? See https://www.kernel.org/doc/html/latest/leds/leds-class.html for naming conventions.

Recovering from a miss-edit
You are editing a system file here. What if you really mess it up? Not to worry, it's in a git repo. You can see what's been changed with: bone$ git status On branch v4.19.x-ti-overlays Your branch is up to date with 'origin/v4.19.x-ti-overlays'. Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified:  src/arm/am335x-bone-common.dtsi no changes added to commit (use "git add" and/or "git commit -a") Good, we've only changed one file. Here's what's been changed: bone$ git diff src/arm/am335x-bone-common.dtsi diff --git a/src/arm/am335x-bone-common.dtsi b/src/arm/am335x-bone-common.dtsi index 8952fe1..59e277f 100644 --- a/src/arm/am335x-bone-common.dtsi +++ b/src/arm/am335x-bone-common.dtsi @@ -52,6 +52,13 @@                        linux,default-trigger = "mmc1"; default-state = "off"; }; +               +               led6 { +                      label = "red:indicator"; +                      gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; +                      linux,default-trigger = "heartbeat"; +                      default-state = "off"; +              };         };         vmmcsd_fixed: fixedregulator0 { The +'s show what's been added.

If you really mess things up you can always start over with: bone$ git checkout src/arm/am335x-bone-common.dtsi and you will be back where you started.

Compiling again
Back up two levels to run make and...

bone$ cd ../.. bone$ make And nothing happens! make only recompiles the files that have changed. It does this by comparing dates, but it doesn't check the included files. We didn't change am335x-boneblack-uboot-univ.dts, so it didn't compile. Just change the date on am335x-boneblack-uboot-univ.dts and try again. touch sets the date of the file to the current time. bone$ touch src/arm/am335x-boneblack-uboot-univ.dts bone$ make DTC    src/arm/am335x-boneblack-uboot-univ.dtb It recompiled, now install. bone$ sudo make install mkdir -p /boot/dtbs/4.19.94-ti-r50/ cp -v src/arm/*.dtb /boot/dtbs/4.19.94-ti-r50/ 'src/arm/am335x-abbbi.dtb' -> '/boot/dtbs/4.19.94-ti-r50/am335x-abbbi.dtb' ... 'src/arm/am335x-boneblack-roboticscape.dtb' -> '/boot/dtbs/4.19.94-ti-r50/am335x-boneblack-roboticscape.dtb' 'src/arm/am335x-boneblack-uboot-univ.dtb' -> '/boot/dtbs/4.19.94-ti-r50/am335x-boneblack-uboot-univ.dtb' 'src/arm/am335x-boneblack-uboot.dtb' -> '/boot/dtbs/4.19.94-ti-r50/am335x-boneblack-uboot.dtb' ... It's now installed, reboot and see what happens. bone$ sudo reboot Your P9_14 LED should be flashing a heartbeat.
 * 1) install Device Tree

Checking /sys/class/leds
Check and make sure your LED appears with the others. bone$ cd /sys/class/leds bone$ ls beaglebone:green:usr0 beaglebone:green:usr1  beaglebone:green:usr2  beaglebone:green:usr3  red:indicator

Yup, there is the newest LED on the right end. Check it out: bone$ cd red:indicator bone$ ls brightness device  invert  max_brightness  power  subsystem  trigger  uevent bone$ cat trigger  none rfkill-any rfkill-none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock mmc0 mmc1 usb-gadget usb-host timer oneshot disk-activity disk-read disk-write ide-disk mtd nand-disk [heartbeat] backlight gpio cpu cpu0 activity default-on panic netdev

It looks like the other LEDs. Try changing the trigger and see what happens.