Changes between Initial Version and Version 1 of gpio


Ignore:
Timestamp:
10/22/2017 05:28:45 AM (5 years ago)
Author:
trac
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • gpio

    v1 v1  
     1[[PageOutline]]
     2
     3= General Purpose I/O =
     4General Purpose I/O or GPIO refers to a digital signal from a processor or peripheral capable of sinking or sourcing current.
     5
     6There are several details that are important when dealing with GPIOs:
     7 * voltage they drive to or are pulled up to
     8 * is there a pull-up or pull-down present
     9 * are they driving to a active-high or active-low state (totem-pole) or are they driving low and relying on a pull-up to go high (open collector)
     10 * how much current can they sink
     11 * how much current can they source
     12 * what bus is used to access them (which can affect when/where and how-fast you can read or write them)
     13 * does the gpio have an associated interrupt available (important if you want to use this as a low-overhead input)
     14
     15
     16Gateworks boards use General Purpose Input / Output (GPIO) pins commonly for things such as:
     17 * enabling/disabling of devices (ie serial drivers)
     18 * signal steering (ie steer USB bus between front-panel connector/header and PCI/PCIe slot)
     19 * device interrupt inputs (ie GSC host interrupt)
     20 * misc inputs (ie GPS PPS (pulse-per-second) input)
     21 * LED drivers (these are handled via led-class and not gpio-class)
     22 * pushbutton inputs (often handled via button-class and not gpio-class)
     23
     24All off-board GPIO signals use 3.3V TTL voltage levels.
     25
     26
     27[=#poweron-defaults]
     28== Power-on GPIO states ==
     29Usually these signals are used in such a way that the default power-on state requires no configuration of GPIO signals (ie, the power up state matches the desired power-on function).
     30
     31As customer needs vary, power-on GPIO states may vary. There are a few options for configuring GPIO's that need to be changed from the 'hardware default':
     32 * bootloader configuration (occurs within milliseconds of board power-up)
     33  * Note the avila/cambria product families can configure ARM host GPIO0-5 according to non-volatile configuration stored in the board's EEPROM which can be manipulated via the RedBoot bootloaders 'econfig' command
     34 * kernel configuration (occurs within seconds of board power-up)
     35 * userspace configuration (occurs within 10s of seconds of board power-up)
     36  * typically this would be done inside of an /etc/rc.local script or other init script. See [wiki:OpenWrt/init OpenWrt/init] and [wiki:Yocto/services Yocto/services] for more info.
     37
     38Each of these options requires a different level of software complexity.
     39
     40
     41== Fast vs Slow GPIO ==
     42A '''fast GPIO''' is one that is directly on the ARM SoC and requires memory mapped register reads and writes to access.
     43
     44A '''slow GPIO''' is one that is provided by a peripheral device that hangs off the SoC on I2C, SPI, USB, or other type of bus that requires complicated bus access mechanisms. These GPIO's are also defined by the linux kernel as GPIO's that 'can sleep' and are not suitable for certain applications that require low latency or deterministic access times in the Linux kernel or in your application usage.
     45
     46Gateworks products offer a bit of variety:
     47 * all GPIO's provided by the Gateworks System Controller (including the user pushbutton) are over I2C are slow gpio
     48 * Ventana boards have up to 4x DIO's to a connector that are ARM based fast GPIO's
     49 * GPIO's going to the miniPCI and miniPCIe connectors such as WDIS# and PERST# are ARM based fast GPIO's
     50
     51You can look at the output of /sys/kernel/debug/gpio to see what GPIO's are available and from what controller. The controller name will indicate if its an I2C controller or not.
     52
     53
     54= Linux GPIO =
     55
     56[=#gpiolib]
     57== gpiolib and gpio class ==
     58The Linux kernel can provide gpio functionality to userspace via a gpio class accessed via sysfs (/sys/class/gpio/) implemented through gpiolib (CONFIG_GPIOLIB, drivers/gpio/gpiolib*). For userspace access this requires sysfs kernel support (CONFIG_SYSFS) and the sysfs filesystem mounted which is standard for most linux systems including the Gateworks BSP's. This framework allows boards to define GPIO configuration (direction, direction-changeable, user-friendly name, state, and userspace configurable).
     59
     60Note that any gpio that is registered for use by a driver is not available for exporting for userspace control. You can cat /sys/kernel/debug/gpio to see what gpio's are current registered with the kernel.
     61
     62Here are some example use cases for using gpio-class via sysfs:
     63 * to see gpio names, config (direction), and current state: (requires debugfs kernel support and fs mounted)
     64{{{
     65cat /sys/kernel/debug/gpio
     66}}}
     67 * to export a GPIO that is available to userspace (ie provided by a gpio controller, not in-use by a kernel driver, and not already exported):
     68{{{
     69echo 9 > /sys/class/gpio/export # export gpio5 (will create /sys/class/gpio/gpio9 and configure as input)
     70echo out > /sys/class/gpio/gpio5/direction # make it an output
     71echo 1 > /sys/class/gpio/gpio5/value # set its value to high
     72}}}
     73 * to see the direction of a gpio via sysfs (only allowed for GPIO's configured as bi-directional)
     74{{{
     75cat /sys/class/gpio/gpio5/direction  ;# in/out
     76}}}
     77 * to set the direction of a gpio via sysfs (only allowed for GPIO's configured as bi-directional)
     78{{{
     79echo out > /sys/class/gpio/gpio5/direction ;# set as output
     80echo in > /sys/class/gpio/gpio5/direction ;# set as input
     81}}}
     82 * to see the state of a gpio via sysfs
     83{{{
     84cat /sys/class/gpio/gpio5/value  ;# show current state (0=low, any other value than 0=high)
     85}}}
     86 * to set the state of a gpio via sysfs
     87{{{
     88echo 0 > /sys/class/gpio/gpio5/value  ;# assert low
     89echo 1 > /sys/class/gpio/gpio5/value  ;# assert high
     90}}}
     91
     92
     93[=#mapping]
     94== GPIO mapping ==
     95The various product hardware manuals will call out GPIO devices on the board and provide a table mapping the GPIO to a GPIO host controller, a function, and a connector pinout (if going off-board).
     96
     97This hardware mapping is defined in the Linux kernel device-tree for Ventana (ie [http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi arch/arm/boot/dts/imx6qdl-gw54xx.dtsi]) or in the kernel board-support file for other product families (file, ie [https://dev.openwrt.org/browser/trunk/target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/laguna.c arch/arm/mach-cns3xxx/laguna.c]).
     98
     99If debugfs is enabled in the kernel (as it is on Gateworks BSP's) you can see a nice table of GPIO mapping via {{{/sys/kernel/debug/gpio}}}. Some examples:
     100 * GW5400:
     101{{{
     102# cat /sys/kernel/debug/gpio
     103GPIOs 0-31, platform/209c000.gpio, 209c000.gpio:
     104 gpio-26  (pps-gpio            ) in  lo   
     105 gpio-29  (PCIe reset          ) out lo   
     106 gpio-30  (phy-reset           ) out hi   
     107
     108GPIOs 32-63, platform/20a0000.gpio, 20a0000.gpio:
     109
     110GPIOs 64-95, platform/20a4000.gpio, 20a4000.gpio:
     111 gpio-86  (usb_otg_vbus        ) out lo   
     112
     113GPIOs 96-127, platform/20a8000.gpio, 20a8000.gpio:
     114 gpio-102 (user1               ) out lo   
     115 gpio-103 (user2               ) out lo   
     116 gpio-111 (user3               ) out lo   
     117
     118GPIOs 128-159, platform/20ac000.gpio, 20ac000.gpio:
     119
     120GPIOs 160-191, platform/20b0000.gpio, 20b0000.gpio:
     121
     122GPIOs 192-223, platform/20b4000.gpio, 20b4000.gpio:
     123 gpio-192 (2198000.usdhc cd    ) in  hi   
     124
     125GPIOs 240-255, i2c/0-0023, pca9555, can sleep:
     126 gpio-240 (user_pb             ) in  hi
     127}}}
     128  * Note that this does not show GPIO's that are not used by Linux drivers such as USB HUB reset, Ethernet PHY reset, etc.
     129 * GW2388:
     130{{{
     131# cat /sys/kernel/debug/gpio
     132GPIOs 0-31, cns3xxx_gpio0:
     133 gpio-0   (GPS_PPS             ) in  hi
     134 gpio-3   (USB_FAULT#          ) in  hi
     135 gpio-6   (USB_VBUS_EN         ) out hi
     136 gpio-7   (GSM_SEL0            ) out lo
     137 gpio-8   (GSM_SEL1            ) out lo
     138 gpio-9   (FP_SER_EN           ) out lo
     139
     140GPIOs 32-63, cns3xxx_gpio1:
     141
     142GPIOs 100-115, i2c/0-0023, pca9555, can sleep:
     143 gpio-100 (USER_PB#            ) in  hi
     144 gpio-114 (user2               ) out hi
     145 gpio-115 (user1               ) out hi
     146}}}
     147 * GW2387:
     148{{{
     149# cat /sys/kernel/debug/gpio
     150GPIOs 0-31, cns3xxx_gpio0:
     151 gpio-0   (GPS_PPS             ) in  hi
     152 gpio-2   (USB_FAULT#          ) in  hi
     153 gpio-5   (USB_PCI_SEL         ) out lo
     154 gpio-6   (USB_VBUS_EN         ) out hi
     155 gpio-7   (GSM_SEL0            ) out lo
     156 gpio-8   (GSM_SEL1            ) out lo
     157 gpio-9   (FP_SER_EN           ) out lo
     158
     159GPIOs 32-63, cns3xxx_gpio1:
     160
     161GPIOs 100-115, i2c/0-0023, pca9555, can sleep:
     162 gpio-100 (USER_PB#            ) in  hi
     163 gpio-114 (user2               ) out hi
     164 gpio-115 (user1               ) out hi
     165}}}
     166
     167Product Family specific notes:
     168 * Ventana:
     169  - IMX6 GPIOs: The IMX6 has 7 32bit GPIO controllers for a possible 224 fast ARM based GPIO's
     170   - GPIO1_IO[0-31]: gpio0-gpio31
     171   - GPIO2_IO[0-31]: gpio32-gpio63
     172   - GPIO3_IO[0-31]: gpio64-gpio95
     173   - GPIO4_IO[0-31]: gpio96-gpio127
     174   - GPIO5_IO[0-31]: gpio128-gpio159
     175   - GPIO6_IO[0-31]: gpio160-gpio191
     176   - GPIO7_IO[0-31]: gpio192-gpio223
     177  - [wiki:gsc GSC] GPIOs:
     178   - GSC_GPIO_P0[0-7]: gpio240-gpio247
     179   - GSC_GPIO_P1[0-7]: gpio247-gpio255
     180  - additional i2c based GPIO port-expanders present on some boards would begin at gpio116
     181 * Laguna:
     182  - cns3xxx GPIOs: The CNS3xxx has 2 32bit GPIO controllers for a possible 64 fast ARM based GPIO's
     183   - GPIOA[0-31]: gpio0-gpio31
     184   - GPIOB[0-31]: gpio32-gpio63
     185  - [wiki:gsc GSC] GPIOs:
     186   - GSC_GPIO_P0[0-7]: gpio100-gpio107
     187   - GSC_GPIO_P1[0-7]: gpio108-gpio115
     188  - additional i2c based GPIO port-expanders present on some boards would begin at gpio116
     189
     190
     191When referring to [http://www.gateworks.com/usermanuals Gateworks board user hardware manuals] you will need to translate the hardware pin name to a gpio using the information above. Some examples:
     192 * Laguna GPIOA8 would be the 9th IO on the GPIOA controller (the first is GPIOA0) thus map to gpio 0+8 = gpio-8
     193 * Laguna GPIOB1 would be the 2nd IO on the GPIOB controller thus map to gpio 32+2 = gpio-34
     194 * Ventana GPIO[1]:DIO16 is GPIO block 1 IO 16 thus maps to gpio0 + 16 (or 0*32+16) = gpio-16
     195 * Ventana GPIO[2]:DIO9 is GPIO block 2 IO 9 thus maps to gpio32 + 9 (or 1*32+9) = gpio-41
     196 * Equation: Ventana GPIO<x>__IO<y> is GPIO block x IO y thus maps to: gpio-((x-1)*32)+y
     197
     198
     199See also:
     200 * [wiki:ventana/DigitalIO Ventana Digital IO Mapping Page]
     201 * [http://www.gateworks.com/usermanuals Board specific hardware manual]
     202
     203
     204
     205[=#gpio-interrupt]
     206== catching a GPIO change from userspace without polling using an interrupt ==
     207A gpio that has an interrupt associated with it (which depends on the gpio controller and how its hooked up to the processor) can be used with a blocking poll system call. This may seem non-intuitive that you use a 'poll' call to block until an interrupt has occurred, but that is exactly what will happen when you use poll on the sysfs 'value' file representing the value of the gpio in question. Note that even if you are not interested in the value files contents (e.g. counting the total number of interrupts caused by a gpio) you must use both an lseek and a read after poll to consume the interrupt. Otherwise the previous interrupt will cause future poll calls to immediately return.
     208
     209Note that you can only do this with an GPIO that has interrupt support which means when its exported to userspace there will be an 'edge' file in this /sys/class/gpio directory.
     210
     211Example code:
     212{{{
     213/*
     214 * gpio-poll.c - demonstrate catching a GPIO change event without polling
     215 *               ironically using the poll(2) system call
     216 *
     217 * Author: Tim Harvey <tharvey@gateworks.com>
     218 */
     219
     220#include <fcntl.h>
     221#include <poll.h>
     222#include <stdio.h>
     223#include <stdlib.h>
     224#include <string.h>
     225#include <unistd.h>
     226#ifdef __ANDROID__
     227#include <cutils/android_reboot.h>
     228#else
     229#include <sys/reboot.h>
     230#endif
     231#include <sys/types.h>
     232#include <sys/stat.h>
     233
     234/* seconds to block waiting for edge
     235 *  - this also defines the interval between calls if button is held down
     236 */
     237#define BLOCK_TIME 5
     238/* seconds before press-and-release count is cleared */
     239#define MIN_REST_TIME 2
     240
     241/* called when a gpio changes value
     242 * @value - 0 is low, 1 is high
     243 *
     244 * The GSC pushbutton has an internal pullup, thus a 'button' should be
     245 * normally open, and when pressed should short to ground. Therefore a 0
     246 * is 'down', and a 1 is 'up'
     247 */
     248time_t held_time = 0; /* num seconds button held down */
     249time_t last = 0; /* last event time */
     250int num_releases = 0; /* number of successive press-and-release events */
     251void gpio_change(int gpio, int value)
     252{
     253        time_t now = time(NULL);
     254
     255        printf("gpio%d: %d last=%ld\n", gpio, value, (long)(now - last));
     256        if (!value) { /* down */
     257                long held;
     258                if (!held_time)
     259                        held_time = now;
     260
     261                held = (long)(now - held_time);
     262                printf("held=%ld\n", held);
     263
     264                /* if held for more than 5 seconds */
     265                if (held >= 5) {
     266                        printf("Powering system down\n");
     267#ifdef __ANDROID__
     268                        /* will perform a safe unmount prior to shutdown */
     269                        android_reboot(ANDROID_RB_POWEROFF, 0, 0);
     270#else
     271                        reboot(RB_POWER_OFF);
     272#endif
     273                        while (1);
     274                }
     275        } else { /* up */
     276                /* cancel held time counter */
     277                held_time = 0;
     278                /* increment or reset num_releases */
     279                if (now - last < MIN_REST_TIME) {
     280                        num_releases++;
     281                        printf("count=%d\n", num_releases);
     282
     283                        /* perform something on number of presses? */
     284                } else {
     285                        printf("reset count\n");
     286                        num_releases = 0;
     287                }
     288
     289                last = time(NULL);
     290        }
     291}
     292
     293
     294int main(int argc, char **argv)
     295{
     296        struct pollfd fdset;
     297        char path[256];
     298        char buf[32];
     299        int gpio;
     300        int fd, rz, c;
     301
     302        if (argc < 3) {
     303                fprintf(stderr, "usage: %s <gpio> <rising|falling|both>\n",
     304                        argv[0]);
     305                exit (-1);
     306        }
     307
     308        gpio = atoi(argv[1]);
     309
     310        /* configure gpio trigger:
     311         *   edge trigger of 'both' (falling and rising) allows catching
     312         *   changes in both directions vs level triggerd.
     313         */
     314        sprintf(path, "/sys/class/gpio/gpio%d/edge", gpio);
     315        if ((fd = open(path, O_WRONLY)) < 0) {
     316                perror("open() failed\n");
     317                fprintf(stderr, "non-exported or non-input gpio: %s\n", path);
     318                exit (-1);
     319        }
     320        write(fd, argv[2], strlen(argv[2]));
     321        close(fd);
     322
     323        /* open gpio sysfs value for reading in blocking mode */
     324        sprintf(path, "/sys/class/gpio/gpio%d/value", gpio);
     325        if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0) {
     326                perror("open() failed\n");
     327                fprintf(stderr, "invalid or non-exported gpio: %s\n", path);
     328                exit (-1);
     329        }
     330
     331        printf("monitoring %s for interrupt using poll()\n", path);
     332        while (1) {
     333                /* use poll(2) to block for 10s or until interrupt occurs */
     334                fdset.fd = fd;
     335                fdset.events = POLLPRI;
     336                fdset.revents = 0;
     337                if ((c = poll(&fdset, 1, 10000)) < 0) {
     338                        perror("poll() failed");
     339                        break;
     340                }
     341
     342                if (fdset.revents & POLLPRI) {
     343                        /* show gpio value */
     344                        /* Note that both an lseek and read are necessary
     345                         * in order to clear the interrupt detected by poll
     346                         */
     347                        lseek(fdset.fd, 0, SEEK_SET);
     348                        rz = read(fdset.fd, buf, sizeof(buf));
     349                        buf[rz ? rz - 1 : 0] = 0;
     350                        gpio_change(gpio, atoi(buf));
     351                }
     352        }
     353        close(fd);
     354
     355        return 0;
     356}
     357}}}
     358
     359Example usage (block until interrupt rising and falling edge interrupt occurs on gpio-100):
     360{{{
     361root@OpenWrt:/# ./gpio-poll 100 both
     362monitoring /sys/class/gpio/gpio100/value for interrupt using poll()
     363gpio100: 1
     364gpio100: 0
     365gpio100: 1
     366gpio100: 0
     367gpio100: 1
     368}}}
     369
     370
     371[=#gpio-keys]
     372== using GPIO's as buttons in Linux ==
     373Often users want to use a GPIO as a button. The best way to do this in Linux is to use the [http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/input/keyboard/gpio_keys.c gpio-keys] (KEYBOARD_GPIO) or [http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/input/keyboard/gpio_keys_polled.c gpio-keys-polled] (KEYBOARD_GPIO_POLLED) Linux input driver which allows you to assign Linux gpio's to Linux input key events which will be fired when the button is pressed and released.
     374
     375The gpio-keys driver is for gpio's that are interrupt capable and the gpio-keys-polled driver is for gpio's that are not interrupt capable and thus must be polled periodically.
     376
     377As an example of how to configure the gpio-keys driver we can look at the GW51xx which has DIO0-DIO4 mapped to ARM gpio's. The [http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi imx6qdl-gw51xx.dtsi device-tree] can have the following section added:
     378{{{
     379       /* define linux keyboard gpio-keys driver named 'gpio-button' */
     380       gpio: gpio-button {
     381               compatible = "gpio-keys";
     382               #address-cells = <1>;
     383               #size-cells = <0>;
     384               autorepeat;
     385
     386               /* map GW51xx DIO0 IMX6 GPIO1_IO16 to linux keycode 103 (KEY_UP) */
     387               button@1 {
     388                        label = "GPIO Key Up";
     389                        linux,code = <103>;
     390                        debounce-interval = <100>;
     391                        gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
     392               };
     393
     394               /* map GW51xx DIO1 IMX6 GPIO1__IO19 to linux keycode 109 (KEY_DOWN) */
     395               button@2 {
     396                        label = "GPIO Key Down";
     397                        linux,code = <108>;
     398                        debounce-interval = <100>;
     399                        gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
     400               };
     401
     402               /* map GW51xx DIO2 IMX6 GPIO1__IO17 to linux keycode 106 (KEY_RIGHT) */
     403               button@3 {
     404                        label = "GPIO Key Right";
     405                        linux,code = <106>;
     406                        debounce-interval = <100>;
     407                        gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
     408               };
     409
     410               /* map GW51xx DIO3 IMX6 GPIO1__IO18 to linux keycode 105 (KEY_LEFT) */
     411               button@4 {
     412                        label = "GPIO Key Left";
     413                        linux,code = <105>;
     414                        debounce-interval = <100>;
     415                        gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
     416               };
     417        };
     418
     419}}}
     420 * The gpio node needs to be at the top level and its placement is arbitrary however its customary to put it in alphabetical order (thus between the '''chosen''' node and the '''leds''' node)
     421
     422
     423BSP Specific notes:
     424 * OpenWrt replaces the gpio-keys and gpio-keys-polled Linux driver with their out-of-tree driver called gpio-button-hotplug which instead of emiting linux input events emits uevent messages to the button subsystem which tie into the OpenWrt hotplug daemon. See the [wiki:OpenWrt/gpio#button-hotplug-gw OpenWrt/gpio page] for more details.
     425 * Android can map Linux input events to Android key events via a !KeyLayout file - see [wiki:Android/OSDevelopment#gpio-pushbutton here] for details.
     426
     427
     428References:
     429 * gpio-keys [http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/input/keyboard/gpio_keys.c driver] and [https://lxr.missinglinkelectronics.com/linux/Documentation/devicetree/bindings/input/gpio-keys.txt device-tree bindings]
     430 * gpio-keys-polled [http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/input/keyboard/gpio_keys_polled.c driver] and  [https://lxr.missinglinkelectronics.com/linux/Documentation/devicetree/bindings/input/gpio-keys-polled.txt device-tree bindings]
     431
     432
     433[=#led_class]
     434= Linux LED class for GPIO (and PWM) controlled LEDs =
     435see wiki:linux/led
     436
     437
     438= Other References =
     439Here are some other useful references from our wiki:
     440 * [wiki:linux/pwm Pulse-Width-Modulation (PWM) outputs]
     441 * [wiki:linux/led Linux GPIO and PWM based LEDs]
     442 * [wiki:OpenWrt/gpio GPIO in OpenWrt]
     443 * [wiki:ventana/DigitalIO Ventana product family Digital I/O]