.. _gpio-57: GPIO ==== The General-Purpose Input/Output interfaces provides pins that can be configured as either inputs or outputs. Many of the signals available at the phyCORE-Connector can be multiplexed as GPIOs. The phyCORE-AM57x SOM brings out a selection of GPIOs and you can access many of these signals through some pre-made LED/Button circuits and with the help of the PHYTEC Expansion board (PCM-957). This guide walks through the basic steps of toggling and reading the state of these IO interfaces. To learn more information about the phyCORE-AM57x GPIO interface, please see section 40 in the `Hardware Manual `_. .. image:: ../../images/phycore-am57x/AM5_GPIO.webp :width: 650px :alt: User LED and Expansion Connector Locations Using LEDs and Push Buttons ------------------------------- This section of the guide will walk through the use of the pre-made LED circuits populated directly on the carrier board and SOM. These outputs have been pre-configured in the device tree for use. .. list-table:: User LEDs :header-rows: 1 * - LED - Location - Signal * - /sys/class/leds/phycore:red@ - SOM (D1) - GPIO4_9 * - /sys/class/leds/phycore:green@ - SOM (D2) - GPIO4_10 * - /sys/class/leds/pcm-948:led1@ - CB (LED1) - X_GPIO1_28 * - /sys/class/leds/pcm-948:led2@ - CB (LED2) - X_GPIO1_29 Toggling the User LEDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The development kit has two user-configurable LEDs. In the next section “GPIO Signal Naming” you’ll see that these GPIO signals are already allocated to names pcm-948:led1/2. This indicates that a driver has claimed these gpios, and this can be confirmed by checking the linux device tree. The driver is gpio-leds. * Let's take a look at the sysfs interface that the gpio-leds driver are located in. .. code-block:: none :caption: Target (Linux) ls /sys/class/leds/ .. code-block:: none :caption: Expected Output root@phycore-am57xx-1:~# ls /sys/class/leds/ mmc0::@ mmc1::@ pcm-948:led1@ pcm-948:led2@ phycore:green@ phycore:red@ * Let’s first turn ON LED1 (it should be OFF by default): .. code-block:: none :caption: Target (Linux) echo 1 > /sys/class/leds/pcm-948\:led1/brightness .. note:: When the gpio-leds driver is attached to a PWM enabled pin, the brightness file will actually control the physical brightness of the pin and allow you to write values from 0 to 255 to do so. In this case, GPIO1_28 is not PWM capable pin and thus 0 corresponds to the LED being OFF and any other value sets the LED to ON. * Turn OFF the LED .. code-block:: none :caption: Target (Linux) echo 0 > /sys/class/leds/pcm-948\:led1/brightness * We can also leverage the driver to do more interesting things with the LED. Let's configure the GPIO as a Linux heartbeat for example: .. code-block:: none :caption: Target (Linux) echo "heartbeat" > /sys/class/leds/pcm-948\:led1/trigger * The heartbeat trigger can be turned OFF like so: .. code-block:: none :caption: Target (Linux) echo "none" > /sys/class/leds/pcm-948\:led1/trigger The other LED, pcm-948:led2, can be controlled in the same way. Reading the User Buttons (S3/S4) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We can see in both the development kit schematic and in /sys/kernel/debug/gpio that GPIO1_26 is connected to the user button S1 and is represented in software as gpio-26 with the name "home" and the user button S2 and is represented in software as gpio-27 with the name "menu" . We can see in the device tree that these GPIO are assigned to the gpio-keys driver. * We can poll the state of the input GPIO just by reading /sys/kernel/debug/gpio like we already did above: .. code-block:: none :caption: Target (Linux) cat /sys/kernel/debug/gpio | grep home .. code-block:: none :caption: Target (Linux) root@phycore-am57xx-1:~# cat /sys/kernel/debug/gpio | grep home gpio-26 ( |home ) in lo IRQ * Now try running that command again while holding down the S1 button: .. code-block:: none :caption: Expected Output root@phycore-am57xx-1:~# cat /sys/kernel/debug/gpio | grep home gpio-26 ( |home ) in hi IRQ We can see that the pin goes from "lo" to "hi" when the button is pressed. * Another option for viewing button presses is to leverage the gpio-keys driver and the input events that it generates: .. code-block:: none :caption: Target (Linux) cat /dev/input/event0 | hexdump With that above command running as an active process, try pushing the User buttons S1 and S2. You should see a large block of hexadecimal data printed to the screen for each button press. .. note:: These blocks of data are input_event structures that identify the key code assigned to the GPIO (see the linux device tree), when the button press occurred, and the type of button press event that was generated (long press, single press, button release, etc). See Documentation/input/input.rst within the kernel source for more information. * Enter Ctrl + C to end the process and resume control of the console. Advanced Steps to Impress your Mom! --------------------------------------- LED Blink ~~~~~~~~~~~~ * To create a script that automatically blinks the LED, open a text editor: .. code-block:: none :caption: Target (Linux) vi ~/blink.sh * Edit the contents of the new file to reflect the code below and save the file: .. note:: The vi text editor begins in "Command Mode" and you must first hit the 'i' key in order to enter "Insert Mode". Using the arrow keys to navigate, make the necessary changes and then hit ESC to go back to "Command mode". Now enter ":wq" to write the file and quit. **Pro Tip:** Use the right click on your mouse to paste! This will only work if you are in "Insert Mode" first. .. code-block:: none :caption: ~/blink.sh #!/bin/sh echo 0 > /sys/class/leds/phycore:red/brightness echo 0 > /sys/class/leds/phycore:green/brightness for i in `seq 1 10`; do echo 1 > /sys/class/leds/phycore:red/brightness echo 0 > /sys/class/leds/phycore:green/brightness sleep 1 echo 0 > /sys/class/leds/phycore:red/brightness echo 1 > /sys/class/leds/phycore:green/brightness sleep 1 done * Make your file executable: .. code-block:: none :caption: Target (Linux) chmod +x ~/blink.sh * Now run the script: .. code-block:: none :caption: Target (Linux) ~/blink.sh User Button via Expansion Board ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This section of the guide will walk through the use of a user made Push Button populated directly onto the PHYTEC Expansion Board (PCM-957). * With the phyCORE-AM57x powered off and with the power supply removed, hook up a through-hole push button to the pin 23C and to the supply rail at pin 51C. Use the following circuit diagram for reference: .. image:: ../../images/phycore-am57x/pb-057948_gpio-pcm-957.webp :width: 350px :alt: User Button Wiring Diagram .. note:: GPIO4_20 is an undefined signal in the device tree and therefore will default to its reset state, which internally pulls down the pin. Thus, we need to pull the signal high when the button is pressed. * Once wired up, reconnect the power supply and boot into Linux. * Use the following command to export the GPIO signal in sysfs: .. code-block:: none :caption: Target (Linux) echo 180 > /sys/class/gpio/export * Set GPIO4_20 as an input: .. code-block:: none :caption: Target (Linux) echo in > /sys/class/gpio/gpio180/direction * Lets try polling the state of the GPIO4_20 signal: .. code-block:: none :caption: Target (Linux) cat /sys/class/gpio/gpio180/value .. code-block:: none :caption: Expected Output root@phycore-am57xx-1:~# cat /sys/class/gpio/gpio180/value 0 * Now try polling the state of the button again while pressing and holding the push button we just wired up! You should see that the state of the signal went from 0 to a 1. GPIO Signal Naming ---------------------- The GPIO pin numbering of the phyCORE-AM57x schematic is represented differently from the device identifier used by the kernel. Therefore in GPIO hardware signal naming convention looks very different from the software GPIO naming convention. This section will walk through how to calcualte the GPIO signals and shoe how to identify which GPIO signals are in use on the developmeny kit. Hardware to Software ~~~~~~~~~~~~~~~~~~~~~~ * Using the development kit's carrier board and SOM schematics the hardware GPIO signal GPIO1_28 (LED1) at SOM connector A52 pin. * See which GPIO signals have been allocated by running the following command. .. code-block:: none :caption: Target (Linux) cat /sys/kernel/debug/gpio .. code-block:: none :caption: Expected Output root@phycore-am57xx-1:~# cat /sys/kernel/debug/gpio gpiochip0: GPIOs 0-31, parent: platform/4ae10000.gpio, gpio-0-31: gpio-26 ( |home ) in lo IRQ gpio-27 ( |menu ) in lo IRQ gpio-28 ( |pcm-948:led1 ) out lo gpio-29 ( |pcm-948:led2 ) out lo gpiochip1: GPIOs 32-63, parent: platform/48051000.gpio, gpio-32-63: gpio-44 ( |encoder@0 ) in lo IRQ gpio-54 ( |vbus ) in hi IRQ gpiochip2: GPIOs 64-95, parent: platform/48053000.gpio, gpio-64-95: gpio-68 ( |pcie-reset ) out hi ACTIVE LOW gpio-71 ( |pcie-clk-oe ) out hi gpiochip3: GPIOs 96-127, parent: platform/48055000.gpio, gpio-96-127: gpiochip4: GPIOs 128-159, parent: platform/48057000.gpio, gpio-128-159: gpiochip5: GPIOs 160-191, parent: platform/48059000.gpio, gpio-160-191: gpio-168 ( |regulator-vtt ) out hi gpio-169 ( |phycore:red ) out lo gpio-170 ( |phycore:green ) out hi gpiochip6: GPIOs 192-223, parent: platform/4805b000.gpio, gpio-192-223: gpio-199 ( |id ) in lo IRQ gpio-205 ( |wp ) out hi gpiochip7: GPIOs 224-255, parent: platform/4805d000.gpio, gpio-224-255: gpio-251 ( |cd ) in lo IRQ ACTIVE LOW gpio-252 ( |wp ) in lo .. list-table:: GPIO and gpiochip :header-rows: 1 * - GPIO SOC Modules - GPIO Hardware Signal - Section * - gpiochip0 - GPIO1 - 0-31 * - gpiochip1 - GPIO7 - 32-63 * - gpiochip2 - GPIO8 - 64-95 * - gpiochip3 - GPIO2 - 96-127 * - gpiochip4 - GPIO3 - 128-159 * - gpiochip5 - GPIO4 - 160-191 * - gpiochip6 - GPIO5 - 192-223 * - gpiochip7 - GPIO6 - 224-255 * Looking at the section "gpiochip0", since it translates to GPIO1, you can see the first software GPIO signal is gpio-28 for GPIO1. By adding 0 and the hardware signal(GPIO1_28) together the proper software singal name can be found. 0+28 = 28 * Now you know that gpio-28 (software) is GPIO1_28 (hardware). Software to Hardware ~~~~~~~~~~~~~~~~~~~~~~~~ * In order to figure out which hardware GPIO signals are already allocated simply subtract the software GPIO singal from the GPIO bank starting section. * Find the GPIO bank section by running the following command on the development kit. .. code-block:: none :caption: Target (Linux) cat /sys/kernel/debug/gpio * The GPIO4 bank correlates gpiochip5 which starts at gpio-160. To find which hardware GPIO signal phycore:red corresponds to gpio-169, subtract gpio-169 from the start of the GPIO bank (gpio-160). 169-160 = 9 * Now you know that gpio-169 (software) is GPIO4_9 (hardware).