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

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

Reply to
karthikbg
Loading thread data ...

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.

Reply to
Arlet

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

Reply to
vze24h5m

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

Reply to
Rufus V. Smith

Reading and writing unhandled in a nested interrupt? Is write access atomic?

Regards, Richard.

  • formatting link
  • formatting link
    for Cortex-M3, ARM7, ARM9, HCS12, H8S, MSP430 Microblaze, Coldfire, AVR, x86, 8051, PIC24 & dsPIC
Reply to
FreeRTOS.org

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.

Reply to
Arlet

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.

Reply to
tbroberg

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:

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.

Reply to
David T. Ashley

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

Reply to
karthikbg

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

Reply to
karthikbg

I find this method to be fine. Have you tried this method practically ?

Is this method for handling(processing) a large number of software interrupts ? How to use this method w.r.t Processing of many Hardware Interrupts at a rapid phase ?

Thx in advans, Karthik Balaguru

Reply to
karthikbg

Hi , I am interested in knowing the interrupt-latency "double-bounce" case and the performance conditions w.r.t it. Kindly share some links/docs/ideas regarding that.

Thx in advans, Karthik Balaguru

Reply to
karthikbg

This is a nested interrupt scenario here. I cannot disable interrupts as every interrupt is important to be handled . There can be different critical alarm interrupts generated from my board during the execution of that part of the code and so, interrupts cannot be disabled during that time. The interrupt has to be handled during that code.

So, it is nested interrupt scenario and handling all the interrupts . There are large number of hardware interrupts.

Thx in advans, Karthik Balaguru

Reply to
karthikbg

So if you don't want interrupts during that code, disable them. What is the problem with doing that?

Is the problem caused by different interrupt types or the same interrupt type?

--
Thad
Reply to
Thad Smith

On many systems one must disable interrupts just before returning from an interrupt routine. The compiler genrated code for cleaning up the interrupt stack often is not re-entrant. i.e.

void ISR(void) { enabled_ints(); /* Allow nested interrupts */ do_isr_activity(); disable_ints(); /* Make sure cleanup code is not interrupted */ /* reti instruction or equivalent will restore interrupts */ }

Regards Anton Erasmus

Reply to
Anton Erasmus

Most but not all systems that have sources of interrupt have a characteristic minimum spacing between assertion of each interrupt. For a communication peripheral, this might be the minimum spacing between the arrival of characters, data packets, CAN messages, etc.

Similarly, these systems tend to have the possibility that the interrupt can occur at the maximum rate indefinitely.

The system typically has to be designed so that if an interrupt is asserted, the ISR begins to run in time to avoid losing data. For most types of peripherals (UARTS, etc.), this means that critical sections plus higher-priority interrupts can't add up to more than (for example) one or two received characters (depending on how deeply buffered the UART is).

Additonally, the ISR typically has to "consume" at a faster rate than the interrupt source can "produce".

What this means in practice is that it is fairly rare to have a system where repeating the ISR body more than once or twice has an effect on performance. If the system meets its real-time constraints to begin with (specifically, interrupt latency), then when the ISR begins to run, there can't be more than one or two characters queued up (in the case of a UART). If such a scenario were possible, it contradicts a prudent real-time design.

There are exceptions, of course. A _deeply_ buffered peripheral violates this rule of thumb. This allows for a large interrupt latency.

For most ISRs, something like the following (a single repetition) will do.

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

if (INTERRUPT_FLAG = 1) { INTERRUPT_FLAG = 0; DO_ISR_ACTIVITY(); } }

This is, of course, not an immutable rule--just a practical tendency. There are some very substantial exceptions.

Dave.

Reply to
David T. Ashley

The need for nested interrupts is a sign of too long interrupt service routines. How long are your ISRs ? 10, 50 200 or 1000 machine instructions ?

What kind of hardware is used ? Is the interrupt requests inputs edge sensitive or level sensitive ? If level sensitive, is the interrupt request pulse shorter than the worst case ISR latency, i.e. the interrupt request may be removed before being handled. Are there any hardware to prioritise the 200 interrupt requests or are they all ORed into a single interrupt request pin, and if so, how du you know which interrupt source is active ?

Avoiding nested interrupt by disabling interrupts during an ISR is not a bad idea, provided that the ISR is _short_ (say 10-20 instructions) and that the hardware retains the interrupt request from an other source, when an other interrupt source is being serviced. When the first ISR returns and restores the stack, it is again interrupted by the other interrupt source, which had issued the request during the service of the first ISR. A hardware prioritised interrupt request system will ensure that the _next_ ISR executed after the current active ISR is the one with the highest priority (and provide the proper interrupt vector), even if the request was the last request activated during the execution of the current ISR.

With such a huge number of interrupt request sources, the hardware _must_ be designed to properly manage the large number of requests. Without proper hardware, no software tricks are going to make the system reliable. It may work in most cases, but it does not work in _all_ situations.

Paul

Reply to
Paul Keinanen

Just nit-picking but ... deep buffering only helps absorb bursty activity, allowing the processing of data bursts to be deferred. However, the overall "average" data rate cannot exceed the ability of the system to process the data without the data buffer overflowing.

Just stating the obvious ;-)

--
Michael N. Moran           (h) 770 516 7918
5009 Old Field Ct.         (c) 678 521 5460
Kennesaw, GA, USA 30144    http://mnmoran.org

"So often times it happens, that we live our lives in chains
  and we never even know we have the key."
The Eagles, "Already Gone"

The Beatles were wrong: 1 & 1 & 1 is 1
Reply to
Michael N. Moran

Believe it or not, I've had colleagues earlier in my career who failed to get the point that you made above.

Reply to
David T. Ashley

This is the classic shared data problem. The solution is to ensure the INTERRUPT_FLAG = 0; operation is atomic i.e cannot be interrupted once started. There are two ways to do this. The first is to use an atomic microprocessor instruction rather than a C statement which might consist of several microprocessor instructions. The second is to disable interrupts just before clearing the flag and enable them immediately after. The first method is preferable IMV.

Depends on the micro. Some will store the fact the interrupt occurred and service it next time interrupts are enabled. Others will just ignore and lose it. This is why the first rule of real time is keep interrupt routines as short as possible.Think about moving some of the functionality of the ISR out into the background.

Ian

Reply to
Ian Bell

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.