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.

Handling of level triggered interrupts in an application running on the DM37x

Other Parts Discussed in Thread: DM3730

I'm porting and existing system that used level triggered interrupts to an embedded Linux device. I'm having a bit of trouble and hopefully someone can help. My plan was to use the poll() function (in user space, no plan for a low level driver) to detect when the gpio line is high. That's the indication to do something.

Unfortunately I haven't figured out how to enable that condition. Right now I'm doing the following:

  • Write the gpio number to /sys/class/gpio/export
  • Set the direction to "in"
  • Set the edge to ?

Can I setup the GPIO such that poll will return whenever the gpio line is high, even if poll() is called multiple times without clearing the condition, but it will wait if the line is low? Should I be using something else instead of trying to use poll()? Thanks!

P.S.  Is it possible I'm running into a hardware configuration problem?  How does the Linux code for the DM37x handle interrupts on the GPIO lines, specifically level triggered ones?

  • I found a wiki from TI partner RidgeRun (active in Linux community for DaVinci processors.)

    https://www.ridgerun.com/developer/wiki/index.php/How_to_use_GPIO_signals#Using_poll.28.29_to_monitor_for_GPIO_0_change

    Note the section titled "Using poll() to monitor for GPIO 0 change "

    I'm not sure it applies equally for level triggered conditions but let me know if this helps as I believe your challenge was to understand how to use poll().

  • I used information on the RidgeRun wikis when I initially wrote my code.  Unfortunately they don't (or I didn't find it) seem to cover the handling of level triggered interrupts.

  • Are you actually using interrupt capability, meaning the transition of the GPIO pin will generate an interrupt to the ARM CPU which you have hooked an IRQ routine?  Or are you using the term interrupt differently.

    You asked about using level-sensitive interrupt capability.  What is the behavior of the signal connected to the GPIO as it relates to being level-sensitive?  How is this condition cleared out?

  • I have a level triggered interrupt generated by an external device tied to a GPIO line.  The GPIO line is not tied to an IRQ.  Instead I'm calling the Linux poll() function to determine when the interrupt has been generated. 

    As for the interrupt signal, it goes high if there is data in a FIFO and low if the FIFO is empty.  I have ways to check the FIFO depth and collect data.

    Regardless, the system is working now.

  • Turns out the system is still not working as expected.  I setup the GPIO line to be rising edge triggered.  When I attempt to read a byte from the FIFO, I do the following:

    Is there data in the FIFO? {

    Read it.

    }

    Call poll() to wait for the data {

    Is there data in the FIFO? {

    Read it.

    }

    }

    There are cases where poll() returns claiming there are bytes in the FIFO, but it's actually empty.  I'm not sure the source of the problem, but I'm wondering if I'm not completely understanding how poll() works here.

  • Hi DThomas,

    I did notice a typo in our wiki page on GPIO, which I fixed.  You can now see that the Linux kernel support interrupts on the falling and raising edge of a GPIO.  This is standard Linux stuff.  The GPIO driver for the DM3730 supports the Linux standard GPIO driver.  The GPIO driver indeed uses interrupts.

    My first question is why you think you have to use a level interrupt?  If the GPIO signal is normally low, and you want to know when it is high, you can set the edge to rising.  You can also set it to both and then read the GPIO level to see if you want to take any action.

    From DM3730 TRM (sprugn4r section 25, page 3477):

    Each GPIO module provides 32 dedicated general-purpose pins with input and output capabilities; thus, the general-purpose interface supports up to 192 (6 x 32) pins....These pins can be configured for the following applications:...Interrupt generation in active mode when external events are detected....The general-purpose interface has 12 interrupt lines...In active mode, the input line can be used through level and edge detectors to trigger synchronous interrupts. The edge (rising, falling, or both) or the level (logical 0, logical 1, or both) used can be configured.

    Looks like the hardware supports level interrupts too, but Linux limits the interrupts to trigger on an edge.  From linux-2.6.37-psp04.02.00.07/drivers/gpio/gpiolib.c:

     *   /edge
     *      * configures behavior of poll(2) on /value
     *      * available only if pin can generate IRQs on input
     *      * is read/write as "none", "falling", "rising", or "both"

    poll() should block until there is an interrupt.  In you loop, I suggest you add a check for data before trying to read it (use a non-block read() for example).  You can add a counter to see if you encounter the case where poll() returns, but there isn't any data.

    Todd