4.9.2.7 Reset and Interrupt Handling
The AVR provides several different interrupt sources. These interrupts and the separate reset
vector each have a separate program vector in the program memory space. All interrupts
have individual enable bits that must be written to logic ‘1
’ together
with the global interrupt enable bit in the status register to enable the interrupt.
Depending on the program counter value, interrupts may be automatically disabled when
the boot lock bits BLB02 or BLB12 are programmed. This feature improves the firmware
security. See Program and Data Memory Lock Bits from Related Links.
The lowest addresses in the program memory space are defined by default as the reset and interrupt vectors. For the complete list of vectors, see Specific Interrupts Handling from Related Links. The list also determines the priority levels of the different interrupts. The lower the address, the higher the priority level. RESET has the highest priority, followed by INT0, which is the External Interrupt Request 0.
The interrupt vectors can be moved to the start of the boot section by setting the IVSEL bit in the MCU control register (MCUCR). The interrupt vectors can also be moved by modifying the BOOTRST fuse. See Fuse Low Byte from Related Links.
When an interrupt occurs, the I bit is cleared and all interrupts are disabled. The application software can write a logic ‘1
’ 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.
In addition, the SPIIO bit in MCUCR allows all interrupts except the SPI interrupts to be blocked. This can be set in the interrupt routine and then the I bit can be enabled without having many different interrupt sources able to disturb the interrupt execution. This feature allows for reliable and fast SPI speeds, thus shortening SPI transfers and lowering system power consumption.
There are two basic types of interrupts. The first type is triggered by an event that sets the interrupt flag. For these interrupts, the program counter is vectored to the actual interrupt vector to execute the interrupt handling routine, and hardware clears the corresponding interrupt flag. Interrupt flags can also be cleared by writing a logic ‘1
’ to the flag bit position(s). If an interrupt condition occurs while the corresponding interrupt enable bit is cleared, the interrupt flag is 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) is set and remembered until the global interrupt enable bit is set, and is, then, executed by order of priority.
The second type of interrupts triggers 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 is not triggered.
When the AVR exits from an interrupt, it always returns to the main program and executes one more instruction before any pending interrupt is served.
When using the CLI instruction to disable interrupts, the interrupts are immediately disabled. No interrupt is executed after the CLI instruction, even if it occurs simultaneously with the CLI instruction. The following example shows how this can be used to avoid interrupts during the timed EEPROM write sequence.
Assembly Code Example |
in r16, SREG; store SREG value cli ; disable interrupts during timed sequence sbi EECR, EEMWE; start EEPROM write sbi EECR, EEWE out SREG, r16; restore SREG value (I bit) |
C Code Example |
char cSREG; cSREG = SREG; /* store SREG value */ /* disable interrupts during timed sequence */ _CLI(); EECR |= (1<<EEMWE); /* start EEPROM write */ EECR |= (1<<EEWE); SREG = cSREG; /* restore SREG value (I bit) */ |
When using the SEI instruction to enable interrupts, the instruction following SEI is executed before any pending interrupts (see the following example).
Assembly Code Example |
sei; set Global Interrupt Enable sleep; enter sleep, waiting for interrupt ; note: will enter sleep before any pending interrupt(s) |
C Code Example |
_SEI(); /* set Global Interrupt Enable */ _SLEEP(); /* enter sleep, waiting for interrupt */ /* note: will enter sleep before any pending interrupt(s) */ |
Interrupt Response Time
The interrupt execution response for all the enabled AVR interrupts is a minimum of four clock cycles. After four clock cycles, the program vector address for the actual interrupt handling routine is executed. During this four-clock-cycle period, the program counter is pushed onto the stack. The vector is normally a jump to the interrupt routine lasting three clock cycles. If an interrupt occurs during execution of a multi-cycle instruction, this instruction is completed before the interrupt is served. If an interrupt occurs when the MCU is in Sleep mode, the interrupt execution response time is increased by four clock cycles. This increase comes in addition to the start-up time from the selected sleep mode.
A return from an interrupt handling routine takes four clock cycles. During these four clock cycles, the program counter (two bytes) is popped back from the stack, the stack pointer is incremented by two and the I bit in SREG is set.