1

I need to free the processor while I wait for a change in the level of a GPIO pin (either rising or falling edge), so I created a simple code to poll a GPIO sysfs value file, but I'm running into some trouble:

  • In the first poll() call, it exits imediatelly, with both POLLPRI and POLLERR set in revents;

  • After this, I lseek() and read() the fd, and loop back to poll();

  • Now poll() hangs.

This is my code:

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

#define GPIO_DIR "/sys/class/gpio/"
#define GPIO_EXPORT GPIO_DIR "export"

int main(int argc, char **argv)
{
   int gpio_fd;
   struct pollfd gpio_fdset[1];

   char pin_value[] = GPIO_DIR "gpioXYZ/value";
   sprintf(pin_value, GPIO_DIR "gpio%s/value", argv[1]);

   gpio_fd = open(pin_value, O_RDONLY);

   while (1)
   {
      char buffer[64];

      gpio_fdset[0].fd = gpio_fd;
      gpio_fdset[0].events = POLLPRI;
      gpio_fdset[0].revents = 0;

      poll(gpio_fdset, 1, -1);

      if (gpio_fdset[0].revents & POLLPRI)
      {
         printf("revents returned POLLPRI!\n");
         lseek(gpio_fdset[0].fd, 0, SEEK_SET);
         read(gpio_fdset[0].fd, buffer, 64);
      }
   }
}

Before calling it, I export the pin I wish to monitor (GPIO1_30 or 62 in the kernel numbering scheme). I've tried setting this pin as input, output, generating interrupts on rising and falling edges, but the behaviour is always the same. What am I missing?

From what I've read, when I use the sysfs, I should not need to use the gpio_request(), gpio_to_irq() and other related functions to be able to poll this pin. Is this right?

Regards,

Guilherme

Guilherme Costa
  • 386
  • 3
  • 15

2 Answers2

3

I've discovered how to overcome this issue. Simply perform a dummy read() after setting opening the file descriptor. Apparently this is due to the fact that a recently opened fd is considered as changed (at least for GPIOs). As for the POLLERR on revents, this is standard sysfs behaviour.

Community
  • 1
  • 1
Guilherme Costa
  • 386
  • 3
  • 15
0

If I understand your requirement right, then you want to take some action when the pin goes high.

you can poll the pin in application layer it self.

Download the "SimpleGPIO.h" and "SimpleGPIO.cpp" from the below URL:

https://github.com/derekmolloy/beaglebone

The SimpleGPIO.h/cpp is self explanatory and you can do all operations with GPIO using the simple function calls. This one will work fine for any am335x processor. Then to poll you can use in your code some thing like this

int main()
{
    //Your code

    while(1)
    {
        if(gpio_get_value())
        {
            //Do what ever you want to do.
        }
    }
}

NOTE:: If you want to send any signal to your application process from kernel level using irq then the approach will be little different, But only for polling this code will work fine.

Hope this helps.

Edit:

Please refer below url for more details, it explains your question. You need to use any signal between (Signal number 32 to 64) to detect the change of GPIO status. You need to register your processId with your kernel module.

http://yongbingchen.github.io/blog/2013/03/11/sending-a-signal-from-linux-kernel/

When there is a change in GPIO status, Kernel sends a signal to application layer on which a dedicated function in application layer can execute.

Sudipta Kumar Sahoo
  • 1,049
  • 8
  • 16
  • Actually, I need to sleep until a change is detected in the GPIO's value., hence the use of poll. I was hoping that it would the same way that it does for sockets, but it seems that it has a different behaviour for sysfs files. I've updated the description to explain my question more clearly :) – Guilherme Costa Mar 04 '16 at 18:50
  • @GuilhermeCosta Answer edited, please have a look. A little can solve your problem. – Sudipta Kumar Sahoo Mar 04 '16 at 18:56