[[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 (although OpenWrt {{{gpioctl}}} defeats this protection) 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. [=#gpioctl] == OpenWrt gpioctl - NOW DEPRECATED == The older method of controlling GPIO's used by OpenWrt was the {{{gpioctl}}} userspace utility and the kernel driver ({{{package/feeds/packages/gpiotoggling}}}). This was is an OpenWrt creation (as opposed to a 'linux standard' driver/API). It has the benefit (or downside depending on your point of view) of having 'full control' over the GPIO's even if the user should not. It was created at a time where linux-gpio was changing and lacked some standardization. The downside of this application/API: 1. it is not linux standard (It has been removed from current OpenWrt trunk and thus won't be present in future Gateworks firmware) 2. it does not allow you to determine the current configuration mode of a pin (input/output) 3. it is not as easy to script (need to use sed/awk/grep) 4. it can override GPIO configuration in cases where board-support does not wish to allow you to do so This driver/application can be useful however if a GPIO is not configured/exported correctly in the kernel and it can co-exist just fine with the more standard gpio-class mechanism shown below. Example usage: {{{ #!bash # configure gpio8 as an input gpioctl dirin 8 # get current state of gpio8 gpioctl get 8 # configure gpio8 as an output gpioctl dirout 8 # set gpio8 state gpioctl set 8 ;# high gpioctl clear 8 ;# low }}} [=#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 == Our modern OpenWrt based BSP's use OpenWrt {{{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 events * calling {{{/sbin/hotplug-call}}} on various subsystem events (such as net, input, usb, block, atm, tty, button) Button events: - {{{/sbin/hotplug-call}}} will have the following defined: - {{{BUTTON}}} - button name - {{{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]