Version 1 (modified by 7 years ago) ( diff ) | ,
---|
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 (although OpenWrt
gpioctl
defeats this protection) - it allows you to name gpio's with a user-friendly name
For details on using the Linux gpio class from userspace see the gpio page.
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:
- it is not linux standard (It has been removed from current OpenWrt trunk and thus won't be present in future Gateworks firmware)
- it does not allow you to determine the current configuration mode of a pin (input/output)
- it is not as easy to script (need to use sed/awk/grep)
- 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:
# 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
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
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 nameACTION
- 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 i2cset -f -y 0 0x20 11 0xff # enable all interrupts
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: