This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

J722SXH01EVM: How to modify GPIO attributes in user space application?

Part Number: J722SXH01EVM
Other Parts Discussed in Thread: SK-TDA4VM

Tool/software:

Hi,

I can set the direction of a GPIO in the terminal by directly writing to the GPIO_DIRXX register:

# set direction of GPIO0_15, 17, 19, 21 to output
root@j722s-evm:~# devmem2 0x00600010 w 0xFFD757FF
/dev/mem opened.
Memory mapped at address 0xffffaa850000.
Read at address  0x00600010 (0xffffaa850010): 0xFFFFFFFF
Write at address 0x00600010 (0xffffaa850010): 0xFFD757FF, readback 0xFFD757FF

In the sysfs interface, I can do that in an application by writing to the direction directory.

...
snprintf(buffer, sizeof(buffer), "/sys/class/gpio/gpio%d/direction", gpio);
gpioSysDir = open(buffer, O_WRONLY);
write(gpioSysDir, "out", strlen("out"));
...

How can I do the same (writing to GPIO_DIRXX, GPIO_SET_FAL_TRIGXX, etc..), in an application using the chardev interface?

Thank you,

Jin

  • Hi Jin,

    We do not have expertise in that. I recommend checking with 

    linux-gpio@vger.kernel.org

    Thanks,
    Keerthy

  • Hi Keerthy,

    It seems like that the included gpio-utils library can be used with the kernel interrupt. Tested with the included gpio-hammer example.

    Tested on SK-TDA4VM example:

    #include <stdio.h>
    #include <fcntl.h>
    #include <linux/gpio.h>
    #include <sys/ioctl.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    
    #include "gpio-utils.h"
    
    #define GPIO_CHIP "gpiochip0"
    #define GPIO_LINE_NUMBER 52
    
    int main() {
    /*
        int fd, ret;
        unsigned int lines[1] = {GPIO_LINE_NUMBER};
    	struct gpio_v2_line_request req;
        struct gpio_v2_line_values values;
    
        fd = open(GPIO_CHIP, O_RDWR);
        if (fd < 0) 
        {
            perror("Failed to open GPIO chip");
            return -1;
        }
        printf("Debug: fd after open(): %d\n",fd);
    
        memset(&req, 0, sizeof(req));
    
        req.offsets[0] = GPIO_LINE_NUMBER;
        req.config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
        strcpy(req.consumer, "gpio_test");
        req.num_lines = 1;
    
        ret = ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req);
        if (ret < 0)
            perror("Failed to request GPIO line");
        
        printf("Debug: fd after get_line: %d\n", fd);
        printf("Debug: Offsets: %d\n", req.offsets[0]);
    
        memset(&values, 0, sizeof(values));
        values.mask = 0;
        values.bits = 0;
    
        printf("Debug: Mask: %llu\n", values.mask);
        printf("Debug: Bits: %llu\n", values.bits);
    
        ret = ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values);
        if (ret < 0)
            perror("Failed to set GPIO line low");
    
        sleep(1);
    
        values.bits |= _BITULL(0);
        printf("Debug: Bits: %llu\n", values.bits);
    
        ret = ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values);
        if (ret < 0)
            perror("Failed to set GPIO line high");
    */
    /* Using gpio-utils */
        struct gpio_v2_line_values values;
        struct gpio_v2_line_config config;
        unsigned int lines[1] = {GPIO_LINE_NUMBER};
        int fd;
        int ret;
        memset(&config, 0, sizeof(config));
    
        //config.flags = GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_EDGE_RISING;
        config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
    
    	ret = gpiotools_request_line(GPIO_CHIP, lines, 1,
    				     &config, "gpio-test");
    	if (ret < 0)
    		perror("Unable to request GPIO line");
    	else
    		fd = ret;
    
    	values.mask = 0;
    	values.bits = 0;
    	gpiotools_set_bit(&values.mask, 0);
    	ret = gpiotools_get_values(fd, &values);
    	if (ret < 0)
            perror("Unable to get GPIO line values");
    
        gpiotools_set_bit(&values.bits, 0);
        gpiotools_set_values(fd, &values);
        if (ret < 0)
            perror("Unable to set GPIO line high");
    }

    Terminal:

    # Open WKUP_GPIO0_52 from userspace and toggle high
    root@tda4vm-sk:/# ./gpio_test 
    [   21.678862] test_irq: irq 275, val=0
    # check direction
    root@tda4vm-sk:/# devmem2 0x42110038
    /dev/mem opened.
    Memory mapped at address 0xffff83fb7000.
    Read at address  0x42110038 (0xffff83fb7038): 0xFFEFFFFF
    # check rising edge trigger
    root@tda4vm-sk:/# devmem2 0x4211004C
    /dev/mem opened.
    Memory mapped at address 0xffffafc4c000.
    Read at address  0x4211004C (0xffffafc4c04c): 0x00100000
    # check GPIO0_52 state
    root@tda4vm-sk:/# devmem2 0x4211003C
    /dev/mem opened.
    Memory mapped at address 0xffffa1b96000.
    Read at address  0x4211003C (0xffffa1b9603c): 0x00100000
    

    Is there any issue with opening and configuring a GPIO line from userspace as such, and using a kernel interrupt?

    Thank you,

    Jin

  • You should be able to control the states of the gpio from user space while the kernel is responsible for handling the interrupt.

    Best regards,

    Keerthy