world leader in high performance signal processing
Trace: » simple-gpio

Simple GPIO Driver

The simple GPIO driver allows users to manipulate any GPIO from userspace (also known as programmable flags). It also serves as simple sample driver for people who wish to see a good example for working with GPIOs using the GPIO framework. And for the people who are just getting started, a very simple character device driver.

Userspace interacts with any GPIO via a character device node. The act of opening and closing it corresponds to the act of claiming and releasing the GPIO. When you read from it, you get back the GPIO data (which usually corresponds to a 0 or 1 which represents the signal level). To control the GPIO, you write individual characters which correspond to a simple “command set”. This way you can control the direction and value with single bytes.

Notice that the creation of the device node merely exposes the resource. Claiming of the resource does not actually occur until you open the device node. In this way you can dynamically share the GPIO resource with other drivers by only claiming it when you need it.

Each GPIO corresponds directly to a character device node. So /dev/gpio5 represents GPIO 5.

If you need non-blocking reads, support for poll() and select() system calls. You should use the gpio-keys input device driver gpio-keys

This driver is deprecated with linux-2.6.28+ (2009R1+) by the gpio-sysfs driver

Setup

Resources

You declare the range of GPIOs that you want exposed via the platform resources. So for the BF537 STAMP board, we expose all GPIOs by default.

file: arch/blackfin/mach-bf537/boards/stamp.c

scm failed with exit code 1:
file does not exist in git

file: arch/blackfin/mach-bf537/boards/stamp.c

scm failed with exit code 1:
file does not exist in git

Config

The device driver can be found in the kernel configuration menu:

Device Drivers  --->
  Character devices  --->
    <*> Simple GPIO char interface

Driver Functions

Init

The init function does the following:

  • Create the “simple-gpio” class
  • Register the platform device driver

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Probe

The real meat of the setup process occurs here:

  • Find the simple-gpio resources specified in the board file
  • Setup a new group of GPIOs for the specified range
  • Dynamically register a character device major using cdev
  • Create devices for each new GPIO

You can see here that we use the minor numbers to communicate the GPIO number to kernel space.

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

File Operations Table

This has the normal open, release, read, and write functions.

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Open

The open function makes sure the GPIO number is within range, and then it tries to request it using gpio_request. You can see we allow any number of people to open the device at the same time. Resource management is done by the GPIO framework.

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Release

The release function also makes sure the GPIO number is valid, and if this is the last consumer to close the device, we release the GPIO with gpio_free so that some other driver may use it.

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Read

The read function just returns the state of the GPIO with the gpio_get_value function.

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Write

The write function allows the user to control the GPIO. The simple command set is:

Command Description
I Set GPIO direction to input via gpio_direction_input
O Set GPIO direction to output via gpio_direction_output
T Toggle the GPIO value
0 Set GPIO value to 0 via gpio_set_value
1 Set GPIO value to 1 via gpio_set_value

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Remove

Here we reverse the operations performed by the probe function:

  • Destroy GPIO devices
  • Delete character device and major/minor numbers
  • Free memory

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Exit

Here we reverse the operations performed by the init function:

  • Destroy the simple-gpio class
  • Unregister the platform driver

file: drivers/char/simple-gpio.c

scm failed with exit code 1:
file does not exist in git

Testing

Simple output operations can be executed from the shell per echo command, e.g.

root:/> echo 'O0' > /dev/gpio17
This sets a port bit to output with value 0. See table above under section “write”. Note though that open close() of a GPIO device, the GPIO is freed which puts it back to its reset state. So the above command will only toggle the state.

Further, a few simple test programs to illustrate the userspace side of working with the device driver are available. These are integrated into the uClinux distribution that we distribute.

In the uClinux dist vendor/user configuration menu, select:

Blackfin test programs  --->
  [*] Simple GPIO test

simple-gpio-test.c

This test will open the specified GPIO and wait for it to go high. In other words, this tests a Push Button. So on the BF537-STAMP, you should choose a GPIO that is tied to one of the PB's on the board (and make sure you have not disconnected the push buttons with the board switches).

root:~> simple-gpio-test /dev/gpio2
Going to sleep until the gpio goes high.
(if this is a button, you should push it :p)
The gpio went high!  Time to bail!

While it's hard to show it in a wiki, I just pushed PB1 on the stamp board (which is hooked up to GPIO 2). The userspace application constantly read from the GPIO until it detected the push.

simple-gpio-game.c

This is a little more complicated. You specify a list of GPIOs to be treated as buttons and a list of GPIOs to be treated as LEDs. First the application will run “blinky” on all of the LEDs for a few seconds, then it will synchronize the LEDs with the respective push buttons. So whenever you push a button, the corresponding LED will light up. Whenever a button is released, the corresponding LED will go dark.