Login

Why register?

  • Download software and technical materials
  • Purchase products at our on-line shop
  • Receive design news to stay up-to-date with Emcraft's new solutions

 

 

Controlling GPIO from Linux User Space Print

 

This application note shows how to control Vybrid GPIOs from the user level using the standard Linux GPIOLIB interface.


Changes to the Kernel Configuration

The generic GPIO interface is controlled by the CONFIG_GPIOLIB kernel option enabled by default in the rootfs project installed to each Vyrid System-on-Module shipped by Emcraft. 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 the requirements of your application, you need to configure the pins that you want to use as GPIO for the GPIO role and other pins for an alternative I/O function.

In this application note, we configure the following pin as GPIO:

  • PTA12 - this pin is connected to the pin 18 of the P9 header on the LCD-VF6-SOM-BSB baseboard and, as such, can be used as a GPIO Input/Output.

The pin multiplexing, as well as the GPIO specific configuration, is performed by the Linux kernel drivers using the information from the rootfs.dts file. Let's edit this file and add the information about the above GPIO:

  • Look at the linux/arch/arm/boot/dts/vf610-pinfunc.h file for definition of the pin in the form VF610_PAD_PTXXX__GPIO_YYY, where XXX is the Vybrid pin name, and YYY is the index of the pin which will be used for accessing from the Linux shell:
  • #define VF610_PAD_PTA12__GPIO_5 0x014 0x000 ALT0 0x0

  • Add this definition to pinctrl_gpios in projects/rootfs/rootfs.dts in order to configure this signal as input/output GPIO:
  • &iomuxc {
    ...
    pinctrl_gpios: gpios_grp {
    fsl,pins = <
    ...
    VF610_PAD_PTA12__GPIO_5 (VF610_GPIO_CTRL | PAD_CTL_OBE_IBE_ENABLE)
    ...
    >;
    };
    ...
    };

After applying the above changes to the rootfs.dts file, rebuild the rootfs project as described in the Installing and Activating Cross Development Environment application notes and install it on the target.


Testing GPIO

Each GPIO is assigned a unique integer GPIO number within the GPIO chip range of 0 to 134 by Linux. This number is represented by the YYY component of the VF610_PAD_PTXXX__GPIO_YYY definition as described above.

The first step is to add (export) the pin to the GPIO array and define it as an input using its index (5 is this example). This is done as follows:

~ # echo 5 > /sys/class/gpio/export
~ # echo in > /sys/class/gpio/gpio5/direction
~ #

Now, all is ready to read the value of the pin. First, connect the pin (P9.18) to the ground (P9.31), so this gpio reads 0:

~ # cat /sys/class/gpio/gpio5/value
0
~ #

Next, break the connection of P9.18 with the ground and connect this pin to the VCC3_P instead (P9.1):

~ # cat /sys/class/gpio/gpio5/value
1
~ #

To test this pin as output, disconnect everything from it and attach a voltemeter instead. Change the direction (don't need to export a pin that is already exported in this session):

~ # echo out > /sys/class/gpio/gpio5/direction
~ #

Now run the following shell commands to turn the gpio on and off at a 1Hz frequency, observe the alternating values with the voltmeter:

~ # while [ 1 ]; do echo 1 > /sys/class/gpio/gpio5/value; sleep 1; echo 0 > /sys/class/gpio/gpio5/value; sleep 1; done


GPIO for LEDs and Push Buttons

Refer to the rootfs.dts file for examples of using the standard Linux facilities for the DS2 and DS3 LEDs and the USER_BTN1 and USER_BTN2 buttons of the LCD-VF6-SOM-BSB baseboard:

projects/rootfs/rootfs.dts:

leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_leds>;

DS2 {
gpios = <&gpio3 2 0>;
default-state = "off";
};

DS3 {
gpios = <&gpio3 7 0>;
default-state = "off";
};

...
};

gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_keys>;

user_btn1 {
label = "USER_BTN1";
gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
gpio-key,wakeup;
linux,code =<KEY_PROG1> ;
};

user_btn2 {
label = "USER_BTN2";
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
gpio-key,wakeup;
linux,code = <KEY_PROG2> ;
};
};

&iomuxc {
...
pinctrl_gpio_leds: ledsgrp {
fsl,pins = <
VF610_PAD_PTB28__GPIO_98 (VF610_GPIO_CTRL | PAD_CTL_OBE_ENABLE)
VF610_PAD_PTC30__GPIO_103 (VF610_GPIO_CTRL | PAD_CTL_OBE_ENABLE)
>;
};
pinctrl_gpio_keys: keys0grp {
fsl,pins = <
VF610_PAD_PTB3__GPIO_25 (VF610_GPIO_CTRL | PAD_CTL_IBE_ENABLE)
VF610_PAD_PTB13__GPIO_35 (VF610_GPIO_CTRL | PAD_CTL_IBE_ENABLE)
>;
};
...
};

The LEDs are accessible via /sys/class/leds/{DS2,DS3}/brightness:

~ # # Turn on the DS2:
~ # echo 255 > /sys/class/leds/DS2/brightness
~ #
~ # # Turn off the DS2:
~ # echo 0 > /sys/class/leds/DS2/brightness
~ #
~ # # Turn on the DS3:
~ # echo 255 > /sys/class/leds/DS3/brightness
~ #
~ # # Turn off the DS3:
~ # echo 0 > /sys/class/leds/DS3/brightness
~ #

The push buttons are accessible via the /dev/input/eventX device, and they react on pressing as follows:

~ # evtest /dev/input/event1
Input driver version is 1.0.1
Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100
Input device name: "gpio-keys"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 148 (KEY_PROG1)
Event code 149 (KEY_PROG2)
Properties:
Testing ... (interrupt to exit)

Event: time 946685503.115766, type 1 (EV_KEY), code 148 (KEY_PROG1), value 1
Event: time 946685503.115766, -------------- SYN_REPORT ------------
Event: time 946685503.255746, type 1 (EV_KEY), code 148 (KEY_PROG1), value 0
Event: time 946685503.255746, -------------- SYN_REPORT ------------

Event: time 946685524.235749, type 1 (EV_KEY), code 149 (KEY_PROG2), value 1
Event: time 946685524.235749, -------------- SYN_REPORT ------------
Event: time 946685524.355743, type 1 (EV_KEY), code 149 (KEY_PROG2), value 0
Event: time 946685524.355743, -------------- SYN_REPORT ------------


Alternative Ways to Access GPIO

In Linux, you may access GPIOs using different approaches, not only the ones described in this application note above. Here are some external links that might be usefull if you decide to try an alternative approach.

The following article describes accessing GPIOs from the kernel context: https://lwn.net/Articles/532714/

To work with GPIOs from the user space, there are the following possibilities: