Interrupts (ATmega328P)
Psuedo-code showing hardware behavior:
while (true)
{
if (isInterruptConditionMet())
{
interruptFlag = 1
}
if (interruptFlag == 1 && globalEnableBit == 1 && enableBit == 1)
{
interruptFlag = 0
globalEnableBit = 0
interruptFunction()
globalEnableBit = 1
}
}
globalEnableBit
:
Global interrupt enable bit. I-bit (7th bit) in SREG
(status register).
enableBit
:
Individual interrupt enable bit. For example,
Timer/Counter0 overflow interrupt is enabled by setting
TOIE0
(Timer/Counter0 Overflow Interrupt Enable bit)
in TIMSK0
(Timer/Counter0 Interrupt Mask register).
interruptFlag
Individual interrupt flag. For example,
Timer/Counter0 overflow flag is TOV0
(Timer/Counter0 Overflow Flag) in
TIFR0
(Timer/Counter 0 Interrupt Flag register).
Observations
- Interrupts are automatically disabled when entering interrupt function and
re-enabled when it ends. This prevents nested interrupts
(jumping to a different interrupt while the current interrupt function is still
in progress). Nested interrupts may cause stack overflow.
- Flag is set even while interrupt is disabled.
Whether the flag will be set or not has nothing to do with the current
interrupt enable settings.
- Interrupt function can be called even for events that happened
(interrupt conditions that were met in the past) while it was disabled.
If the flag is set but interrupt is disabled, the interrupt function
will be called as soon as the interrupt is enabled back again.
It may appear as though the interrupt function is called even
though the condition is not met. A solution is to clear the interrupt
flag before enabling the interrupt.
- Interrupt flag is automatically cleared when entering interrupt function.
- If the interrupt condition is met multiple times while that
interrupt is disabled, interrupt function will be called only once
for that interrupt when it is re-enabled.
For example, if a button press is configured as an interrupt
and that button is pressed multiple times while that interrupt
function is still executing, the interrupt function will be called
only once after the current call returns.
It can be said that this microcontroller has an interrupt queue of length 1.
For every interrupt that has a flag, there can be one pending
interrupt function call.