wiki:OpenWrt/gpio

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:

  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 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:

  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:

# 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 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 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 default logger 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:

Last modified 12 months ago Last modified on 08/24/16 15:40:45

Attachments (2)

Download all attachments as: .zip