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.

GPIO Sysfs Interrupt using Poll not Working

Other Parts Discussed in Thread: PCF8575

Hi,

I'm trying to get GPIO Interrrupt functionality working using sysfs and poll calls.   The problem appears to be that the poll call is always returnng immediately and is not triggering on the actualy rising edge.   I have configured the kernel for this GPIO to be an input which does work correctly.  I've also configured the GPIO (114) correctly for an interrupt input set for rising edge.  This can be seen here:

root@dm814x-evm:/sys/class# mount -t debugfs debugfs /sys/kernel/debug
root@dm814x-evm:/sys/class# cat /sys/kernel/debug/gpio
GPIOs 0-31, gpio:
 gpio-31  (ts_irq              ) in  hi irq-191 edge-falling

GPIOs 32-63, gpio:

GPIOs 64-95, gpio:

GPIOs 96-127, gpio:
 gpio-114  (sysfs              ) in  lo irq-247 edge-rising

GPIOs 128-143, i2c/1-0021, pcf8575, can sleep:
 gpio-128 (lcd_power           ) out lo

When I call my "Wait/Poll" routine below from a thead , it does not Bock waiting on the interrupt...instead it ruturns immediately and indicates that an interrupt was encountered but there is none because the line is tied low....  Any suggestions on what might be wrong below or with this wait / poll process ???????    Also can a GPIO interrupt be configured as a level triggered interrupt ???? If so , how .....   

int CGPIOControlPort::GpioPoll(unsigned int gpio)
{
 struct pollfd fdset[1];
 int timeout, nfds, rc;
 int fd, len;
 char buf[60];

 len = snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);

 fd = open(buf, O_RDONLY | O_NONBLOCK);
 if (fd < 0)
    {
  perror("gpio/poll");
  return fd;
 }

    timeout = -1;
    nfds = 1;
    fdset[0].fd = fd;
    fdset[0].events = POLLPRI;
    fdset[0].revents = 0;

    rc = poll(fdset, nfds, timeout);   // I believe this should be blocking until an actual rising edge is seen but it is not 

 if (rc < 0)
    {
  m_DebugLog.LogDebug(AT, 0, "CGPIOControlPort::GpioPoll Protect FAILED" );
        xfc_printf("CGPIOControlPort::GpioPoll FAILED\n");
  return -1;
 }

 if (fdset[0].revents & POLLPRI)
    {
  m_DebugLog.LogDebug(AT, 0, "CGPIOControlPort::GpioPoll Interrupt" );    // This is being displayed immediately everytime routine is called
  len = read(fdset[0].fd, buf, sizeof(buf));
  xfc_printf("\npoll() GPIO %d interrupt occurred = %d \n", gpio, rc);
 }

 close(fd);
 return 0;
}

 

 

  • Maybe try without the O_NONBLOCK flag in the open() call. I assume that you used the sysfs edge file to specify the edge transition.

  • Thanks for the suggestion but there was no change....Poll call returns immediately without an error...Return rc value = 1..

    I am using sysfs edge file to specify the edge transition which appears to be set correctly based on initial post output.

    gpio-114  (sysfs              ) in  lo irq-247 edge-rising

    I have not tried the POLLIN event rather than the POLLPRI that I'm currently using but I think POLLPRI is correct.

  • I have seen sometimes that the first poll is not "real". I think it is due to the initial state of the GPIO value register being undefined. It can be opposite of the incoming signal. You could try polling twice. Ignore the first one.

    POLLPRI is the correct flag. Is revents non-zero? What is the value from read()? Everything looks proper. Just to check you have correct GPIO....you have tried printing out the level as you toggle the GPIO? I've used the same sort of GPIO code on an Atmel plafform. Never actually tried it on a TI processor. Hopefully TI has properly implemented the low-level GPIO driver.

  • I have tried polling twice and that does not seem to work.  I have verified that the input is changing when I pull it high or low as seen below.

    The poll call returns a positive value indicating 1 fd and thus no errors (rc = 1) ....however the revents return value (revents = 0xA) indicates both that the POLLPRI  and POLLERR are set.  I do not understand what is causing the POLLERR but must be the source of the issue.  I've read that it might be caused by a bad fd but that looks good, as the read would not work if that was the case....

    Once again my setup appears correct based on the cat debug/gpoio output below for GPIO 114 that I'm testing with....

    Any further suggestion would be appreciated in trying to resolve this problem....

    Thanks very much

    poll() GPIO 114 interrupt occurred  rc = 1   revents = 0xA
    Input is High
    poll() GPIO 114 interrupt occurred  rc = 1   revents = 0xA
    Input is High
    poll() GPIO 114 interrupt occurred  rc = 1   revents = 0xA
    Input is Low

    cat... output:

    GPIOs 0-31, gpio:
     gpio-29  (sysfs               ) out hi
     gpio-30  (sysfs               ) in  lo
     gpio-31  (ts_irq              ) in  hi irq-191 edge-falling

    GPIOs 32-63, gpio:

    GPIOs 64-95, gpio:

    GPIOs 96-127, gpio:
     gpio-114 (sysfs               ) in  lo irq-274 edge-rising

     

     

  • I've seen the seemingly spurious POLLERR flag as well on the Atmel platform. The POLLPRI flags was always correct. I wrote it off as a bug in implemention. Probably shouldn't have. Odd that you receiving the POLLERR flag as your events mask is just for POLLPRI.

    I usually open the value file with O_RDWR. Don't remember why. It should not make any difference.

    Some posts on other forums would suggest a dummy read() before the poll(). I think this must clear any pending IRQs.

    I'm out of ideas. Some details might help others to help you. Which processor and board? Which version of Linux, PSP or SDK?

  • Thanks a bunch Normal !!!

    Your last suggestion of doing a dummy read() before the poll() did the trick.  I'm still getting back both POLLPRI and POLLERR bits set, but seems to be a common issue if you have seen this as well.....I'll just mask it out....But it is blocking until a rising edge and then functions as expected.  I've left the open options as is since there was no effect with changing that.

    Thanks again

  • I just ran into the POLLERR thing you're seeing too. Turns out this is how all sysfs files work, and you're using gpio through the sysfs interface.

    From the sysfs GPIO kernel document:

    If the pin can be configured as interrupt-generating interrupt
    and if it has been configured to generate interrupts (see the
    description of "edge"), you can poll(2) on that file and
    poll(2) will return whenever the interrupt was triggered. If
    you use poll(2), set the events POLLPRI and POLLERR.

    Also, if you look take a look at the kernel code in fs/sysfs/file.c, you'll see that sysfs_poll returns DEFAULT_POLLMASK | POLLERR | POLLPRI.

    All that said, it does seem strange that sysfs files return POLLERR, I'm not sure why they chose to do that.

  • Thanks for the additional info. In the old kernels, that paragraph was in the gpio.txt rather than the newly created sysfs.txt. The doc probably just documents what was implemented with no idea why it was implemented that way. As it is, I guess there is no way to tell if there is a true POLLERR.