GPIO Programming on Embedded Linux

Aug 8, 2020


I have not been updating my blogs for a long time since I was caught up in a lot of personal matters. I wanted to put some instructions for programming GPIO pins on embedded systems. I will do it today.


1. CPU-controlled GPIO

The CPU-controlled GPIO pins are so easy to use if you already have a Linux booted. This is common for all the embedded processors. If some of the pins coming from the CPU are connected to GPIO devices, the general steps to use are:

  1. Export the pin.

  2. Set the pin direction (input or output).

  3. If an output pin, set the level to low or high.

  4. If an input pin, read the pin's level (low or high).

  5. When done, unexport the pin.

This looks easy, doesn't it? The real challenge you may face, however, is to know the GPIO pin number in your system. Usually this number can be found using the following method:

ls /sys/class/gpio

Suppose the result looks like the following:

export gpiochip89@ gpiochip300@ unexport

Then you know the GPIO base number is either 89 or 300. You can go to each individual one to check which GPIO chip is the one you really care about. Suppose gpiochip300 is the one you want, now you will have to add your own GPIO offset to this base number. Let's say out of many GPIO pins available on PS, we want GPIO 30 to be an output. This means the GPIO pin number is (300+30)=330.

Finally you have:

echo 330 > /sys/class/gpio/export

echo 'out' > /sys/class/gpio/gpio330/direction

echo 1 > /sys/class/gpio/gpio330/value

After this the corresponding GPIO pin will be pulled up high.

One question: why did you see more than 1 GPIO chip in the above steps? The short answer is that there might be other devices mapped as GPIO device in the Linux device tree. As long as you have them as GPIO devices, you can use the above steps to control them.

2. AXI GPIO

For Zynq/Zynq Ultrascale devices, there is an additional type of GPIO that you can use: AXI GPIO. Compared to the CPU-controlled GPIO, you need to build a block design with the AXI GPIO controller in it:

For the gpio_rtl pin, you can constrain it using *.xdc file so they are tied to specific pins (like LEDs, push buttons, or switches) on your board. AXI GPIO is memory-mapped so you can use Memory-Mapped IO (MMIO) to control the GPIO pin in the above block design.