Controlling GPIO from Linux User Space Print

This application note shows how to control the i.MX RT1060 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. Most of the i.MX RT1060 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 two pins as GPIO:

  • GPIO_AD_B1_11 (GPIO1[27]) - this pin is connected to the J23.2 pin on J23 connector on the NXP i.MX 1060RT EVK board and can be used as a GPIO Input
  • GPIO_AD_B0_09 (GPIO1[9]) - this pin is connected to the D18 User LED on the NXP i.MX 1060RT EVK board and, as such, can be used as a GPIO 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.IMXRT106X_NXPEVK file. Let's edit this file and add the information about the above two GPIOs:

  • Update the pinctrl_leds and pinctrl_gpio_key nodes with the information about specific (e.g. pull-up, alt mux, ...) settings of the used GPIOs.
  • Update the leds and gpio-keys nodes, and specify GPIOs which will be used with them.
  • The result should look like this:

pinctrl_leds: ledsgrp { fsl,pins = < MXRT105X_PAD_AD_B0_09_GPIO1_IO09 MXRT105X_PAD_CFG_GPIO >; }; pinctrl_gpio_key: gpiokeygrp { fsl,pins = < MXRT105X_PAD_AD_B1_11_GPIO1_IO27 MXRT105X_PAD_CFG_GPIO >; }; leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_leds>; #if 0 /* Disable binding to the LEDs driver */ user-led { gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; retain-state-suspended; default-state = "off"; }; #endif gpio-keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio_key>; #if 0 button_0 { label = "Button 0"; gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; linux,code = <KEY_A>; }; #endif };

After applying the above changes to the rootfs.dts.IMXRT106X_NXPEVK file, rebuild the rootfs project (Building Linux) and install it on the target (Installing Linux Images to SD Card).

Testing GPIO

Each GPIO is assigned a unique integer GPIO number within the GPIO chip range of 0 to 142 by Linux. To calculate that number for a specific GPIO, use the following formula:

gpio = bank_base + pin

Where the bank_base value is taken from gpioX nodes of the .dts file. For example:

gpio number for GPIO5.0 will be 128 + 0 = 128 (see gpio-ranges property for gpio5 node)
gpio number for GPIO3.4 will be 64 + 4 = 68 (see gpio-ranges property for gpio3 node)

The J23.2 input used in this note is connected to GPIO1[27], which corresponds to the following GPIO number:

0 + 27 = 27

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

/ # echo 27 > /sys/class/gpio/export
/ # echo in > /sys/class/gpio/gpio27/direction

Now, all is ready to read the value from the J23.2 pin. First, leave the J23.2 pin unconnected and read the signal. We enabled pull-up for this GPIO in rootfs.dts.IMXRT106X_NXPEVK (see MXRT106X_PAD_CFG_GPIO definition in the pinctrl_gpio_key node), so when the pin is not connected this GPIO reads as 1:

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

Now connect J23.2 to GND (e.g. to J21.12) and make sure the GPIO value reads as 0:

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

Remove connection of J23.2 from GND and validate that the value has returned to 1:

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

For the User LED the specific pin is GPIO1[9], which corresponds to the following GPIO number:

0 + 9 = 9

Export the GPIO and define it as an output:

/ # echo 9 > /sys/class/gpio/export
/ # echo out > /sys/class/gpio/gpio9/direction

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

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

Stop this test by pressing Ctrl-C, and run a composite test: control the User LED with the J23.2 (turn the LED off if the J23.2 is not connected to GND, and turn the LED on if the J23.2 is connected to GND):

/ # while [ 1 ]; do cat /sys/class/gpio/gpio27/value > /sys/class/gpio/gpio9/value; done


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