2009-06-03 17:02:39     Multiple GPIO Interrupts

Document created by Aaronwu Employee on Aug 15, 2013
Version 1Show Document
  • View in full screen mode

2009-06-03 17:02:39     Multiple GPIO Interrupts

Ben Matthews (UNITED STATES)

Message: 75132   

 

I've written an interrupt driven driver for a memory mapped timing device which works fine, until I try to add a second device with a second interrupt. Either device works, but if I try to use both at once things break. It looks like the chip I'm using (BF532) only has two GPIO interrupts which can be shared among many pins, so I'm guessing that there's an interrupt conflict between the ethernet controller and my two devices (three GPIO interrupts registered in the kernel).  With the second device, it looks like both my devices are missing interrupts (the ethernet controller is unaffected, so I'm guessing that the kernel put both my devices on the same interrupt). It's also worth mentioning that the edge sensitivity of my interrupts may need to change, depending on the mode the device is being used in (this could be worked around if it has to be).

 

 

 

I found a post from 2005 (https://blackfin.uclinux.org/gf/project/uclinux-dist/forum/?action=ForumBrowse&forum_id=39&_forum_action=ForumMessageBrowse&thread_id=360) which indicated that support for this kind of setup was being worked on? Should it work now? If not, could you give me some hints as to where to look to go about implementing it myself?

 

 

 

I'm using a fresh copy of the kernel/tools from git as of May 29 on the BlackStamp board with a BF532 processor.

 

 

 

Thanks.

QuoteReplyEditDelete

 

 

2009-06-03 19:47:29     Re: Multiple GPIO Interrupts

Mike Frysinger (UNITED STATES)

Message: 75136   

 

why do you think only two GPIO interrupts are supported ?  MASKA/MASKB are to provide different prioritizations only from the SIC to the CEC.  otherwise, there should be no limitation at all with interrupts on all GPIO pins.

 

using set_irq_type() on the fly to change edge settings shouldnt be a problem either.

 

presumably you're servicing the interrupts completely.  what if your handlers only return IRQ_HANDLED ?  then check /proc/interrupts to make sure things increment as you expect.

QuoteReplyEditDelete

 

 

2009-06-04 04:07:13     Multiple GPIO Interrupts

Michael Hennerich (GERMANY)

Message: 75144    Since years there is something implemented called demux_gpio_irq.

This allows you to have up to 16 IRQ_GPIOs on a single MASKA bank.

In general this means that all Blackfin GPIOs can be simultaneous Interrupts with only using MASK_A.

 

In theory you should not experience such things. And I know it used to be working well.

However there have been some changes in the meanwhile - maybe something broke this.

 

Can you also test the kernel from our last 2008R1 Release branch in svn/git.

 

-Michael

QuoteReplyEditDelete

 

 

2009-06-04 10:12:15     Re: Multiple GPIO Interrupts

Ben Matthews (UNITED STATES)

Message: 75212   

 

Glad to hear this should work,

 

What do you mean by servicing the interrupts completely? They're edge triggered interrupts. Then handler takes care of the hardware's needs and returns IRQ_HANDLED. After looking at the code surrounding demux_gpio_irq, it looks like there's an additional ack call which I might need to be using? Is this the case? If so, what's the generic call (not blackfin specific)/what header is it in?

 

Also, are multiple interrupts queued so that they can't be missed? If I miss an interrupt, the devices I'm talking to stop sending them and I have no way of knowing if they need reseting or not.

 

If that's not it, I'll try the 2008R1 release in a little while, I want to copy my working directory before I go back that far, and our NFS server could be faster.

 

After some more careful testing, It looks like it's ok if I don't have either interrupt changing edge sensitivity (at least most of the time).. is this the expected behavior or should I be able to have different edge sensitivity on different pins (it gets changed under interrupt -- in the handler for a rising edge interrupt, I change it to falling edge using set_irq_type() to catch the next falling edge)

 

 

 

The count in /proc/interrupts is incrementing as expected

 

 

 

Thanks again for all your help

QuoteReplyEditDelete

 

 

2009-06-04 11:16:12     Re: Multiple GPIO Interrupts

Michael Hennerich (GERMANY)

Message: 75213    >What do you mean by servicing the interrupts completely?

 

Don't know what you mean.

 

>additional ack call which I might need to be using?

 

No - the kernel will ack the IRQ for you, in case you use an EDGE

triggered interrupt.

You - should not ACK.

 

>Also, are multiple interrupts queued so that they can't be missed?

 

They are executed in row - see the mask shift in bfin_demux_gpio_irq.

 

You should be able to have different edge sensitivity on different pins

 

However can you avoid calling set_irq_type in the ISR.

(set_irq_type() may have side effects)

 

For instance use both edge triggered interrupts?

The hardware supports that.

 

-Michael

QuoteReplyEditDelete

 

 

2009-06-04 11:51:48     Re: Multiple GPIO Interrupts

Ben Matthews (UNITED STATES)

Message: 75214   

 

>What do you mean by servicing the interrupts completely?

 

>>Don't know what you mean.

   Mike F's first sentence in the first reply to this thread

 

 

 

 

>>You should be able to have different edge sensitivity on different pins

>>

>>However can you avoid calling set_irq_type in the ISR.

>>(set_irq_type() may have side effects)

>>

>>For instance use both edge triggered interrupts?

>>The hardware supports that.

 

 

 

Maybe; I didn't see a type flag in the kernel's interrupt header to allow triggering on both edges. I need two interrupts, but the chip I'm talking two only provides one, so what I'm doing is getting the first interrupt and changing the chip's interrupt mask to get a second interrupt with a different meaning. (The chip has two fifos, on the first interrupt I tell it to move a measurement into the output fifo and set it to interrupt when the second fifio is no longer empty.. I then rearm the chip on the second interrupt). If I could mask the interrupt so that I don't get a garbage one when I change the interrupt mask, then triggering on both could work.

 

How do I request a both edge triggered interrupt? (It might be nice to add this to the wiki page on interrupts)

 

Can I mask the interrupt in the blackfin while I talk to the chip causing the interrupts (inside the ISR) / how?

 

Based on what I'm reading on the web it looks like masking should be doable (though I'm not exactly sure how.. it looks like the handler's prototype has changed), but there doesn't seem to be a nice way to trigger on both edges.

QuoteReplyEditDelete

 

 

2009-06-04 12:05:26     Re: Multiple GPIO Interrupts

Michael Hennerich (GERMANY)

Message: 75216    >How do I request a both edge triggered interrupt? (It might be nice to add this to the wiki page on interrupts)

 

Simply request the IRQ with both flags or'ed:

(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)

 

>Can I mask the interrupt in the blackfin while I talk to the chip causing the interrupts (inside the ISR) / how?

 

Using:

 

disable_irq(IRQ_Pxx);

 

enable_irq(IRQ_Pxx);

 

-Michael

QuoteReplyEditDelete

 

 

2009-06-04 16:35:35     Re: Multiple GPIO Interrupts

Ben Matthews (UNITED STATES)

Message: 75221   

 

Thanks for the hints, but even with both flags or'd in, it misses one edge or the other (even if I don't mask the interrupt while I'm changing settings). Based on how my device is behaving, I think it's probably missing the falling edges.

 

Watching the interrupt line on the scope, the line starts low, goes high for ~ 12uS, goes low for about 1uS and goes back high. During that exchange I would expect three interrupts, but I only get two (put printk's in the handler to be sure). If I was getting the last interrupt, I would reset my device and the line would go low again (but I never get it, so it stays high).

 

I'm requesting the interrupt with

 

request_irq(IRQ_PF12,handler_function_ptr,(IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING),"String",struct_of_chip_data);

 

Am I correct in thinking this isn't the expected behavior?

 

 

 

I still haven't been able to try 2008R1 because the last tag was released before there was support for my board. If this isn't what you would expect (nobody has better ideas) I can try to cherry-pick the changes I need to get it to boot, but I'd rather not have to.

 

 

 

Thanks again for all your help

QuoteReplyEditDelete

 

 

2009-06-05 03:50:05     Re: Multiple GPIO Interrupts

Michael Hennerich (GERMANY)

Message: 75226    >Watching the interrupt line on the scope, the line starts low, goes

high for ~ 12uS, goes low for

>about 1uS and goes back high. During that exchange I would expect three

interrupts, but I only get

>two (put printk's in the handler to be sure).

 

Don't put printks into ISR handlers that go out the serial port. UART is

**** slow - this is going to hold off interrupt processing. In general

1us is way to fast. You enter the interrupt on the first active edge

(you possibly did some printk), the interrupt returns. And I have the

impression the edge after the 1us pause may get lost due to the possible

instance that it could get ACKed by the kernel acknowledging the last

falling edge.

 

Debugging interrupt timing, I would only use GPIOs. Set a GPIO when you

enter the ISR and reset it upon return. On a scope watch the IRQ and the

GPIO. Use complex/advanced triggers to determine when you possibly lost

an edge.

 

If you don't have spare GPIOs - you may also do dummy read accesses to

different Async Memory banks, and watch the /AMSx strobe wiggle.

 

-Michael

QuoteReplyEditDelete

 

 

2009-06-05 10:12:58     Re: Multiple GPIO Interrupts

Ben Matthews (UNITED STATES)

Message: 75251   

 

I have some memory mapped LEDs I've been also using for that purpose, but I had been (seemingly) getting away with the prinks because the chip I'm talking to can wait for at least a while (they're easier to work with in a lot of ways). It does make the interrupt last a lot longer though (the timeing I mentioned is w/o the printks). Also, I wouldn't think the overhead would be too bad with the messages going to syslog (probably get put in a buffer some place and get moved to userspace when things are idle?).. but I'm just guessing here.

 

I know that the last edge will occur ~1uS after the one before, so I could probably make it work by busy-waiting in the ISR for a few hundred instructions, but I'd rather not. Is there a better way to catch that last edge? It seems to me that you may very well be correct about it getting ack'd by accident (it still seems to be missing at least)

 

About how long is the minimum period that linux can reliably catch all the edges? (I have a 400Mhz core clock for what it's worth)

QuoteReplyEditDelete

 

 

2009-06-05 10:31:01     Re: Multiple GPIO Interrupts

Michael Hennerich (GERMANY)

Message: 75253    >About how long is the minimum period that linux can reliably catch all

the edges? (I have a 400Mhz

>core clock for what it's worth)

 

First of all you should enable all options in "Blackfin Kernel

Optimizations" that speed up the interrupt path. Also use Write Back

Cache.

 

However I still doubt that you can catch the edge 1us apart form the

last edge causing an interrupt.

The typical interrupt latency is somewhere in the single digit us range

depending cache trashing etc.

And it always can be the case that a higher priority interrupt will snip

in - so it can be longer.

 

Connect a scope and measure the latency - to see where you are.

 

-Michael

QuoteReplyEditDelete

 

 

2009-06-07 23:24:45     Re: Multiple GPIO Interrupts

Sonic Zhang (CHINA)

Message: 75304   

 

If you want real time capability, please run your driver and application under ADEOS patch and Xenomai.

 

Standard Linux kernel doesn't ensure you catch a max interrupt latency.

QuoteReplyEditDelete

 

 

2009-06-08 14:27:01     Re: Multiple GPIO Interrupts

Ben Matthews (UNITED STATES)

Message: 75368   

 

Thanks again for all the help, I finally got it working this afternoon at acceptible data rates by adjusting things a little to give the blackfin more time to react to pulses. I'll try out the real time patches when I have a minute, but for now I have to write some higher level code

Attachments

    Outcomes