| 1 | [[PageOutline]] |
| 2 | |
| 3 | = OpenWrt GPIO = |
| 4 | 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. |
| 5 | |
| 6 | [=#gpiolib_sysfs] |
| 7 | == Linux gpiolib / gpio class == |
| 8 | 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). |
| 9 | |
| 10 | 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: |
| 11 | 1. its a linux standard |
| 12 | 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) |
| 13 | 3. it allows you to name gpio's with a user-friendly name |
| 14 | |
| 15 | For details on using the Linux gpio class from userspace see the [wiki:gpio#gpiolib gpio] page. |
| 16 | |
| 17 | [=#gpioctl] |
| 18 | == OpenWrt gpioctl - NOW DEPRECATED == |
| 19 | 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. |
| 20 | |
| 21 | The downside of this application/API: |
| 22 | 1. it is not linux standard (It has been removed from current OpenWrt trunk and thus won't be present in future Gateworks firmware) |
| 23 | 2. it does not allow you to determine the current configuration mode of a pin (input/output) |
| 24 | 3. it is not as easy to script (need to use sed/awk/grep) |
| 25 | 4. it can override GPIO configuration in cases where board-support does not wish to allow you to do so |
| 26 | |
| 27 | 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. |
| 28 | |
| 29 | Example usage: |
| 30 | {{{ |
| 31 | #!bash |
| 32 | # configure gpio8 as an input |
| 33 | gpioctl dirin 8 |
| 34 | |
| 35 | # get current state of gpio8 |
| 36 | gpioctl get 8 |
| 37 | |
| 38 | # configure gpio8 as an output |
| 39 | gpioctl dirout 8 |
| 40 | |
| 41 | # set gpio8 state |
| 42 | gpioctl set 8 ;# high |
| 43 | gpioctl clear 8 ;# low |
| 44 | }}} |
| 45 | |
| 46 | |
| 47 | [=#init_script] |
| 48 | == OpenWrt init script for configuring GPIO == |
| 49 | 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. |
| 50 | |
| 51 | An example OpenWrt init-script that runs only at 'boot' time: |
| 52 | * {{{/etc/init.d/gpio}}} |
| 53 | {{{ |
| 54 | #!bash |
| 55 | #!/bin/sh /etc/rc.common |
| 56 | # Copyright (C) 2006 OpenWrt.org |
| 57 | |
| 58 | START=20 |
| 59 | boot() { |
| 60 | [ -d /sys/class/gpio ] && { |
| 61 | # Custom GPIO Configuration: |
| 62 | # GW2382 - steer USB from FP to PCIe: |
| 63 | echo 0 > /sys/class/gpio/gpio10/value |
| 64 | } |
| 65 | } |
| 66 | }}} |
| 67 | * to enable make sure this script is executable and enabled via: |
| 68 | {{{ |
| 69 | #!bash |
| 70 | chmod +x /etc/init.d/gpio |
| 71 | /etc/init.d/gpio enable |
| 72 | }}} |
| 73 | |
| 74 | [=#button-hotplug-gw] |
| 75 | == OpenWrt gpio-button-hotplug driver == |
| 76 | 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: |
| 77 | * using makedev to create device nodes in /dev on 'add' events and removing the nodes on 'remove' events |
| 78 | * facilitate firmware loading |
| 79 | * calling {{{/sbin/hotplug-call}}} on platform subsystem events |
| 80 | * calling {{{/etc/rc.button/$BUTTON}}} on button events |
| 81 | * calling {{{/sbin/hotplug-call}}} on various subsystem events (such as net, input, usb, block, atm, tty, button) |
| 82 | |
| 83 | Button events: |
| 84 | - {{{/sbin/hotplug-call}}} will have the following defined: |
| 85 | - {{{BUTTON}}} - button name |
| 86 | - {{{ACTION}}} - pressed|released |
| 87 | - {{{SEQNUM}}} - a numeric value that increments with the event message |
| 88 | - {{{SEEN}}} - number of seconds since last button event from driver |
| 89 | * 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 |
| 90 | |
| 91 | 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. |
| 92 | Note that for Ventana this uses the {{{gpio_keys}}} device-tree node to map gpio-240 to the {{{user_pb}}} button event. |
| 93 | |
| 94 | === Gateworks Button Hotplug package === |
| 95 | 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: |
| 96 | * catching multiple successive button events (ie 3x press/release) |
| 97 | * min and max hold times (ie catch a button release after being held for 10 secs) |
| 98 | |
| 99 | Example configuration ({{{/etc/config/system}}}): |
| 100 | {{{ |
| 101 | #!bash |
| 102 | # catch BTN_0 pressed and released 3 times in quick succession (held for <1 sec each time): |
| 103 | config button |
| 104 | option button 'BTN_0' |
| 105 | option action 'released' |
| 106 | option handler 'logger BTN_0 pressed: 3x' |
| 107 | option repeat '3' |
| 108 | |
| 109 | # catch BTN_0 released after behind held for 0 to 3 seconds |
| 110 | config button |
| 111 | option button 'BTN_0' |
| 112 | option action 'released' |
| 113 | option handler 'logger BTN_0 pressed: 0-3s' |
| 114 | option min '0' |
| 115 | option max '3' |
| 116 | |
| 117 | # catch BTN_0 released after behind held for 8 to 10 seconds |
| 118 | config button |
| 119 | option button 'BTN_0' |
| 120 | option action 'released' |
| 121 | option handler 'logger BTN_0 pressed: 8-10s' |
| 122 | option min '5' |
| 123 | option max '20' |
| 124 | }}} |
| 125 | * 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: |
| 126 | {{{ |
| 127 | #!bash |
| 128 | logread -f # show all new log activity |
| 129 | }}} |
| 130 | |
| 131 | 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: |
| 132 | {{{ |
| 133 | #!bash |
| 134 | i2cset -f -y 0 0x20 0 0x00 # disable pushbutton hard reset |
| 135 | i2cset -f -y 0 0x20 11 0xff # enable all interrupts |
| 136 | }}} |
| 137 | |
| 138 | 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. |
| 139 | |
| 140 | ==== Factory Reset ==== |
| 141 | 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: |
| 142 | {{{ |
| 143 | #!bash |
| 144 | > uci show system |
| 145 | ... |
| 146 | system.@button[0]=button |
| 147 | system.@button[0].button='BTN_0' |
| 148 | system.@button[0].action='pressed' |
| 149 | system.@button[0].handler='logger BTN_0 pressed' |
| 150 | system.@button[1]=button |
| 151 | system.@button[1].button='BTN_0' |
| 152 | system.@button[1].action='released' |
| 153 | system.@button[1].handler='factory_reset' |
| 154 | system.@button[1].min='15' |
| 155 | system.@button[1].max='999' |
| 156 | ... |
| 157 | }}} |
| 158 | |
| 159 | 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. |
| 160 | |
| 161 | Please note that at the very least, both the IRQ_PB and IRQ_GPIO_CHANGE must be enabled in the gsc: |
| 162 | {{{ |
| 163 | #!bash |
| 164 | i2cset -f -y 0 0x20 11 0x11 # enable IRQ_PB and IRQ_GPIO_CHANGE |
| 165 | }}} |
| 166 | |
| 167 | [=#led] |
| 168 | == GPIO based LEDs == |
| 169 | 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}}}. |
| 170 | |
| 171 | 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. |
| 172 | |
| 173 | This is accomplished from the following configuration in {{{/etc/config/system}}}: |
| 174 | {{{ |
| 175 | #!bash |
| 176 | config led |
| 177 | option default '0' |
| 178 | option name 'heartbeat' |
| 179 | option sysfs 'user1' |
| 180 | option trigger 'heartbeat' |
| 181 | }}} |
| 182 | |
| 183 | |
| 184 | See also: |
| 185 | * [wiki:gpio#led_class Linux LED class] |