GPIO pin/line state is resetting to “low” after reading the state

The GPIO pin/line state is resetting to “low” after reading the state. We are using userspace gpio tools. Here is the scenario.

  • Set GPIO mode to output.
  • Set GPIO to HIGH.
  • The scope is reading state HIGH
  • Read the GPIO state.
  • The scope is reading state LOW.

Doesn’t the new iotcl-based interface resets the state of the GPIO to its default after the descriptor is closed?

Which in my opinion makes this interface useless for most embedded applications, at least without a persistent service or some such. For now we’re relying on the deprecated old sysfs-based interface, which we’ve brought back in Ubuntu 22.04’s kernel.

I tested that too. unfortunately, there is no change in voltage on the scope even before closing the descriptor.

More detailed description:

Environment:
Device: Jetson Orin nano
Software:
PRETTY_NAME=“Ubuntu 22.04.5 LTS”
NAME=“Ubuntu”
VERSION_ID=“22.04”
VERSION=“22.04.5 LTS (Jammy Jellyfish)”
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL=“https://www.ubuntu.com/
SUPPORT_URL=“https://help.ubuntu.com/
BUG_REPORT_URL=“Bugs : Ubuntu
PRIVACY_POLICY_URL=“Data privacy | Ubuntu and Canonical Legal | Ubuntu
UBUNTU_CODENAME=jammy


I made a test program with libgpiod library to test the behavior of the gpio line before and after the closing of gpio descriptor.

Here is the code:

#include <gpiod.h>                                                                                                                                                                                                                      
#include <stdio.h>                                                                                                                                                                                                                      
#include <stdlib.h>                                                                                                                                                                                                                     
#include <unistd.h>                                                                                                                                                                                                                     
                                                                                                                                                                                                                                        
void usage (void)                                                                                                                                                                                                                       
{                                                                                                                                                                                                                                       
        printf("gpio-pulse chipname line pulse_count\n");                                                                                                                                                                               
}

int main(int argc, char **argv)
{
        char *chipname = argv[1];
        unsigned int line_num = strtol(argv[2], NULL, 10);
        unsigned int count = strtol(argv[3], NULL, 10);
        unsigned int val;
        struct gpiod_chip *chip;
        struct gpiod_line *line;
        int i, ret;

        if (argc < 4) {
                fprintf(stderr, "Invalid number of arguments\n");
                usage();
                ret = -1;
                goto end;
        }

        chipname = argv[1];
        line_num = strtol(argv[2], NULL, 10);
        count = strtol(argv[3], NULL, 10);
        chip = gpiod_chip_open_by_name(chipname);
        if (!chip) {
                perror("Open chip failed\n");
                goto end;
        }

        line = gpiod_chip_get_line(chip, line_num);
        if (!line) {
                perror("Get line failed\n");
                goto close_chip;
        }

        ret = gpiod_line_request_output(line, "gpio-pulse", 0);
        if (ret < 0) {
                perror("Request line as output failed\n");
                goto release_line;
        }

        val = 0;
        for (i = count; i > 0; i--) {
                ret = gpiod_line_set_value(line, val);
                if (ret < 0) {
                        perror("Set line output failed\n");
                        goto release_line;
                }
                printf("Output %u on line #%u\n", val, line_num);
                sleep(1);
                val = !val;
        }

        printf("Done generating pulses. Press any key to quit...\n");
        getchar();

release_line:
        gpiod_line_release(line);
close_chip:
        gpiod_chip_close(chip);
end:
        return ret;
}

Compile commands:

gcc gpio-pulse.c -o gpio-pulse -lgpiod

Usage:

./gpio-pulse <chip name> <line number> <number of pulses>
# exmple to generate 16 pulses on gpiochip0 line 105
./gpio-pulse gpiochip0 105 16

I tested several gpio lines with this program and I attached external logic analyzer on those pins. I didn’t see any voltage change on the logic analyzer during the program execution.

Note: The sysfs interface is deprecated and disabled in jetpack 6. So, I cannot test the gpios via sysfs interface.

Hi harsha.manam,

Are you using the devkit or custom board for Orin NX?
What’s the Jetpack version in use?

Are you trying to control PQ.05?
If so, please try running the following command to keep its state.

# gpioset --mode=wait `gpiofind "PQ.05"`=1

Please note that gpioget may configure the pin as Input.
You can simply run the following command to check.

# gpioget `gpiofind "PQ.05"`
# gpioinfo|grep "PQ.05"

Have you configured this pin as Output/Drive 1 in pinmux spreadsheet before use?

HI @harsha.manam

Sorry to go on a tangent. It’s true sysfs interface is deprecated and not available in Jetpack 6’s kernel binary. But for what’s worth, we’ve re-compiled the kernel enabling it, plus more stuff we need, without any issue. Long term we’ll have to move to the ioctl interface, but this is buying us much needed time.