Interrupt Subsystem
- We have two strategies for getting input from an external device:
- Polling — continually watch for completion of an event.
- Interrupts — hardware generated subroutine call.
- Polling with the ADC involved a tight loop that watched for a change in the ADSC flag:
poll: sbic ADCSRA, ADSC ; skip if bit clear (ADC complete) rjmp poll in r16, ADCH
- Using interrupts allows the microcontroller to continue executing useful instructions.
- When an interrupt occurs:
- Completes current instruction.
- Saves program counter (PC) on the stack.
- Executes interrupt jump vector instruction (typically loads PC with the location of the Interrupt Service Routinue starting location).
- Executes Interrupt Service Routine (ISR).
- Returns to program when ISR encounters RETI instruction.
Interrupt Sources
The Interrupt Subsystem on the ATmega32 can receive interrupts from internal and external sources.
Internal Interrupt Sources
- Power Subsystem:
- Power on
- Reset
- Voltage low
- Timer/Counter Subsystem:
- Timer expired
- Counter match
- Analog to Digital Converter Subsystem:
- ADC complete
- Serial Communication Subsystem:
- Character received
- Character sent
- Covered in more detail in CS-3841: Design of Operating Systems.
External Interrupt Sources
- Anything that can generate an "on/off" signal.
- ATmega32 has 3 pins (PD2, PD3, PB2) that the controller "listens" for an external trigger.
Interrupt Vector Table
.cseg .org 0x00 rjmp start ; Interrupt Vector Table .org 0x2a start: ; ....
- The ATmega32 has approximately 20 interrupts.
- Each interrupt has a program memory location that stores a RJMP instruction that jumps to the ISR for the particular interrupt.
- The m32def.inc file has labels associated with each interrupt type
- Setting up the location of the ISR for the ADC, looks like this:
.org 0x00 rjmp start .org ADCCaddr rjmp adcISR .org 0x2a start: ; ... ; ISR for ADC subsystem adcISR: ; ...
The ATmega32 interrupt subsystem supports twenty one different kinds of interrupts:
Vector No. | Program Address | Label | Source | Interrupt |
---|---|---|---|---|
1 | 0x00 | — | RESET | Power-on Reset, etc... |
2 | 0x02 | INT0addr | INT0 | External Interrupt Request 0 |
3 | 0x04 | INT1addr | INT1 | External Interrupt Request 1 |
4 | 0x06 | INT2addr | INT2 | External Interrupt Request 2 |
5 | 0x08 | OC2addr | TIMER2 COMP | Timer/Counter2 Compare Match |
6 | 0x0A | OVF2addr | TIMER2 OVF | Timer/Counter2 Overflow |
7 | 0x0C | ICP1addr | TIMER1 CAPT | Timer/Counter1 Capture Event |
8 | 0x0E | OC1Aaddr | TIMER1 COMP A | Timer/Counter1 Compare Match A |
9 | 0x10 | OC1Baddr | TIMER1 COMP B | Timer/Counter1 Compare Match B |
10 | 0x12 | OVF1addr | TIMER1 OVF | Timer/Counter1 Overflow |
11 | 0x14 | OC0addr | TIMER0 COMP | Timer/Counter0 Compare Match |
12 | 0x16 | OVF0addr | TIMER0 OVF | Timer/Counter0 Overflow |
13 | 0x18 | SPIaddr | SPI STC | Serial Transfer Complete |
14 | 0x1A | URXCaddr | USART RXC | USART, Rx Complete |
15 | 0x1C | UDREaddr | USART UDRE | USART, Data Register Empty |
16 | 0x1E | UTXCaddr | USART TXC | USART, Tx Complete |
17 | 0x20 | ADCCaddr | ADC | ADC Conversion Complete |
18 | 0x22 | ERDYaddr | EE_RDY | EEPROM Ready |
19 | 0x24 | ACIaddr | ANA_COMP | Analog Comparator |
20 | 0x26 | TWIaddr | TWI | Two-wire Serial Interface |
21 | 0x28 | SPMRaddr | SPM_RDY | Store Program Memory Ready |
Enabling Interrupts
- Must enable the global interrupt flag.
- SREG has an I flag.
- Ways to set I flag (enable interrupts):
- SEI — Set Enable Interrupt.
- RETI — RETurn from Interrupt service routine (automatically sets the I flag.
- Ways to clear I flag (disable interrupts):
- CLI — clears the interrupt flag.
- Whenever the ATmega32 is reset, the I flag is cleared.
- Whenever an interrupt occurs, the I flag is cleared.
Interrupt Processing Steps
Setup:
- Must initialize the stack.
- Must set up the interrupt jump table.
- Must enable the global interrupt flag.
- Must enable particular local interrupt we are interested in.
When the interrupt occurs:
- Finish current instruction.
- Push current PC onto the stack.
- Clear I flag.
- Execute RJMP instruction in the Interrupt Vector Table.
- Execute the interrupt service routine.
- Execute RETI at end of ISR.
- Set I flag.
- Pop saved PC into the PC.
Interrupt Service Routine Guidelines
- Make it as short as possible.
- Push/Pop any registers that must be preserved onto the stack.
- Push/Pop SREG onto the stack.
push r0 in r0, SREG push r0 ; ... pop r0 out SREG, r0 pop r0
Sample Code
Here is a simple program that makes use of the interrupt subsystem to display the results of the ADC conversion on the LEDs.
; Author: t a y l o r@msoe.edu ; Date: 4-23-2007 ; Filename: adcIntDemo.asm ; ; This program uses the ADC subsystem and the interrupt subsystem ; to take the analog signal on ADC channel 0 and display its digital ; representation on the LEDs. ; Hardware configuration: ; - PORTB connected to LEDs. ; - PORTA pin 0 connected to analog source. .nolist .include "m32def.inc" .list .def temp = r16 ; Use r16 as a temp register .cseg .org 0x00 rjmp stackInit .org ADCCaddr ; Jump vector for ADC interrupts rjmp adcISR .org 0x2a stackInit: ldi temp, HIGH(RAMEND-0x20) out SPH, temp ldi temp, LOW(RAMEND-0x20) out SPL, temp start: ldi temp, 0xff ; Configure PORTB as output out DDRB, temp cbi DDRA, 0 ; Configure PORTA as input rcall adcIntInit0 sbi ADCSRA, ADSC ; Start AD conversion ; Program just loops forever doing nothing (until interrupted) forever: rjmp forever ; Initialize ADC for single ended conversion on ADC channel 0 ; with interrupt subsystem enabled. adcIntInit0: .def temp = r16 push temp ; Set ADC reference voltage, put in 8-bit mode and select channel 0 ldi temp, 0b01100000 out ADMUX, temp ; Enable ADC and ADC interrupts, prescale factor = 128 ldi temp, 0b10001111 out ADCSRA, temp sei ; Enable global interrupt flag pop temp ret ; Interrupt Service Routine for ADC subsystem ; Takes result of ADCH and sends compliment of the result ; (since LED are active low) to the LEDs on PORTB and then ; starts the ADC all over again. ; Assumptions: ; - ADC and Interrupt subsystems have been initialized. ; - Using ADC channel 0. ; - Using only 8 MSB of ADC result. ; - PORTB is configured as output. ; Hardware configuration: ; - Analog input source is connected to PORTA pin 0. ; - PORTB connected to active low LEDs. adcISR: push temp in temp, SREG ; Capture status register push temp in temp, ADCH out PORTB, temp sbi ADCSRA, ADSC ; Start ADC again pop temp out SREG, temp ; Restore status register pop temp reti