1

This seems like a simple question but I'm not finding an answer so far: at a high level, say I have a timer interrupt and some input interrupt. The input arrives, the ISR is entered, interrupts are (automatically by default?) disabled, I service the input (quickly!), but while that's going on a timer used for some other purpose fires. I don't want to miss that timer but because interrupts are disabled my input processing won't get interrupted for it.

I exit the input ISR and interrupts are (automatically?) re-enabled. Assuming the timer is uncomplicated (it wouldn't overflow twice during my input ISR) how do I accurately handle the fact that it overflowed during my input ISR and I "missed" it?

Would this differ if instead of the timer I simply had a second input2 that similarly might fire during my input1 processing (but would present a useful input long enough to process after input1, presuming I knew it triggered)?

I'm not looking to nest interrupts here, just to understand what happens when an interrupt happens during another ISR which has temporarily disabled them - do they pend and fire after the blocking ISR returns, or are they just lost?

1

Q1:

... exit the input ISR and interrupts are (automatically?) re-enabled

Yes, the RETI (return from interrupt) instruction enables interrupts. See third paragraph of section 7.7 in Atmel's document #8271 (a 650-page spec sheet for the Atmega 48, 88, 168, 328 series), which says:

When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is executed.

Q2:

Assuming the timer is uncomplicated (it wouldn't overflow twice during my input ISR) how do I accurately handle the fact that it overflowed during my input ISR and I "missed" it?

If the timer is running a clock, set the timer control bits to automatically reload the count register upon each overflow (or underflow). That will leave a full count period for processing each timer interrupt.

That is, you can pre-load a next-timer-count (I think it can be different from the current count if necessary), so the timer can start its next interval automatically. If the timer is used for some purpose more complicated than that, you may need a nested interrupt.

Q3:

Would this differ if instead of the timer I simply had a second input2 that similarly might fire during my input1 processing (but would present a useful input long enough to process after input1, presuming I knew it triggered)?

If indeed input2 sticks around long enough to process after input1 processing is done, no problem. Its interrupt will occur after the first interrupted code sequence executes one more instruction after the RETI occurs. (See paragraph 6 of section 7.7 in doc8271.)

If input2 is brief, several different things can happen. (a) If it is shorter than a clock cycle, in general it won't trigger an interrupt. (b) If it is a level-interrupt-triggering event on INT0 or INT1 that ends while another interrupt is being processed, it won't trigger an interrupt. (See discussion on page 72, section 13.2.3, of doc8271 of INTF0 and INTF1 being clear for level interrupts.) (c) If it is an interrupt-flag-setting event that sets a flag and ends while another interrupt is being processed, it will trigger an interrupt after the global interrupt flag is set, unless current processing clears its flag.

I think the above accurately states what happens on Atmega devices, but I suggest you also see doc8271 – and run tests – to see for yourself. Here is part of what paragraphs 4 and 5 of section 7.7 in doc8271 say regarding (b) and (c):

There are basically two types of interrupts. The first type is triggered by an event that sets the Interrupt Flag. ... Interrupt Flags can also be cleared by writing a logic one to the flag bit position(s) to be cleared. If an interrupt condition occurs while the corresponding interrupt enable bit is cleared, the Interrupt Flag will be set and remembered until the interrupt is enabled, or the flag is cleared by software. Similarly, if one or more interrupt conditions occur while the Global Interrupt Enable bit is cleared, the corresponding Interrupt Flag(s) will be set and remembered until the Global Interrupt Enable bit is set, and will then be executed by order of priority.

The second type of interrupts will trigger as long as the interrupt condition is present. These interrupts do not necessarily have Interrupt Flags. If the interrupt condition disappears before the interrupt is enabled, the interrupt will not be triggered.

  • So, based on some slow timer I need to do some background task, but one in a while I'll get an input during which the timer interrupt would've fired, but because I was processing that input (though quickly) I missed the timer's interrupt. Will the timer overflow interrupt stay flagged so that I can process it after I return from my ISR? (Similarly once triggered will the interrupt for input2 be ready for processing after input1 is done, even if data is a bit stale?) I (think) I see the point about reloading the timer, but that seems like it'd skew timings unnecessarily. – MartyMacGyver Nov 6 '15 at 17:57
  • Actually, that might fall under the "input flag setting event" thing above. – MartyMacGyver Nov 6 '15 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.