Controlling GPIO from Linux User Space Print


This application note explains how to drive GPIO outputs and read the state of GPIO inputs from the Linux user-space on the Kinetis.

The API that is used to control GPIO is the standard Linux GPIOLIB interface. The API is described in the Linux documenation available in the kernel tree from the following file: inux/Documentation/gpio.txt.

Alternatively, the same document can be found in the Internet, for instance here:
http://lxr.free-electrons.com/source/Documentation/gpio/sysfs.txt

To enable the generic GPIO interface in the kernel, you need to enable certain build-time configuration options. Specifically, from the kernel configuration menu, go to Device Drivers, enable GPIO Support (CONFIG_GPIOLIB), and then from the GPIO Support menu enable the sysfs interface item (CONFIG_GPIO_SYSFS):

Now, most of the Kinetis GPIO pins can be used in different multiplexed I/O roles (for instance, some GPIO pins can be also configured as an SPI interface, etc). Depending on specific requirements of your applications, you need to configure those pins that you want to use as GPIO for the GPIO role and other pins as an alternative I/O function.

For the purposes of this application note, we want to configure two pins as GPIO, specifically:

  • PTB18 is connected to the User LED DS3 on the TWR-K70-SOM-BSB baseboard;
  • PTC3 is connected to the User Push button on the TWR-K70-SOM-BSB baseboard (the User Push button is available only the Rev 2A of the TWR-K70-SOM-BSB baseboard).

In the Kinetis kernel, the I/O functions of the Kinetis pins are defined in the following file:
linux/arch/arm/mach-kinetis/iomux.c.

Here is the code that is responsible for configuring the above two pins for the GPIO function. Enable it in the source file:

/* The "User Button" is at PTC3, with external pullup */
{{KINETIS_GPIO_PORT_C, 3}, KINETIS_GPIO_CONFIG_MUX(1)},

/* LEDs DS3 */
{{KINETIS_GPIO_PORT_B, 18}, KINETIS_GPIO_CONFIG_MUX(1)},

Having configured the kernel as described above, build the Linux image and load it to the Kinetis SOM Starter Kit.

On the Linux running on the Kinetis, each GPIO is assigned a unique integer GPIO number within the GPIO chip range of 0 to 191:

~ # cd /sys/class/gpio/
/sys/class/gpio # ls
export gpiochip0 unexport
/sys/class/gpio # cat gpiochip0/ngpio
192
/sys/class/gpio #

To calculate the GPIO number for a specific GPIO, use the following formula:

gpio = (bank * 32) + pin

Bank numbers start with 0 (corresponding to Bank A, etc), pin numbers start with 0 (corresponding to pin 0, etc).

For the User Push Button the specific pin is PTC3, which corresponds to the following GPIO number:

(2 * 32) + 3 = 67

First step is to add (export) the pin to the GPIO array and define it as an input. This is done as follows:

/sys/class/gpio # echo 67 > export
/sys/class/gpio # echo in > gpio67/direction
/sys/class/gpio #

Now, all is ready to read the value of the User Push button. First, leave the button unpressed on the board and read the signal. There is an external pull-up resistor on the User Push button GPIO so when unpressed the GPIO reads as 1:

/sys/class/gpio # cat gpio67/value
1
/sys/class/gpio # cat gpio67/value
1
/sys/class/gpio #

Push the button and make sure the GPIO value reads as 0:

/sys/class/gpio # cat gpio67/value
0
/sys/class/gpio # cat gpio67/value
0
/sys/class/gpio #

Release the button and validate that the value has returned to 1:

/sys/class/gpio # cat gpio67/value
1
/sys/class/gpio # cat gpio67/value
1
/sys/class/gpio #

For the User LED the specific pin is PTB18, which corresponds to the following GPIO number:

(1 * 32) + 18 = 50

Export the GPIO and define it as an output:

/sys/class/gpio # echo 50 > export
/sys/class/gpio # echo out > gpio50/direction
/sys/class/gpio #

Now run the following shell commands to turn the LED on and off at a 1Hz frequency:

/sys/class/gpio # while echo hey
> do
> echo 1 > gpio50/value; sleep 1
> echo 0 > gpio50/value; sleep 1
> done
hey
hey
hey
hey
hey
hey
hey
^C

/sys/class/gpio #

If you need to control GPIO from C / C++ code, it is probably a good idea to perform the GPIO setup (export, define direction, etc) from a start-up script (eg. in /etc/rc). You can then use the standard POSIX APIs such as open, read, write, etc on gpioxx/value files to control your GPIO from C code.