0

i'm writing a library for my raspberry pi 2 for gpio control.

I'm trying to test a function for read a gpio driven by interrupts with sysfs but i can't do that my function stops in poll() function.

This is my fucntion

int gpio_waitForInterrupt(GPIO_t *gpio, uint32_t timeout)
{

    char buf[50] = {0};
    snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio->number);

    int fd = open(buf, O_RDONLY);
    if (fd == -1) return -1;

    struct pollfd pfd;
    memset(&pfd,0,sizeof(struct pollfd));
    pfd.fd = fd;
    pfd.events = POLLPRI;

    char c;
    int value=0;

    int ret = poll(&pfd, 1, timeout);
    if(ret==0)
    {   
        errno=ETIMEDOUT;
        return -1;
    }else if(ret<0){
        return -1;
    }


    if(pfd.revents&POLLPRI)
    {

        if(read(fd, &c, 1)<0)
        {
            close(fd);
            return -1;
        }

        if(lseek(fd, 0, SEEK_SET)<0)
        {
            close(fd);
            return -1;
        }

        if(c=='1') value=1;
        else value=0;
        gpio->value=value;

        if(gpio->intCallback)
        {
            gpio->intCallback(gpio);
        }

    }

    close(fd);

    return value;

}

and this is my example test program.

int main (void)
{
    GPIO_t gpio;
    gpio_init(&gpio, 17);
    if(gpio_config(&gpio, INPUT,0)<0)
    {
        perror("Couldn't config gpio.");
        return -1;
    }

    if(gpio_setEdge(&gpio,RISING_EDGE)<0)
    {
        perror("Couldn't config edge.");
        return -1;
    }

    while(1)
    {
        puts("Waiting for GPIO.");
        int retVal=gpio_waitForInterrupt(&gpio,-1); //Infinite waiting
        printf("WaiForInterrupt returned with value %d \n", retVal);
        if(retVal<0)
        {   
            perror("Error waiting GPIO.");
            return -1;
        }
    }


    return 0;
}

My output is:

Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.
WaiForInterrupt returned with value 0
Waiting for GPIO.

As you can see poll function is returning constantly with POLLPRI flag set and is not waiting for level change of gpio.

I'm controlling this GPIO with the next gpio (GPIO27) configured as output.

I don't know what is doing wrong.

2
  • No, as you can see in the main function, gpio17 is configured as input. I have connected gpio17 to gpio27(configured as output) for drive de level change of gpio17 – jcardenas Dec 29 '19 at 18:46
  • I,m controlling gpio27 with command line in sysfs directory but without change the value of gpio27 i have this output with my test program – jcardenas Dec 29 '19 at 18:52
0

Here is some working code which waits for a sysfs interrupt.

Please note the preconditions assumed by the code which are noted in the comments.

As an aside please note that the sysfs interface is deprecated and has been removed from some Linux kernels. If you are writing a new library I suggest you use the /dev/gpiochip interface instead.

/* 2014-07-06
   wfi.c

   gcc -o wfi wfi.c

   ./wfi [gpio]
*/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <poll.h>

#define GPIO 4

int main(int argc, char *argv[])
{
   char str[256];
   struct timeval tv;
   struct pollfd pfd;
   int fd, gpio;
   char buf[8];

   /*
      Prior calls assumed.
      sudo sh -c "echo 4      >/sys/class/gpio/export"
      sudo sh -c "echo in     >/sys/class/gpio/gpio4/direction"
      sudo sh -c "echo rising >/sys/class/gpio/gpio4/edge"
   */

   if (argc > 1) gpio = atoi(argv[1]);
   else          gpio = GPIO;

   sprintf(str, "/sys/class/gpio/gpio%d/value", gpio);

   if ((fd = open(str, O_RDONLY)) < 0)
   {
      fprintf(stderr, "Failed, gpio %d not exported.\n", gpio);
      exit(1);
   }

   pfd.fd = fd;

   pfd.events = POLLPRI;

   lseek(fd, 0, SEEK_SET);    /* consume any prior interrupt */
   read(fd, buf, sizeof buf);

   poll(&pfd, 1, -1);         /* wait for interrupt */

   lseek(fd, 0, SEEK_SET);    /* consume interrupt */
   read(fd, buf, sizeof buf);

   exit(0);
}
2
  • It worked! Thank you very much. I Have added lseek(fd, 0, SEEK_SET); read(fd, buf, sizeof buf); before poll to consume any prior interrupt. – jcardenas Dec 29 '19 at 22:59
  • Thank you about the suggestion to change to /dev/gpiochip. I'm going to investigate it. – jcardenas Dec 30 '19 at 11:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.