Controlling GPIO in Linux |
This application note shows how to control i.MX8M GPIOs in Linux.
The generic GPIO interface is controlled by the CONFIG_GPIOLIB kernel option enabled by default in the Emcraft i.MX8M kernel. Most of the i.MX8M 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:
The pin multiplexing, as well as the GPIO specific configuration, is performed by the Linux kernel drivers using the information from the meta-emcraft/recipes-kernel/linux/linux-imx/imx8m-som.dts file. Let's edit this file and add the information about the above two GPIOs:
/ { After applying the above changes to the meta-emcraft/recipes-kernel/linux/linux-imx/imx8m-som.dts file, rebuild the device tree (Building Linux Kernel) and use it to boot the target.
Each GPIO is assigned a unique integer GPIO number within the GPIO chip range of 0 to 160 by Linux. To calculate that number for a specific GPIO, use the following formula: gpio = ((bank - 1) * 32) + pin Bank numbers start with 1 (corresponding to GPIO1, etc), pin numbers start with 0 (corresponding to pin 0, etc). For the User Push Button the specific pin is SAI2_RXFS (GPIO4_IO21), which corresponds to the following GPIO number: ((4 - 1) * 32) + 21 = 117 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 117 > /sys/class/gpio/export 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. We enabled pull-up for this GPIO in rootfs.dts.STM32F7 (see the S2.but node), so when the User Push Button unpressed this GPIO reads as 1: / # cat /sys/class/gpio/gpio117/value Push the button and make sure the GPIO value reads as 0: / # cat /sys/class/gpio/gpio117/value Release the button and validate that the value has returned to 1: / # cat /sys/class/gpio/gpio117/value For the User LED the specific pin is SAI5_RXFS (GPIO3_IO19), which corresponds to the following GPIO number: ((3 - 1) * 32) + 19 = 83 Export the GPIO and define it as an output: / # echo 83 > /sys/class/gpio/export 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/gpio83/value; sleep 1; echo 0 > /sys/class/gpio/gpio83/value; sleep 1; done Stop this test by pressing Ctrl-C, and run a composite test: control the User LED with the User Push Button (turn the LED on if the Button is unpressed, and turn the LED off if the Button is pressed): / # while [ 1 ]; do cat /sys/class/gpio/gpio117/value > /sys/class/gpio/gpio83/value; done
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. To work with GPIOs from the user space, there are the following possibilities:
Controlling GPIO from Kernel The following article describes accessing GPIOs from the kernel context: As an example of a device driver that makes use of the kernel GPIO APIs, refer to the device driver for the Goodix touch-screen controller. The device driver configures and uses a GPIO input for interrupt. The relevant device tree file is meta-emcraft/recipes-kernel/linux/linux-imx/imx8m-som-mipi-frd55.dts. Refer specifically to the goodix_ts@5d node and the goodix,irq-gpio property. The device driver itself is linux/drivers/input/touchscreen/gt1x/gt1x.c. Refer specifically to the gt1x_parse_dt(), gt1x_request_io_port(), and gt1x_request_irq() functions. |