How to Use GPIO on Torizon OS
Introduction
This article presents the essential steps for using GPIO on Torizon OS devices. It does not describe how to customize Torizon OS for using GPIO pins that require any device tree modification. If you want to change pin functionalities, refer to the Pin Multiplexing - Changing Pin Functionalities in the Linux Device Tree article. If your image is already customized to make the GPIO pin available, the instructions from this article are also valid.
After reading this guide, you will be able to incorporate GPIO into your application. This article covers the following topics:
- Check the available GPIO pins in your carrier board
- Test GPIO pins
- Use GPIO inside containers
- Build and run sample applications
This article complies with the Typographic Conventions for Toradex Documentation.
Can I use GPIO user space SysFS?
The Kernel Linux has deprecated GPIO user space SysFS. However, the kernel config CONFIG_GPIO_SYSFS
is still enabled on Toradex's BSP to support customers using it in their legacy applications. You can check the configuration by running zcat /proc/config.gz | grep CONFIG_GPIO_SYSFS
. For GPIO access from userspace, the new char device API, also known as libgpiod, must be used.
For detailed information on using the command-line tools and the C API, refer to GPIO (Linux).
Torizon OS supports various non-generic features such as GPIO power management keys, GPIO power off, GPIO LED and others explained in GPIO (Linux).
What is libgpiod?
The libgpiod library provides a straightforward API that encapsulates the complexities of the Operating System, including ioctl calls and data structures for working with GPIO. Additionally, the libgpiod project offers a set of command-line tools for GPIO manipulation from the command line. These tools can be used as replacements for scripts previously based on the deprecated sysfs API. They can be helpful for quickly verifying if the targeted GPIO pins are available to your application.
The new user space API uses the /dev/gpiochip
devices through Operating System calls to manage GPIOs:
# ls /dev/gpiochip*
/dev/gpiochip0 /dev/gpiochip2 /dev/gpiochip4 /dev/gpiochip6
/dev/gpiochip1 /dev/gpiochip3 /dev/gpiochip5 /dev/gpiochip7
Each entry on the /dev/gpiochip
corresponds to a GPIO bank that the operating system has access to.
Prerequisites
- A Toradex Computer on Module with Torizon OS installed
- A configured build environment, as described in the Configure Build Environment for Torizon OS Containers article
Pin Standardization
On Torizon OS, the GPIO pins are named based on the module's edge connector type. Verdin and Colibri modules use the name SODIMM
for GPIO pins, while Apalis modules use MXM3
. This naming convention simplifies pin identification and usage, allowing users to refer to pins by name instead of bank and line. Follow the next steps to identify and test GPIO pins.
Find Available GPIO Pins
This section provides a step-by-step guide on how to identify available GPIO pins of a SoM and locate the corresponding connector on both the SoM and the carrier board.
1. Identify SODIMM/MXM3 Pins on Modules
Each SoM offers multiple dedicated GPIO pins. Some of those are reserved for other interfaces. Additionally, several modules' pins can be used as GPIO if their primary function is not in use. To ensure compatibility across modules, prioritize the utilization of dedicated GPIO pins.
Refer to the GPIO section of the SoM's datasheet for information on available GPIO pins. If you are performing a quick evaluation, you can select a GPIO pin directly available on a carrier board connector, as explained in the next section.
The following example shows the GPIO table for the Verdin iMX8M Plus.
Also, ensure that the chosen pin is not reserved for any other interfaces (which is the case for pin 216 in the above example).
Using GPIO pins other than the dedicated requires device trees modification. However, this is not covered in this article. If you need to modify the device tree to use GPIO pins, refer to the Pin Multiplexing - Changing Pin Functionalities in the Linux Device Tree article.
2. Identify GPIO Pins on the Carrier Board
Refer to your carrier boards' datasheet or schematic and identify a SODIMM/MXM3 Pin connected to the GPIO interface and available through a connector on the carrier board.
For instance, you can find valuable information in the Verdin Development Board datasheet. In the IO pin configuration table you will find the GPIO pins, SODIMM pins, and signal names available through the X5 connector:
3. Record the Pin Details
Once you have selected a GPIO pin, write down its SODIMM/MXM3 Pin, and the corresponding connector.
The relevant information for the GPIO_3
pin is listed below:
- Connector location: X5
- SODIMM Pin: 210
Hardware Setup to Test a GPIO Pin
In this section, you will learn how to setup the hardware for testing GPIO pins.
1. Locate the GPIO Pin on Your Carrier Board
The carrier board's datasheet or schematic can help you to locate the GPIO pin. Alternatively, you can directly search for the GPIO pin using the labels on your carrier board.
The image below shows the GPIO_3
connector location on the Verdin Development Board.
2. Prepare your Testbed
To test the GPIO pin, you can utilize either a multimeter or an LED to verify the logic level of the connector. When using an LED, ensure you match the voltage and current of both the LED and the GPIO pin. If necessary, consider using a driver circuit to power the LED correctly.
The Verdin Development Board already provides LEDs with driver circuits for quick evaluation.
Thus, we can directly connect the GPIO pin to the carrier board's LED interface.
The TTL level for Colibri and Apalis I/O is 3.3V, while for Verdin is 1.8V. Do not apply 3.3V signals to Verdin I/O.
Test GPIO Pins from a Container
In this section, you will learn how to make the GPIO pin accessible from a Docker container. Then, you will check if the pin works as expected before using it in your application.
1. Run the Toradex Pre-built Container
Toradex provides a pre-built container with libgpiod installed, which enables you to confirm that the GPIO pin is working as expected.
To download the image and build the container for testing, run the following command on the board's terminal:
# docker run --rm -it -v /dev:/dev --device-cgroup-rule='c 254:* rmw' torizonextras/arm64v8-gpiod
To download the image and build the container for testing, run the following command on the board's terminal:
# docker run --rm -it -v /dev:/dev --device-cgroup-rule='c 254:* rmw' torizonextras/arm32v7-gpiod
2. Ensure Access to the GPIO Pin from the Container
Take note of its bank and line, as they will be needed for testing using libgpiod
commands, such as gpioset
.
# gpiofind <SODIMM/MXM3_PIN>
For instance, you would get the following output for SODIMM_210
of the Verdin Development Board:
It means that our pin is located at bank 0 and line 5.
If you are experiencing difficulties finding a GPIO pin, you can alternatively execute the command provided below and manually search for the pin.
# gpioinfo
3. Toggle the GPIO Pin
Change the logic level of the pin and verify if it works as expected.
# gpioset <bank> <line>=<logic_level>
For example, we could turn the LED on by running the following command.
# gpioset 0 5=1
Command-line Tools Usage
After launching the container, you can run any libgpiod command inside the container. For detailed information, refer to the section Command Line Tools on GPIO (Linux).
Best Practices for Production
Use SODIMM/MXM3 Pin Names
Although it is acceptable to use bank and line for testing, using the SODIMM/MXM3 Pin names helps you to simplify your code. SODIMM/MXM3 Pin names are also guaranteed to not change during Torizon/BSP upgrades, minimizing impact of OS upgrades on your application.
Specify Accessible Devices within the Container
To test the GPIO pin, we provided container access to all GPIO banks using the --device-cgroup-rule='c 254:* rmw'
flag. However, it is recommended to only share the required banks with the container using the --device
flag when in production. For example:
# docker run --rm -it --device /dev/gpiochip0 <yourDockerHubUsername>/<DockerHubRepository>
If the container needs to access multiple GPIO banks, you will need to specify the --device
argument multiple times, as shown in the following example:
# docker run --rm -it --device /dev/gpiochip0 --device /dev/gpiochip1 --device /dev/gpiochip2 <yourDockerHubUsername>/<DockerHubRepository>
Use GPIO as Non-root User
A best practice for Dockerfile is to run containers as non-root users. This approach ensures that containers only have the necessary permissions. In this case, you will have to add the user to the GPIO group adding the following command to your Dockerfile:
RUN usermod -a -G gpio torizon
Dockerfile example
ARG BASE_NAME=debian
# Image for arm64 architecture
ARG IMAGE_ARCH=linux/arm64/v8
# Image for arm architecture
#ARG IMAGE_ARCH=linux/arm/v7
ARG IMAGE_TAG=3-bookworm
ARG DOCKER_REGISTRY=torizon
FROM $DOCKER_REGISTRY/$BASE_NAME:$IMAGE_TAG
RUN apt-get -y update && apt-get install -y --no-install-recommends \
gpiod \
&& apt-get clean && apt-get autoremove && rm -rf /var/lib/apt/lists/*
# Allow the user torizon use GPIOs
RUN usermod -a -G gpio torizon
# Add sample bash scripts for convenience
COPY ./*.sh /usr/local/bin/
# Run the container using the torizon user
USER torizon
CMD [ "bash" ]
C Language Examples
This section illustrates how to use C API from libgpiod. Pre-built containers are not provided, therefore you are encouraged to build your own.
1. Clone the Torizon Samples Repository
First, clone the torizon-samples repository into your development PC:
$ git clone https://github.com/toradex/torizon-samples.git
$ cd torizon-samples/gpio
Then, you will build, deploy and run the application container, as explained in the next sections.
2. Build the Docker Image With the C Samples
In this section, you will compile all the C examples and build a container image that can be easily deployed to the board.
Dockerfile of the sample
Assuming you have cloned the torizon-samples repository as described in the Software Requirements, you can modify and rebuild the image on your development PC.
Select your SoM from the tabs below:
To begin, build the container image.
$ docker build --build-arg CROSS_TC_IMAGE_ARCH=arm64 --build-arg GCC_PREFIX=aarch64-linux-gnu --build-arg IMAGE_ARCH=linux/arm64 -t <yourDockerHubUsername>/arm64v8-c-gpiod .
Upload the generated image to your Docker Hub:
$ docker login
$ docker push <yourDockerHubUsername>/arm64v8-c-gpiod
After that, on the board's terminal, run the following command to pull the image from Docker Hub:
# docker pull <yourDockerHubUsername>/arm64v8-c-gpiod
To begin, build the container image.
$ docker build -t <yourDockerHubUsername>/arm32v7-c-gpiod .
Upload the generated image to your Docker Hub:
$ docker login
$ docker push <yourDockerHubUsername>/arm32v7-c-gpiod
After that, on the board's terminal, run the following command to pull the image from Docker Hub:
# docker pull <yourDockerHubUsername>/arm32v7-c-gpiod
The following sections will guide you through running C samples using the containers you previously built.
3. How to Toggle a GPIO
Run the gpio-toggle application example, which is available in the previously built and deployed container. Choose your SoM architecture from the tabs below:
This example continuously toggles the GPIO_3
of the Verdin Development Board:
# docker run --rm -it --device /dev/gpiochip0 <yourDockerHubUsername>/arm64v8-c-gpiod
## gpio-toggle SODIMM_210
This example continuously toggles the GPIO_1
of the Aster Carrier Board:
# docker run --rm -it --device /dev/gpiochip0 <yourDockerHubUsername>/arm32v7-c-gpiod
## gpio-toggle SODIMM_45
4. Read GPIO Using Events (Interrupt Driven)
Run the gpio-event application example, which is available in the previously built and deployed container. Choose your SoM architecture from the tabs below:
This example uses GPIO_1
of the Verdin Development Board as input and GPIO_2
as output. It means the application waits for rising edges on GPIO_1
and then toggles the GPIO_2
.
# docker run --rm -it --device /dev/gpiochip0 <yourDockerHubUsername>/arm64v8-c-gpiod
## gpio-event SODIMM_206 SODIMM_208
This example uses GPIO_1
of the Aster Carrier Board as input and GPIO_2
as output. It means the application waits for rising edges on GPIO_1
and then toggles GPIO_2
.
# docker run --rm -it --device /dev/gpiochip0 <yourDockerHubUsername>/arm32v7-c-gpiod
## gpio-event SODIMM_45 SODIMM_67
Next Steps
This article presented the first steps for using GPIO on Torizon OS devices. To support your next steps, Toradex provides comprehensive documentation that will enhance your experience of embedded application development. We recommend exploring the following articles:
- How to enable Peripheral Access for other devices and interfaces
- Deploy Container Images to Torizon OS
- What is the Torizon IDE Extension 2 for Visual Studio Code