Difference between revisions of "EBC Exercise 17 Switching a GPIO to an LED"
m |
m (→Finding which device tree to edit: Simplified discovering which device tree.) |
||
Line 53: | Line 53: | ||
=== Finding which device tree to edit === | === Finding which device tree to edit === | ||
We will switch the '''P9_14''' GPIO to an LED by editing the device tree. | We will switch the '''P9_14''' GPIO to an LED by editing the device tree. | ||
− | But which one? | + | But which one? Run the following to see. |
− | |||
− | |||
− | |||
− | + | bone$ '''cat /proc/device-tree/chosen/base_dtb''' | |
− | + | am335x-boneblack-uboot-univ.dts | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Here we see '''am335x-boneblack-uboot-univ.dtb''' is being used. The source for this | Here we see '''am335x-boneblack-uboot-univ.dtb''' is being used. The source for this |
Latest revision as of 10:09, 21 November 2020
Embedded Linux Class by Mark A. Yoder
[1]
Most GPIOs are accessed through /sys/class/gpio
. The builtin LEDs are accessed through /sys/class/leds
.
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 /sys/class/leds
interface.
Contents
Setup
First wire an LED with a 220Ω current limiting resistor to P9_14. Test it using the /sys/class/gpio
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 /sys/class/gpio
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 /sys/class/gpio/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.
The device tree
Finding which device tree to edit
We will switch the P9_14 GPIO to an LED by editing the device tree. But which one? Run the following to see.
bone$ cat /proc/device-tree/chosen/base_dtb am335x-boneblack-uboot-univ.dts
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 /opt/source/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 /opt/source/dtb-4.19-ti/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:
#include "am33xx.dtsi" #include "am335x-bone-common.dtsi" #include "am335x-bone-common-univ.dtsi" #include "bbb-bone-buses.dtsi"
One of these include files must have the leds defined. Look in each one.
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 /sys/class/leds
,
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 <file>..." to update what will be committed) (use "git checkout -- <file>..." 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 /opt/source/dtb-4.19-ti 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 # install Device Tree 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.
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 /sys/class/leds/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.
- ↑ Tested on: bone$ cat /etc/dogtag BeagleBoard.org Debian Buster IoT Image 2020-08-25 bone$ uname -a Linux ece434 4.19.94-ti-r50 #1buster SMP PREEMPT Mon Aug 24 23:03:55 UTC 2020 armv7l GNU/Linux
Embedded Linux Class by Mark A. Yoder