Jetson nano gpio control in c

Hi there.

I’m trying to control nano gpio via c. (Nano 2G version)

I wrote simple code and run and it looks work but its output behavior is very strange to me.
Actually issue happens not all GPIO ports and some ports has strange behavior so I wonder what I missed in my code.

If I ran code via “main 12”, it toggles GPIO 12 and it looks good working and I think so.
If I ran code using other gpio, its output is very strange to me, “main 76”.
Its wave is like as below…


Actually it controls gpio but its level looks big noise.
Not all GPIOs are working like this and some are working like noise and some are normal.
So I wonder what I made wrong in my test code below.

Could you help me how to make it working good?

#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>

#define	CONSUMER	"con"

char *gpiod_nano_chip_name = "gpiochip0";
struct gpiod_chip *chip = NULL;
static struct gpiod_line *ioRed = NULL;

//#define LED_RED     216

int main(int argc, char* argv[])
{
    int ret = 0;
    int count = 10;

    int port = atoi(argv[1]);

    printf("Port %d opening\n", port);

    // GPIO Open
    chip = gpiod_chip_open_by_name(gpiod_nano_chip_name);
	if (!chip) {
		perror("Open chip failed\n");
		return -1;
	}
    
    // GPIO get each lines
    ioRed = gpiod_chip_get_line(chip, port);
	if (!ioRed) {
		perror("Get red led line failed\n");
		//gpiod_close();
        return -1;
	}

    // GPIO set direction
    gpiod_line_request_output(ioRed, CONSUMER, 0);

    gpiod_line_set_value(ioRed, 0);

    while(count--)
    {
        printf("IO set to high\n");        
        gpiod_line_set_value(ioRed, 1);
        sleep(1);

        printf("IO set to low\n");
        gpiod_line_set_value(ioRed, 0);
        sleep(1);
    }

    printf("Bye~~~\n");

    return 0;
}

hello user50457 ,

may I know what’s the actual use-case for toggle GPIO pins like that?
could you please have a try by using standard APIs to access GPIOs from kernel side.
for example,
$L4T_Sources/r32.6.1/Linux_for_Tegra/source/public/kernel/kernel-4.9/include/linux/gpio.h

static inline int gpio_get_value(unsigned int gpio)
{
        return __gpio_get_value(gpio);
}

static inline void gpio_set_value(unsigned int gpio, int value)
{
        __gpio_set_value(gpio, value);
}

Hello JerryChang.

I couldn’t make it work with your suggestion, there were lots of errors due to path issues.

So I have tried sysfs to control GPIOs and have same results.
GPIO12 is working normally and GPIO76 works like a noise.
Could you guide how to make it works with your recommended APIs?
(seems to be path issue but still couldn’t make it work…)

My test code with sysfs is below.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define LED_GPIO_DIR "/sys/class/gpio"

int main()
{
    int  led_gp,value, i;
    char buff[256];
    FILE *led_gpio;
    
    printf("input gpio number : \n");

    scanf("%d",&led_gp);

    snprintf(buff,sizeof(buff),"%s/export",LED_GPIO_DIR);
    led_gpio = fopen(buff,"w");
    fprintf(led_gpio,"%d\n",led_gp);
    fclose(led_gpio);

    snprintf(buff,sizeof(buff),"%s/gpio%d/direction",LED_GPIO_DIR,led_gp);
    led_gpio = fopen(buff,"w");
    fprintf(led_gpio,"out\n");
    fclose(led_gpio);

    snprintf(buff,sizeof(buff),"%s/gpio%d/value",LED_GPIO_DIR,led_gp);
    led_gpio = fopen(buff,"w");
    setvbuf(led_gpio,NULL,_IONBF,0);

    value = 0;
    for(i=0;i<=10;i++)
    {
        fprintf(led_gpio,"%d\n",value);
        usleep(100);
        value = !value;
    }
    fclose(led_gpio);

    snprintf(buff,sizeof(buff),"%s/unexport",LED_GPIO_DIR);
    led_gpio = fopen(buff,"w");
    fprintf(led_gpio,"%d\n",led_gp);
    fclose(led_gpio);

    return 0;
}

hello user50457,

may I know what the failures shown?
it’s the kernel layer codes, and you should refer to similar GPIO controls for reference,
thanks

Hi JerryChang.

Thanks for your help.

I wrote below example to test what you recommended and got errors which are relates with path or config issue.
I tried to fix it but I couldn’t make it.

//#include </usr/src/linux-headers-4.9.253-tegra-ubuntu18.04_aarch64/kernel-4.9/include/linux/gpio.h>
#include <linux/gpio.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    int count = 10;
    int port = atoi(argv[1]);
    int pNum = 0;

    printf("Port %d opening\n", port);

    pNum = gpio_reqeust(port, "io");
    if(pNum < 0)
    {
        perror("io port request error\n");
        return -1;
    }

    pNum = gpio_direction_output(port, 0);
    printf("io initialized to output port\n");

    while(count--)
    {
        printf("IO set to high\n");        
        gpio_set_value(pNum, 1);
        sleep(1);

        printf("IO set to low\n");
        gpio_set_value(pNum, 0);
        sleep(1);
    }

    printf("Bye~~~\n");

    return 0;
}
tempus@tempus-desktop:~/Work/nano_gpio$ gcc io.c -o io
io.c: In function ‘main’:
io.c:15:12: warning: implicit declaration of function ‘gpio_reqeust’ [-Wimplicit-function-declaration]
     pNum = gpio_reqeust(port, "io");
            ^~~~~~~~~~~~
io.c:22:12: warning: implicit declaration of function ‘gpio_direction_output’ [-Wimplicit-function-declaration]
     pNum = gpio_direction_output(port, 0);
            ^~~~~~~~~~~~~~~~~~~~~
io.c:28:9: warning: implicit declaration of function ‘gpio_set_value’ [-Wimplicit-function-declaration]
         gpio_set_value(pNum, 1);
         ^~~~~~~~~~~~~~
/tmp/ccY5h0MK.o: In function `main':
io.c:(.text+0x50): undefined reference to `gpio_reqeust'
io.c:(.text+0x80): undefined reference to `gpio_direction_output'
io.c:(.text+0xac): undefined reference to `gpio_set_value'
io.c:(.text+0xcc): undefined reference to `gpio_set_value'
collect2: error: ld returned 1 exit status

hello mr.Louie,

there’re undefined reference compile failure.
did you access Jetson Linux | NVIDIA Developer to download the L4T sources package?
please refer to Kernel Customization session for the steps to build the NVIDIA kernel.

BTW,
it’s using of_get_named_gpio() to get the gpio via device tree.
you may also check camera reference driver, kernel/nvidia/drivers/media/i2c/ov5693.c for the demonstration.
thanks

My friend, the functions in $L4T_Sources/r32.6.1/Linux_for_Tegra/source/public/kernel/kernel-4.9/include/linux/gpio.h are kernel api to control gpios, the functions can only be used in drivers or kernel codes(kernelspace), they cannot be used in userspace, .
The codes from mr.Louie are test codes for gpios, it is running in userspace, you have used libgpiod and sysfs to control gpios,these both are correct ways to control gpios.
The reason why did gpios output strange wave, I think it may due to the pinmux config in dtb file.The default configuration for GPIO12 is gpio , so you can control it correctly.I do not know which pin “76” is and what its default pinmux configuration is. You should check the pinmux configuration in dtb files.

2 Likes

Hi Yangchuan.

Thanks for your guide, I’ll check dtb and try again.
Many thanks.