i.MX7D Using poll() and Interrupt Handling

Hello,

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.

Thanks @sanchayan.tx,

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:

&pinctrl_hog_1 {
	fsl,pins = <
		MX7D_PAD_UART3_RTS_B__GPIO4_IO6		0x14 /* SODIMM 131 USBH OC */
		MX7D_PAD_SAI1_RX_SYNC__GPIO6_IO16	0X14 /* SODIMM 77 */
		MX7D_PAD_EPDC_DATA09__GPIO2_IO9		0x14 /* SODIMM 89 */
		MX7D_PAD_EPDC_DATA08__GPIO2_IO8		0x74 /* SODIMM 91 */
		MX7D_PAD_LCD_RESET__GPIO3_IO4		0x14 /* SODIMM 93 */
		MX7D_PAD_EPDC_DATA13__GPIO2_IO13	0x14 /* SODIMM 95 */
		MX7D_PAD_ENET1_RGMII_TXC__GPIO7_IO11	0x14 /* SODIMM 99 */
		MX7D_PAD_EPDC_DATA10__GPIO2_IO10	0x74 /* SODIMM 105 */
		MX7D_PAD_EPDC_DATA15__GPIO2_IO15	0x74 /* SODIMM 107 */
		MX7D_PAD_EPDC_GDRL__GPIO2_IO26		0x14 /* SODIMM 133 */
		MX7D_PAD_SAI1_RX_DATA__GPIO6_IO12	0x14 /* SODIMM 169 */
		MX7D_PAD_SAI1_RX_BCLK__GPIO6_IO17	0x14 /* SODIMM 24 */
		MX7D_PAD_SD2_DATA2__GPIO5_IO16		0x14 /* SODIMM 100 */
		MX7D_PAD_SD2_DATA3__GPIO5_IO17		0x14 /* SODIMM 102 */
		MX7D_PAD_EPDC_GDSP__GPIO2_IO27		0x14 /* SODIMM 104 */
		MX7D_PAD_EPDC_BDR0__GPIO2_IO28		0x74 /* SODIMM 106 */
		MX7D_PAD_EPDC_BDR1__GPIO2_IO29		0x14 /* SODIMM 110 */
		MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30	0x14 /* SODIMM 112 */
		MX7D_PAD_EPDC_SDSHR__GPIO2_IO19		0x14 /* SODIMM 120 */
		MX7D_PAD_EPDC_SDCE0__GPIO2_IO20		0x14 /* SODIMM 122 */
		MX7D_PAD_EPDC_SDCE1__GPIO2_IO21		0x14 /* SODIMM 124 */
		MX7D_PAD_EPDC_DATA14__GPIO2_IO14	0x14 /* SODIMM 126 */
		**MX7D_PAD_EPDC_PWR_STAT__GPIO2_IO31	0x14 /* SODIMM 128 */**
		MX7D_PAD_EPDC_SDCE3__GPIO2_IO23		0x14 /* SODIMM 130 */
		MX7D_PAD_EPDC_GDCLK__GPIO2_IO24		0x14 /* SODIMM 132 */
		MX7D_PAD_EPDC_GDOE__GPIO2_IO25		0x14 /* SODIMM 134 */
		MX7D_PAD_EPDC_DATA12__GPIO2_IO12	0x14 /* SODIMM 150 */
		MX7D_PAD_EPDC_DATA11__GPIO2_IO11	0x14 /* SODIMM 152 */
		MX7D_PAD_SD2_CLK__GPIO5_IO12		0x14 /* SODIMM 184 */
		MX7D_PAD_SD2_CMD__GPIO5_IO13		0x14 /* SODIMM 186 */
	>;
};

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?

Thank You.

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?

Thank You

For an example, see here.

Hey sanchayan,

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.

Thanks for the assistance sanchayan.tx!

Have a great weekend!

Please take a look at this community post.