How access GPIO pins using IOCTL functions?

Hello All,

I am using IVY Carrier board with iMX8M plus SOM, I did all development setup and also able to run the sample code using local docker setup.

The following GPIO toggle code i created to toggle LED on carrier board:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>

int main() {
    const char *chipname = "/dev/gpiochip2";  // GPIO chip device
    int line = 25;                            // GPIO line number (adjust for your board)
    int fd, ret;

    printf("GPIO Example Started\n");

    // Open GPIO chip
    fd = open(chipname, O_RDONLY);
    if (fd < 0) {
        perror("Failed to open gpiochip device");
        return EXIT_FAILURE;
    }

    // Request line
    struct gpiohandle_request req;
    memset(&req, 0, sizeof(req));
    req.lineoffsets[0] = line;    // which GPIO line
    req.flags = GPIOHANDLE_REQUEST_OUTPUT;  // request as output
    req.lines = 1;                // number of lines requested
    req.default_values[0] = 0;    // initial value (LOW)
    strcpy(req.consumer_label, "my-gpio-app");

    ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
    if (ret == -1) {
        perror("Failed to request line");
        close(fd);
        return EXIT_FAILURE;
    }

    // Toggle GPIO value
    struct gpiohandle_data data;
    data.values[0] = 1;  // set HIGH
    ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
    if (ret == -1) {
        perror("Failed to set line value HIGH");
    }
    sleep(5);

    data.values[0] = 0;  // set LOW
    ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
    if (ret == -1) {
        perror("Failed to set line value LOW");
    }
    sleep(5);

    // Release line handle
    close(req.fd);
    close(fd);

    printf("GPIO %d toggled successfully\n", line);
    return EXIT_SUCCESS;
}

This code successfully compile and ran without ERRORs but not able to see the GPIO pin actually toggle.

The console log shows:

Could you please help me to address out where i am wrong? Is it required to modify device tree?

Thanks,

Vishal

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello Vishal,

Your code looks correct, but the issue is likely that the GPIO pin needs to be properly configured for GPIO functionality through the device tree. On i.MX 8M Plus based modules, pins need to be explicitly muxed to GPIO function before they can be used as GPIOs (1).

Pin Configuration Requirements

For i.MX 8M Plus based modules, you need to configure the pin multiplexing in the device tree (1). The pin control configuration requires defining a device tree node inside the pin controller node with the fsl,pins property (1).

Device Tree Configuration Steps

  1. Create a custom device tree overlay to configure GPIO2_25 for GPIO functionality (2):
/dts-v1/;
/plugin/;

#include "imx8mp-pinfunc.h"

/ {
    compatible = "toradex,verdin-imx8mp";
    
    fragment@0 {
        target = <&iomuxc>;
        __overlay__ {
            pinctrl_gpio2_25: gpio2_25grp {
                fsl,pins = <
                    /* Replace with correct pin definition for GPIO2_25 */
                    MX8MP_IOMUXC_[PIN_NAME]__GPIO2_IO25 0x1c4
                >;
            };
        };
    };
    
    fragment@1 {
        target = <&gpio2>;
        __overlay__ {
            pinctrl-names = "default";
            pinctrl-0 = <&pinctrl_gpio2_25>;
        };
    };
};
  1. Identify the correct pin definition by checking the i.MX 8M Plus Applications Processor Reference Manual and the pin function definitions in imx8mp-pinfunc.h (1).

Pin Control Settings

The recommended pad configuration value 0x1c4 provides weak pull-up configuration (1). For GPIO applications, you can also use 0x184 for weak pull-down if needed (1).

Alternative Approach

If you only need to set the pin direction and don’t want to use gpio-hog in the device tree, you can configure just the pinmux in the overlay and then control the direction from your application (3). This approach requires:

  1. Configure only the pinmux in the device tree overlay
  2. Use your existing C code to control the GPIO direction and value

Verification Steps

After applying the device tree overlay:

  1. Check if the GPIO is properly exported: ls /sys/class/gpio/
  2. Verify the pin configuration with a multimeter or oscilloscope
  3. Ensure no other peripherals are using the same pin

The key issue is that without proper device tree configuration, the pin remains in its default function and cannot be controlled as a GPIO (1).

Best regards, Toradex AI Assistant.

Hey @vishalborle92,

Can you let me know which pin (SODIMM number) you are expecting the value change to be on? Can you validate this sodimm number to your gpiochip and line number?

Thanks @eric.tx For you response..!!

I am trying to toggle pin SODIMM_30 which is line 25. I already referred same document that you suggested.

When i am trying to toggle pin using gpioset =<logic_level> but still nothing happen no any ERROR shows.

gpioset 2 25=1
gpioset 2 25=0

But this is not working.

Thanks,

Vishal

Hey @vishalborle92,

For SODIMM_30, this pin, while can be for GPIO4.io[25], by the device tree is currently set to sai2.TX_BLK.

You would need to disable the SAI2 node, and enable this gpio node for getting it to work.

What might be easier is if you use a gpio that is already dedicated, like SODIMM 206, 208, 210 or 212.

-Eric

Thanks @eric.tx for your suggestion to get correct me. Now If I used SODIMM 208 then it working as expected. If i want to modify device tree which steps i need to follow? As I am new in Linux could you please provide me reference tutorial step by step that i will execute from my side.

I want to blink Status LED that connected on IVY board.

Hey @vishalborle92,

Glad I could help!

We have our developer.toradex.com website if you are not familiar, we have quite a bit of guides, including a “first steps” with device trees. Here is the link.

For modifying the device tree for our linux based Torizon OS. I would actually mention something called device tree overlays, theses are device tree modifications that happen after boot. We have a tool we build called “torizoncore-builder” that allows for device tree overlays to be easily integrated into a customized Torizon OS.

This is the overview for the builder tool. And on the left you can see menu drop downs that will walk you through (1) Installing the tool (2) customizing the OS framework/source files (3) configuration files (where you can do Overlays.