We are having an issue using poll() in an interrupt handler to wait for interrupts to occur.
We are using GPIO line 128 as an input and setting this line to trigger an interrupt on a rising edge. The interrupt handler calls poll() and waits for a POLLPRI event to occur. Here is the software that sets up and waits for the interrupt:
GPIO gpioFpgaFifoInterrupt;
static int gpioFpgaFifoInterruptFileDescriptor;
int WaveformCommands::gpioFpgaFifoInterruptFileDescriptor = 0;
static const uint32_t gpiofpgaFifoInterruptLine = 128;
gpioFpgaFifoInterrupt = GPIO();
gpioFpgaFifoInterrupt.gpio_export( gpiofpgaFifoInterruptLine );
gpioFpgaFifoInterrupt.gpio_set_dir( gpiofpgaFifoInterruptLine, "in" );
gpioFpgaFifoInterrupt.gpio_set_edge( gpiofpgaFifoInterruptLine, "rising" ); // Can be rising, falling or both
WaveformCommands::gpioFpgaFifoInterruptFileDescriptor = gpioFpgaFifoInterrupt.gpio_fd_open( gpiofpgaFifoInterruptLine, O_RDONLY ); // Makes the following call: open(gpiofpgaFifoInterruptLine, 0 | O_NONBLOCK );
WaveformCommands::gpioFpgaFifoInterruptFileDescriptor = gpioFpgaFifoInterrupt.gpio_fd_open( gpiofpgaFifoInterruptLine, O_RDONLY );
FpgaInterruptService()
{
while( TRUE )
{
int returnValue = 0;
memset( pollFileDescriptor, 0, sizeof( pollFileDescriptor ) );// while(1)
// {
// usleep( 100 );
// }
pollFileDescriptor[0].fd = STDIN_FILENO;
pollFileDescriptor[0].events = POLLIN;
pollFileDescriptor[1].fd = WaveformCommands::gpioFpgaFifoInterruptFileDescriptor;
pollFileDescriptor[1].events = POLLPRI;
// 6/26/2017 KJC - TODO: Setting timeout to a -1 to indicate that poll()
// should wait indefinitely for an interrupt to
// occur.
returnValue = poll( pollFileDescriptor, numberOfFileDescriptors, -1 );
if( pollFileDescriptor[1].revents & POLLPRI )
{
lseek( pollFileDescriptor[1].fd, 0, SEEK_SET ); // Read from the start of the file
(void)read( pollFileDescriptor[1].fd, readBuffer, sizeof( readBuffer ) );
qdebug() << "Interrupt occured!"
}
}
}
When we test this software in our application we see that we are receiving interrupts as the output Interrupt Occured! is generated, but the return from poll() only occurs twice. The third time the call to poll() is made it never returns. We don’t understand why the interrupt only seems to occur twice. Also, by stepping through code we can see that the call to poll() is made but we can never step past that call the third time an interrupt occurs.
Is there something that we are doing wrong or not configuring for this to work properly?
We are setting up the GPIO line according to the: gpio.txt document. It specifies calling lseek on the file descriptor and then calling read to make sure the event is reset for the interrupt and we are doing this.
I did read through the forum post previously in the link you provided, but I missed the the part in the last response where it’s necessary to call read() after opening the file but before the call to poll().
This resoved the issue where poll() returns immediately when first called, but before an interrupt occurs. Now poll() never returns, but I believe this has to do with the fact that GPIO line 128 is not properly configured for use as a GPIO line in the device tree file for our carrier board.
Here is the node in the device tree where GPIO line 128 is configured as a GPIO line for use:
I made sure that this GPIO line is not being used for anything else in the device tree. Is there something else that needs to be setup in the device tree to allow GPIO lines to be used as GPIO? I tried configuring another GPIO line: 99 to use in user space. I was able to export GPIO99. I set the direction as out and the value as 1, but it isn’t working since the LED connected to that line doesn’t light up as it should.
I believe this has to do with correct GPIO line configuration, but I don’t know what I’m doing wrong. If I can figure out the problem the interrupt line should start working.
Do you have any idea what I might be doing wrong based on the node configuration above?
Sorry but can you please confirm if you are really referring to SODIMM 128 and 99 or GPIO 128 and 99? SODIMM number is not equivalent to Linux GPIO number.
That’s the problem that I believe we’re having. I wasn’t sure how the GPIO lines from the processor are mapped to GPIO pin numbers in embedded Linux. The closest thing that I could find was a link on the Community Support forum here to a Toradex page that has the pin mappings for an i.MX6 processor, but not an i.MX7 so I wasn’t sure if they were the same.
I am referring to SODIMM 128. What would be the GPIO line number that I would need to set in embedded Linux to setup SODIMM 128 from user space?
Success! I actually went back and looked at this document: GPIO Alphanumeric to GPIO Numeric Assignment. It only mentions GPIO line mappings up to the i.MX6, but it looks like GPIO lines are the same for the i.MX6 and i.MX7 processors. The GPIO line number that I need to use is 63 not 128. Thanks for pointing out my error. Once I corrected this in my code it looks like the interrupt handler is working perfectly now which is sweet! Viewing the signals on a logic analyzer indicates that everything is now working as it should so success!
Now we should be able to move along and make rapid progress.