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 Vybrid.

The API that is used to control GPIO is the standard Linux GPIOLIB interface. The API is described in the Linux documentation available in the kernel tree from the following file: linux/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 Vybrid 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:

  • PTB14 is connected to the User LED DS4 on the TWR-VF6-SOM-BSB baseboard;
  • PTC30 is connected to pin 13 of header P10 on the TWR-VF6-SOM-BSB baseboard.

In the Vybrid kernel, the I/O functions of the Vybrid pins are defined in the following file:
linux/arch/arm/mach-mvf/board-emcraft-vybrid-som.c.

Here is the code that is responsible for configuring the above two pins for the GPIO function (note that the PTB14 signal configuration is present in the release source code but the PTC30 configuration must be added in order to make corresponding examples from this application note work):

/* GPIO36 */
#define VYBRID_SOM_PAD36_PTB14__LED1 \
IOMUX_PAD(0x90, 0x90, 0, 0x0000, 0, \
MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE)

/* GPIO103 */
#define VYBRID_SOM_PAD103_PTC30__INPUT_SIGNAL \
IOMUX_PAD(0x19c, 0x19c, 0, 0x0000, 0, \
MVF600_GPIO_GENERAL_CTRL | PAD_CTL_OBE_ENABLE | PAD_CTL_ODE)

static iomux_v3_cfg_t mvf600_pads[] = {

/* User LEDs */
VYBRID_SOM_PAD36_PTB14__LED1,

/* PTC30 Test Input signal */
VYBRID_SOM_PAD103_PTC30__INPUT_SIGNAL,
};

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

On the Linux running on the Vybrid, each Vybrid pad that can be used as GPIO pin is assigned a unique integer GPIO number within the GPIO chip range of 0 to 134. Mapping between a Vybrid pad and integer GPIO number is defined in section “8.11.1.1 GPIO Mapping” of the Vybrid Reference Manual.

For the Test Input signal the specific pin is PTC30, which corresponds to GPIO number 103. First step is to add (export) the pin to the GPIO array and define it as an input. This is done as follows:

~ # cd /sys/class/gpio/
/sys/class/gpio # echo 103 > export
/sys/class/gpio # echo in > gpio103/direction
/sys/class/gpio #

Now, all is ready to read the value of the Test Input signal. First, connect the PTC30 pad (pin P10.13 of the TWR-VF6-SOM-BSB) to the 3.3V signal at P10.19 of the TWR-VF6-SOM-BSB:

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

Now, connect pin P10.13 to the ground (pin P10.20):

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

Connect again pin P10.13 to pin P10.19:

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

For the User LED the specific pin is PTB14, which corresponds to GPIO number 36. Export the GPIO and define it as an output:

/sys/class/gpio # echo 36 > export
/sys/class/gpio # echo out > gpio36/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 > gpio36/value; sleep 1; echo 0 > gpio36/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.