EmbeddedRelated.com
Forums

One of the 200 interrupts does not get executed sometimes due to a single statement

Started by karthikbg December 14, 2006
Hi,

1)  I have 200 interrupts and the corresponding Interrupt service
routines for those.

ISR ()
{
   If (INTERRUPT_FLAG == 1)
        DO_ISR_ACTIVITY
   INTERRUPT_FLAG = 0;
}

When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the
interrupt gets fired, but not handled as it is at the end of ISR. How
to avoid this.
But, the clearing of the 'INTERRUPT_FLAG = 0' is required.

So, one of the 200 interrupts does not get executed sometimes.
How to avoid the above problem ?

2)   Further, i do suspect that an interrupt can come in the middle of
'DO_ISR_ACTIVITY' routine and that can also cause a problem of that
interrupt being left un-attended.
If this is the case, how to check this as there are 200 interrupts ?

Tonnes of Thx in advans,
Karthik Balaguru

karthikbg wrote:

> Hi, > > 1) I have 200 interrupts and the corresponding Interrupt service > routines for those. > > ISR () > { > If (INTERRUPT_FLAG == 1) > DO_ISR_ACTIVITY > INTERRUPT_FLAG = 0; > } > > When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the > interrupt gets fired, but not handled as it is at the end of ISR. How > to avoid this. > But, the clearing of the 'INTERRUPT_FLAG = 0' is required. > > So, one of the 200 interrupts does not get executed sometimes. > How to avoid the above problem ? > > 2) Further, i do suspect that an interrupt can come in the middle of > 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that > interrupt being left un-attended. > If this is the case, how to check this as there are 200 interrupts ?
How about something like this: ISR() { if( interrupt_flag ) { interrupt_flag = 0; do_isr_activity(); } } That way, when a new interrupt comes in while you're processing the old one, the interrupt flag will be set again. This assumes 'do_isr_activity()' can handle the case where multiple interrupts have been received.
Arlet wrote:
> karthikbg wrote: > > > Hi, > > > > 1) I have 200 interrupts and the corresponding Interrupt service > > routines for those. > > > > ISR () > > { > > If (INTERRUPT_FLAG == 1) > > DO_ISR_ACTIVITY > > INTERRUPT_FLAG = 0; > > } > > > > When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the > > interrupt gets fired, but not handled as it is at the end of ISR. How > > to avoid this. > > But, the clearing of the 'INTERRUPT_FLAG = 0' is required. > > > > So, one of the 200 interrupts does not get executed sometimes. > > How to avoid the above problem ? > > > > 2) Further, i do suspect that an interrupt can come in the middle of > > 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that > > interrupt being left un-attended. > > If this is the case, how to check this as there are 200 interrupts ? > > How about something like this: > > ISR() > { > if( interrupt_flag ) > { > interrupt_flag = 0; > do_isr_activity(); > } > } > > That way, when a new interrupt comes in while you're processing the old > one, the interrupt flag will be set again. This assumes > 'do_isr_activity()' can handle the case where multiple interrupts have > been received.
200 interrupts is a HUGE # of interrupts! Do you really need that many? I'd also make sure that interrupts are disabled at the start of the ISR and restored at the end of the ISR. "do_isr_activity()" should also be as short and simple as possible. Calling O/S routines from an ISR is also not a good idea. HTH -Dave Pollum
"Arlet" <usenet+5@ladybug.xs4all.nl> wrote in message 
news:1166104313.478604.162220@f1g2000cwa.googlegroups.com...
> > karthikbg wrote: > >> Hi, >> >> 1) I have 200 interrupts and the corresponding Interrupt service >> routines for those. >> >> ISR () >> { >> If (INTERRUPT_FLAG == 1) >> DO_ISR_ACTIVITY >> INTERRUPT_FLAG = 0; >> } >> >> When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the >> interrupt gets fired, but not handled as it is at the end of ISR. How >> to avoid this. >> But, the clearing of the 'INTERRUPT_FLAG = 0' is required. >> >> So, one of the 200 interrupts does not get executed sometimes. >> How to avoid the above problem ? >> >> 2) Further, i do suspect that an interrupt can come in the middle of >> 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that >> interrupt being left un-attended. >> If this is the case, how to check this as there are 200 interrupts ? > > How about something like this: > > ISR() > { > if( interrupt_flag ) > { > interrupt_flag = 0; > do_isr_activity(); > } > } > > That way, when a new interrupt comes in while you're processing the old > one, the interrupt flag will be set again. This assumes > 'do_isr_activity()' can handle the case where multiple interrupts have > been received. >
This will handle receiving multiple interrupts during interrupt processing. ISR() { static int unhandled = 0; if (unhandled) { unhandled++; // buffering interrupt counts interrupt_flag = 0; } else { unhandled++; // first interrupt interrupt_flag = 0; while (unhandled) // handle interrupt, and others that may come in { do_isr_activity(); unhandled--; } } } Rufus
"Rufus V. Smith" <nospam@nospam.com> wrote in message 
news:45817976$0$20219$88260bb3@news.teranews.com...
> > "Arlet" <usenet+5@ladybug.xs4all.nl> wrote in message > news:1166104313.478604.162220@f1g2000cwa.googlegroups.com... >> >> karthikbg wrote: >> >>> Hi, >>> >>> 1) I have 200 interrupts and the corresponding Interrupt service >>> routines for those. >>> >>> ISR () >>> { >>> If (INTERRUPT_FLAG == 1) >>> DO_ISR_ACTIVITY >>> INTERRUPT_FLAG = 0; >>> } >>> >>> When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the >>> interrupt gets fired, but not handled as it is at the end of ISR. How >>> to avoid this. >>> But, the clearing of the 'INTERRUPT_FLAG = 0' is required. >>> >>> So, one of the 200 interrupts does not get executed sometimes. >>> How to avoid the above problem ? >>> >>> 2) Further, i do suspect that an interrupt can come in the middle of >>> 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that >>> interrupt being left un-attended. >>> If this is the case, how to check this as there are 200 interrupts ? >> >> How about something like this: >> >> ISR() >> { >> if( interrupt_flag ) >> { >> interrupt_flag = 0; >> do_isr_activity(); >> } >> } >> >> That way, when a new interrupt comes in while you're processing the old >> one, the interrupt flag will be set again. This assumes >> 'do_isr_activity()' can handle the case where multiple interrupts have >> been received. >> > > This will handle receiving multiple interrupts > during interrupt processing. > > ISR() > { > static int unhandled = 0; > > if (unhandled) > { > unhandled++; // buffering interrupt counts > interrupt_flag = 0; > } > else > { > unhandled++; // first interrupt > interrupt_flag = 0; > while (unhandled) // handle interrupt, and others that may come in > { > do_isr_activity(); > unhandled--; > } > } > } > > Rufus >
Reading and writing unhandled in a nested interrupt? Is write access atomic? Regards, Richard. + http://www.FreeRTOS.org + http://www.SafeRTOS.com for Cortex-M3, ARM7, ARM9, HCS12, H8S, MSP430 Microblaze, Coldfire, AVR, x86, 8051, PIC24 & dsPIC
Rufus V. Smith wrote:

> "Arlet" <usenet+5@ladybug.xs4all.nl> wrote in message > news:1166104313.478604.162220@f1g2000cwa.googlegroups.com... > > > > karthikbg wrote: > > > >> Hi, > >> > >> 1) I have 200 interrupts and the corresponding Interrupt service > >> routines for those. > >> > >> ISR () > >> { > >> If (INTERRUPT_FLAG == 1) > >> DO_ISR_ACTIVITY > >> INTERRUPT_FLAG = 0; > >> } > >> > >> When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the > >> interrupt gets fired, but not handled as it is at the end of ISR. How > >> to avoid this. > >> But, the clearing of the 'INTERRUPT_FLAG = 0' is required. > >> > >> So, one of the 200 interrupts does not get executed sometimes. > >> How to avoid the above problem ? > >> > >> 2) Further, i do suspect that an interrupt can come in the middle of > >> 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that > >> interrupt being left un-attended. > >> If this is the case, how to check this as there are 200 interrupts ? > > > > How about something like this: > > > > ISR() > > { > > if( interrupt_flag ) > > { > > interrupt_flag = 0; > > do_isr_activity(); > > } > > } > > > > That way, when a new interrupt comes in while you're processing the old > > one, the interrupt flag will be set again. This assumes > > 'do_isr_activity()' can handle the case where multiple interrupts have > > been received. > > > > This will handle receiving multiple interrupts > during interrupt processing. > > ISR() > { > static int unhandled = 0; > > if (unhandled) > { > unhandled++; // buffering interrupt counts > interrupt_flag = 0; > } > else > { > unhandled++; // first interrupt > interrupt_flag = 0; > while (unhandled) // handle interrupt, and others that may come in > { > do_isr_activity(); > unhandled--; > } > } > } > > Rufus
Usually, the ISR isn't reentrant, as it disables any further interrupts, so this wouldn't do anything. I was referring to a situation where there are many h/w interrupts, but where it was okay to occasionally miss one, for instance if the peripheral has a FIFO. If every interrupt is important, the OP needs to make sure the ISR is finished before the next interrupt is received.
Arlet wrote:
> ISR() > { > if( interrupt_flag ) > { > interrupt_flag = 0; > do_isr_activity(); > } > }
I have run into cases where I had problems with this code when the interrupt flag is a register on a PCI target. The code was just like this, only it looped to handle as many interrupt conditions as possible - replace "if" with "while" above. PCI would post the write, which would get backed off by target stop so long that the ISR had returned before the write finally posted. This sometimes cleared not only the current interrupt condition(s), but the next one as well resulting in a lost interrupt. I had accessed two different busses and assumed that I had some notion of the order in which the accesses would happen. Wrong. Now whenever I catch myself thinking "before" or "after" I stop and check for synchronization issues. - Tim.
"karthikbg" <karthik.balaguru@lntinfotech.com> wrote in message 
news:1166103394.859935.243690@j72g2000cwa.googlegroups.com...
> Hi, > > 1) I have 200 interrupts and the corresponding Interrupt service > routines for those. > > ISR () > { > If (INTERRUPT_FLAG == 1) > DO_ISR_ACTIVITY > INTERRUPT_FLAG = 0; > } > > When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the > interrupt gets fired, but not handled as it is at the end of ISR. How > to avoid this. > But, the clearing of the 'INTERRUPT_FLAG = 0' is required. > > So, one of the 200 interrupts does not get executed sometimes. > How to avoid the above problem ? > > 2) Further, i do suspect that an interrupt can come in the middle of > 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that > interrupt being left un-attended. > If this is the case, how to check this as there are 200 interrupts ?
First, check the data book carefully for the required style of interaction with the control register. Many micros have control registers interfaced in unusual ways where a RMW instruction can cause a pending interrupt to be lost (in the digital logic, if the interrupt becomes asserted appromixately during the M part of the instruction). Lost interrupts can easily be due to mishandling the type of statement you've called:
> INTERRUPT_FLAG = 0;
Second, as another poster mentioned, you want to rearrange things to: ISR () { If (INTERRUPT_FLAG == 1) { INTERRUPT_FLAG = 0; DO_ISR_ACTIVITY } } This covers the case where another interrupt occurs during the ISR. Third, you want to [in general] think about the paradigm you're using for dealing with the interrupts when they are occurring rapidly. One way to handle it is to use the two suggestions above and let the ISR be entered again and again if an interrupt is pending at the time you exit the ISR. This is fine if you can spare the context switch overhead. However, it may be more efficient to do two operations per ISR, which handles the interrupt latency "double-bounce" case (there is seldom a performance improvement from handling more than two operations per ISR, and I won't get into the reasons for that here). Then the pseudo-code would be: #define MAX (2) ISR () { int iteration = 0; while ((INTERRUPT_FLAG == 1) && (iteration < MAX)) { INTERRUPT_FLAG = 0; DO_ISR_ACTIVITY(); iteration++; } } Fourth, you need to be aware that interrupt-related issues are, as a rule of thumb, responsible for about 80% of the intermittent bugs in small systems. You need to pay careful attention to this. I do admire your style in posting just an abstraction of your problem (your post was brief and very readable). However, in this case, posting the entire ISR as well as identifying the micro would have been helpful. Dave.
vze24h5m@verizon.net wrote:
> Arlet wrote: > > karthikbg wrote: > > > > > Hi, > > > > > > 1) I have 200 interrupts and the corresponding Interrupt service > > > routines for those. > > > > > > ISR () > > > { > > > If (INTERRUPT_FLAG == 1) > > > DO_ISR_ACTIVITY > > > INTERRUPT_FLAG = 0; > > > } > > > > > > When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the > > > interrupt gets fired, but not handled as it is at the end of ISR. How > > > to avoid this. > > > But, the clearing of the 'INTERRUPT_FLAG = 0' is required. > > > > > > So, one of the 200 interrupts does not get executed sometimes. > > > How to avoid the above problem ? > > > > > > 2) Further, i do suspect that an interrupt can come in the middle of > > > 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that > > > interrupt being left un-attended. > > > If this is the case, how to check this as there are 200 interrupts ? > > > > How about something like this: > > > > ISR() > > { > > if( interrupt_flag ) > > { > > interrupt_flag = 0; > > do_isr_activity(); > > } > > } > > > > That way, when a new interrupt comes in while you're processing the old > > one, the interrupt flag will be set again. This assumes > > 'do_isr_activity()' can handle the case where multiple interrupts have > > been received. > > 200 interrupts is a HUGE # of interrupts! Do you really need that > many? > > I'd also make sure that interrupts are disabled at the start of the ISR > and restored at the end of the ISR. "do_isr_activity()" should also be > as short and simple as possible. Calling O/S routines from an ISR is > also not a good idea. > HTH > -Dave Pollum
I use nested interrupts, so it is not possible to disable the interrupts at the start of the ISR and restoring at the end of the ISR. Even though, we make the 'do_isr_activity()' short and simple, how to protect it when an interrupt arrives in that short span of time of execution of 'do_isr_activity()'. Regards, Karthik Balaguru
Arlet wrote:
> Rufus V. Smith wrote: > > > "Arlet" <usenet+5@ladybug.xs4all.nl> wrote in message > > news:1166104313.478604.162220@f1g2000cwa.googlegroups.com... > > > > > > karthikbg wrote: > > > > > >> Hi, > > >> > > >> 1) I have 200 interrupts and the corresponding Interrupt service > > >> routines for those. > > >> > > >> ISR () > > >> { > > >> If (INTERRUPT_FLAG == 1) > > >> DO_ISR_ACTIVITY > > >> INTERRUPT_FLAG = 0; > > >> } > > >> > > >> When i am doing the 'INTERRUPT_FLAG=0' in the above code, One of the > > >> interrupt gets fired, but not handled as it is at the end of ISR. How > > >> to avoid this. > > >> But, the clearing of the 'INTERRUPT_FLAG = 0' is required. > > >> > > >> So, one of the 200 interrupts does not get executed sometimes. > > >> How to avoid the above problem ? > > >> > > >> 2) Further, i do suspect that an interrupt can come in the middle of > > >> 'DO_ISR_ACTIVITY' routine and that can also cause a problem of that > > >> interrupt being left un-attended. > > >> If this is the case, how to check this as there are 200 interrupts ? > > > > > > How about something like this: > > > > > > ISR() > > > { > > > if( interrupt_flag ) > > > { > > > interrupt_flag = 0; > > > do_isr_activity(); > > > } > > > } > > > > > > That way, when a new interrupt comes in while you're processing the old > > > one, the interrupt flag will be set again. This assumes > > > 'do_isr_activity()' can handle the case where multiple interrupts have > > > been received. > > > > > > > This will handle receiving multiple interrupts > > during interrupt processing. > > > > ISR() > > { > > static int unhandled = 0; > > > > if (unhandled) > > { > > unhandled++; // buffering interrupt counts > > interrupt_flag = 0; > > } > > else > > { > > unhandled++; // first interrupt > > interrupt_flag = 0; > > while (unhandled) // handle interrupt, and others that may come in > > { > > do_isr_activity(); > > unhandled--; > > } > > } > > } > > > > Rufus > > Usually, the ISR isn't reentrant, as it disables any further > interrupts, so this wouldn't do anything. > > I was referring to a situation where there are many h/w interrupts, but > where it was okay to occasionally miss one, for instance if the > peripheral has a FIFO. > > If every interrupt is important, the OP needs to make sure the ISR is > finished before the next interrupt is received.
Thx for all your replies which have given some enough ideas. I do agree on this method/idea of coding change for nested hardware interrupts . ISR() { if( interrupt_flag ) { interrupt_flag = 0; do_isr_activity(); } } How do you say that there is a possibility of missing an interrupt ocassionaly. I do not find flaw in the above idea ? Do i miss anything ? I would like to clarify that i am talking about nested interrupts . But, Is the above method very suitable for handling some 121 software interrupts ? (Nested interrupts) Regards, Karthik Balaguru