In Raspberry Pi land, there are a bunch of libraries and userspace tools to interact with GPIOs. Most of them are proprietary and work only for select SoCs made by Broadcom for Raspberry Pi. Many of them are not well designed architecturally and not well coded. Do not ask us to port any of these libraries or tools because they are a waste of time for everyone involved.
Another interface that is used to control the GPIOs is the sysfs interface. This interface exposes the /sys/class/gpio/export
and /sys/class/gpio/unexport
files which you can echo into to expose GPIOs and control them. This interface is deprecated and will be dropped in the future. We do not recommend continuing to use this interface.
libgpiod is the preferred C interface to interact with the Linux kernelâs GPIO subsystem. Every one of our boards feature GPIOs that can be controlled through this interface. It is well supported, stable, reliable, and well designed.
GPIOs are organized into banks. These banks can be different voltages. The Linux pinctrl subsystem controls the operations of these GPIO banks. The Linux pinctrl subsystem organizes and exposes these banks to userspace as /dev/gpiochipX
where a gpiochip can be a composite of multiple banks and individual GPIOs as lines.
Our libretech-wiring-tool offers a handy utility called lgpio. It allows you to quickly lookup the chip and line number of a specific pin on a specific header.
lgpio info HEADER PIN
Most of our boards feature a primary header so you can also leave out the header if you are looking up with pin number on the primary header.
lgpio info PIN
For example, we can lookup pin 3 on AML-S905X-CC Le Potato:
$ lgpio info 3
Chip Line sysfs Name Pad Ref Desc
0 5 506 GPIOAO_5 D13 I2C_SDA_AO I2C_SDA_AO // I2C_SLAVE_SDA_AO // UART_RX_AO_B
This provides us with all the fields of that pin. The fields are described as follows:
- Chip - the gpio chip number for libgpiod - /dev/gpiochipX
- Line - the gpio line number on the chip for libgpiod
- sysfs - the legacy gpio number for the deprecated sysfs interface - /sys/class/gpio
- Name - SoC GPIO name
- Pad - SoC physical pad
- Ref - Schematic Reference Name
- Desc - Pin Multiplex Functions
If all we care about is controlling the GPIOs via libgpiod, we can run the following to give us the chip and line numbers respectively:
$ lgpio info 3 gpiod
0 5
Every Linux distro may have a different version of the Python 3 libgpiod. The upstream repository is located here. Click on the version under branch that matches your distroâs version and then click tree, click bindings, click python, and click examples to see example scripts of using GPIOs.
- Ubuntu 22.04 - 1.6.x
- Ubuntu 20.04 - 1.4.x
- Debian/Raspbian 11 - 1.6.x
- Debian/Raspbian 10 - 1.2.x
gpioget.py
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of libgpiod.
#
# Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
#
'''Simplified reimplementation of the gpioget tool in Python.'''
import gpiod
import sys
if __name__ == '__main__':
if len(sys.argv) < 3:
raise TypeError('usage: gpioget.py <gpiochip> <offset1> <offset2> ...')
with gpiod.Chip(sys.argv[1]) as chip:
offsets = []
for off in sys.argv[2:]:
offsets.append(int(off))
lines = chip.get_lines(offsets)
lines.request(consumer=sys.argv[0], type=gpiod.LINE_REQ_DIR_IN)
vals = lines.get_values()
for val in vals:
print(val, end=' ')
print()
gpioset.py
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of libgpiod.
#
# Copyright (C) 2017-2018 Bartosz Golaszewski <bartekgola@gmail.com>
#
'''Simplified reimplementation of the gpioset tool in Python.'''
import gpiod
import sys
if __name__ == '__main__':
if len(sys.argv) < 3:
raise TypeError('usage: gpioset.py <gpiochip> <offset1>=<value1> ...')
with gpiod.Chip(sys.argv[1]) as chip:
offsets = []
values = []
for arg in sys.argv[2:]:
arg = arg.split('=')
offsets.append(int(arg[0]))
values.append(int(arg[1]))
lines = chip.get_lines(offsets)
lines.request(consumer=sys.argv[0], type=gpiod.LINE_REQ_DIR_OUT)
lines.set_values(values)
input()