Tue Nov 1 13:28:37 EDT 2011
Edge filtering for Interrupt On Change
Given CHANGE and STATE registers, and assuming that reading the CHANGE
register also clears it so it can detect new hardware events, how to
reliably filter out edges?
Suppose we have an ISR that is triggered by CHANGE becoming 1, reads
CHANGE, then reads STATE. Then we filter an edge based on the value
of STATE. For short pulses we filter on the trailing edge.
Can it reliably detect an arbitrarily short pulse that is long enough
to be handled by the hardware, but might be too short to be seen by a
port readout, or that is shorter than the interrupt to CHANGE readout?
In the case of a short pulse, these are the possible ordering of edge
and register read events, with l,t the leading and trailing edges and
C = CHANGE read and S = STATE read.
(1) l C S t C S both C S are in time to see first edge
(2) l C t S C S S is too late ...
(3) l t C S bot C S are too late ..
In the first 2 cases, 2 interrupts are triggered, while in the second
case only one is triggered as the HW edge detect did not see the
second edge. Using just the value of S is not enough to detect only
one edge per pulse, as this would trigger on both edges in case (2).
* The above seems to work for pulses that are long enough or short
enough, but the middle case is puzzling.
* Is this a problem? How to fix it?
* Why didn't I hear about this before? Probably because it's solved
by using long enough pulses such that interrupt -> C,S reads all
happen before the trailing edge.
* For level triggered interrupts of course one triggers on the
leading edge because it is never going to be missed as it will
only be lifted after acknowledgement which is necessarily after
The scenario above is for an Atmel AT91SAM7. After a bit of Googling
I find this in Microchip AN566 which talks about using the IOC pins
for handling external interrupts:
An interrupt pulse with a small pulse width requires less overhead
than a wide pulse width. A small pulse width signal must be less
than the minimum execution time of the interrupt service routine,
while a wide pulse width must be greater then the maximum time
through the interrupt service routine.
They mention these 2 good cases (1) and (3), but not the bad case (2).
Maybe for the PIC there is no problem because there is an atomic read?
I'm not sure exactly how the mechanism works there..
Indeed, It looks like there is only a single interrupt flag, not a
per-pin flag as on the AT91, and this flag is cleared when the input
pins are read. So here there are only two cases, the C and S
operations are atomic:
(p1) l CS t CS
(p2) l t CS
Is there a way to fix the AT91 problem? Does a 2nd read solve it?
Let's try C S C.
l C S C r C S C
l C S r C
l C r S C
l r C S C
At first sight it looks like this makes it at least possible to
distinguish the cases, but it makes it harder to do in parallel for a
number of pins.. FIXME: check with clear head..