OpenWrt GPIO
This page discusses aspects of GPIO particular to the OpenWrt BSP. For GPIO hardware and Linux basics please refer to the gpio page.
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:
- its a linux standard
- 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
- it allows you to name gpio's with a user-friendly name
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
#!/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:
chmod +x /etc/init.d/gpio /etc/init.d/gpio enable
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|releasedSEQNUM
- a numeric value that increments with the event messageSEEN
- 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
- this can be used to determine how long a button has been 'held' for 'released' events. If a button is released and
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 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
):
# 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 defaultlogger
will not send info to the serial console: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:
i2cset -f -y 0 0x20 0 0x00 # disable pushbutton hard reset
Refer to the GSC pushbutton wiki section for information on properly configuring your board for pushbutton events and the GSC IRQ_GPIO_CHANGE wiki section for information on GSC interrupts.
Factory Reset
In our latest 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:
> 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:
i2cset -f -y 0 0x20 11 0x11 # enable IRQ_PB and IRQ_GPIO_CHANGE
GPIO based LEDs
GPIO's that drive LED's are controlled via the 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
:
config led option default '0' option name 'heartbeat' option sysfs 'user1' option trigger 'heartbeat'
See also: