[[PageOutline]] = OpenWrt GPIO = This page discusses aspects of GPIO particular to the OpenWrt BSP. For GPIO hardware and Linux basics please refer to the [wiki:gpio gpio] page. [=#gpiolib_sysfs] == Linux gpiolib / gpio class == The standard Linux way of working with GPIO's uses a gpio class accessed via {{{/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 OpenWrt based BSP). This framework allows kernel board-support to define GPIO configuration (direction, direction-changeable, user-friendly name, state, and userspace configurable). The benefit of this standard method is: 1. its a linux standard 2. it allows you to configure GPIO's in such a way that users don't have the ability to change them to invalid states per hardware design 3. it allows you to name gpio's with a user-friendly name For details on using the Linux gpio class from userspace see the [wiki:gpio#gpiolib gpio] page. [=#init_script] == OpenWrt init script for configuring GPIO == If you wish to configure a GPIO differently from its power-on state, bootloader config state (if any), kernel config state (if any), you may do so in userspace. A common way to control board initialization is through init scripts. An example OpenWrt init-script that runs only at 'boot' time: * {{{/etc/init.d/gpio}}} {{{ #!bash #!/bin/sh /etc/rc.common # Copyright (C) 2006 OpenWrt.org START=20 boot() { [ -d /sys/class/gpio ] && { # Custom GPIO Configuration: # GW2382 - steer USB from FP to PCIe: echo 0 > /sys/class/gpio/gpio10/value } } }}} * to enable make sure this script is executable and enabled via: {{{ #!bash chmod +x /etc/init.d/gpio /etc/init.d/gpio enable }}} [=#button-hotplug-gw] == OpenWrt gpio-button-hotplug driver == OpenWrt uses a home-grown app called {{{procd}}} as PID1. One of {{{procd}}}'s features is to catch messages from the kernel and act upon them, much in the way a conventional linux system uses a hotplug helper and udev. The {{{/etc/hotplug.json}}} file configures how various events are handled: * using makedev to create device nodes in /dev on 'add' events and removing the nodes on 'remove' events * facilitate firmware loading * calling {{{/sbin/hotplug-call}}} on platform subsystem events * calling {{{/etc/rc.button/$BUTTON}}} on button (Linux input) events * calling {{{/sbin/hotplug-call}}} on various subsystem events (such as net, input, usb, block, atm, tty, button) Button (Linux input) events: - {{{/sbin/hotplug-call}}} will have the following defined: - {{{BUTTON}}} - button name (ie BTN_0 for user pushbutton) - {{{ACTION}}} - pressed|released - {{{SEQNUM}}} - a numeric value that increments with the event message - {{{SEEN}}} - number of seconds since last button event from driver * this can be used to determine how long a button has been 'held' for 'released' events. If a button is released and {{{SEEN=8}}} it has been held for 8 seconds The {{{gpio-button-hotplug}}} driver is the Linux kernel driver that creates hotplug events for GPIO based buttons. The {{{gpio-button-hotplug}}} out-of-tree driver is an OpenWrt custom driver that takes the place of the in-kernel {{{gpio-keys}}} (KEYBOARD_GPIO) and {{{gpio_keys_polled}}} (KEYBOARD_GPIO_POLLED) drivers and instead of emiting linux input events it emits uevent messages to the button subsystem which tie into the OpenWrt hotplug daemon. Note that for Ventana this uses the {{{gpio_keys}}} device-tree node to map gpio-240 to the {{{user_pb}}} button event. === Gateworks Button Hotplug package === The Gateworks [https://github.com/Gateworks/gw-openwrt-packages/tree/master/gateworks/button-hotplug-gw button-hotplug-gw] package installs the {{{/etc/hotplug.d/button/00-button}}} handler which does the following using UCI configuration for one or more buttons: * catching multiple successive button events (ie 3x press/release) * min and max hold times (ie catch a button release after being held for 10 secs) Example configuration ({{{/etc/config/system}}}): {{{ #!bash # catch BTN_0 pressed and released 3 times in quick succession (held for <1 sec each time): config button option button 'BTN_0' option action 'released' option handler 'logger BTN_0 pressed: 3x' option repeat '3' # catch BTN_0 released after behind held for 0 to 3 seconds config button option button 'BTN_0' option action 'released' option handler 'logger BTN_0 pressed: 0-3s' option min '0' option max '3' # catch BTN_0 released after behind held for 8 to 10 seconds config button option button 'BTN_0' option action 'released' option handler 'logger BTN_0 pressed: 8-10s' option min '5' option max '20' }}} * Note that the {{{logread}}} application can be used to read the output of the system log. By default {{{logger}}} will not send info to the serial console: {{{ #!bash logread -f # show all new log activity }}} Note that to use the user pushbutton present on the front panel of most Gateworks boards, you must configure the Gateworks System Controller (GSC) to not hard-reset the board on a button press: {{{ #!bash i2cset -f -y 0 0x20 0 0x00 # disable pushbutton hard reset i2cset -f -y 0 0x20 11 0xff # enable all interrupts }}} Refer to the [wiki:gsc#pushbutton GSC pushbutton] wiki section for information on properly configuring your board for pushbutton events and the [wiki:gsc#IRQ_GPIO_CHANGE GSC IRQ_GPIO_CHANGE] wiki section for information on GSC interrupts. ==== Factory Reset ==== In our latest [https://github.com/Gateworks/openwrt OpenWrt branch], we have added a factory reset handler through the above-mentioned button handler to factory reset the board. On first boot, the system uci entries default to the following: {{{ #!bash > uci show system ... system.@button[0]=button system.@button[0].button='BTN_0' system.@button[0].action='pressed' system.@button[0].handler='logger BTN_0 pressed' system.@button[1]=button system.@button[1].button='BTN_0' system.@button[1].action='released' system.@button[1].handler='factory_reset' system.@button[1].min='15' system.@button[1].max='999' ... }}} From the above, we can see that to invoke the factory reset, the pushbutton must be held for a minimum of 15s, to a maximum of 999s. This will invoke the function "factory_reset" which can be found in {{{/etc/hotplug.d/button/factory_reset}}}. The script will attempt to write to the console and log that a factory reset is occurring, as well as attempt to take over the user LEDs to make it a solid 'red' color. Change the {{{uci}}} entries to match your desired outcome. Please note that at the very least, both the IRQ_PB and IRQ_GPIO_CHANGE must be enabled in the gsc: {{{ #!bash i2cset -f -y 0 0x20 11 0x11 # enable IRQ_PB and IRQ_GPIO_CHANGE }}} [=#led] == GPIO based LEDs == GPIO's that drive LED's are controlled via the [wiki:gpio#led_class Linux led class]. OpenWrt has a UCI method of configuring LED's on boot via {{{/etc/config/system}}}. By default, the Gateworks OpenWrt BSP installs the '''userled-heartbeat'' package which sets the '''heartbeat''' trigger on the '''user1''' led. On most boards this is the green LED on the front-panel bi-color LED and results in the LED blinking green twice a second like a heartbeat. This is accomplished from the following configuration in {{{/etc/config/system}}}: {{{ #!bash config led option default '0' option name 'heartbeat' option sysfs 'user1' option trigger 'heartbeat' }}} See also: * [wiki:gpio#led_class Linux LED class]