-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlab6_interrupts.asm
More file actions
190 lines (175 loc) · 5.87 KB
/
Copy pathlab6_interrupts.asm
File metadata and controls
190 lines (175 loc) · 5.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
;==============================================================================
; Lab 6 - External Interrupts, Priority, and the Interrupt Vector Table
; Target : ATmega32 on STK500 (JTAGICE mkII)
; Clock : 1 MHz (internal RC default) -- adjust delayIt if F_CPU differs
;
; Behavior:
; Main loop free-runs a 1-second up-counter on PORTA (LEDs, active-low).
; Three external interrupts, all falling-edge triggered, each flash a
; signature pattern on the LEDs five times before returning to the count:
; INT0 -> 0x03
; INT1 -> 0xC0
; INT2 -> 0xAA
;
; Hardware priority is fixed by the vector table: INT0 > INT1 > INT2.
; Because each ISR runs with global interrupts disabled (the I-bit is
; cleared on entry and only restored by RETI), an ISR cannot itself be
; pre-empted. A trigger that arrives mid-service only sets the pending
; flag, and is serviced after RETI according to vector priority.
;
; Notes vs. original report:
; * The report's discussion said "positive edge triggered"; the actual
; MCUCR value (0x0A) selects FALLING edge for INT0/INT1. Comment fixed.
; * ISRs now save BOTH a scratch register AND SREG correctly (the original
; pushed R3, used R3 to hold SREG, then popped R3 -- which works, but is
; fragile. Here R16 is the scratch and SREG is preserved cleanly.)
;==============================================================================
.include "m32def.inc"
; 1,000,000 cycles / (10 cycles per Delay1 pass) = 100000 for a 1 s tick @ 1MHz
.equ delayIt = 100000
;------------------------------------------------------------------------------
; Interrupt Vector Table
;------------------------------------------------------------------------------
.org 0x0000
jmp Start ; Reset
.org INT0addr
jmp int_0 ; External Interrupt 0
.org INT1addr
jmp int_1 ; External Interrupt 1
.org INT2addr
jmp int_2 ; External Interrupt 2
.org 0x002A ; first address past the vector table on ATmega32
;------------------------------------------------------------------------------
; Reset / Initialization
;------------------------------------------------------------------------------
Start:
ldi r16, low(RAMEND) ; initialize stack pointer
out SPL, r16
ldi r16, high(RAMEND)
out SPH, r16
cbi DDRD, 2 ; INT0 (PD2) as input
cbi DDRD, 3 ; INT1 (PD3) as input
cbi DDRB, 2 ; INT2 (PB2) as input
sbi PORTD, 2 ; enable pull-ups so idle line reads high
sbi PORTD, 3
sbi PORTB, 2
ldi r16, 0x0A ; ISC11:ISC10=10, ISC01:ISC00=10 -> falling edge
out MCUCR, r16
ldi r16, 0x00 ; ISC2=0 -> INT2 falling edge
out MCUCSR, r16
ldi r16, 0xFF ; PORTA all outputs (LEDs)
out DDRA, r16
ldi r16, (1<<INT1)|(1<<INT0)|(1<<INT2) ; local enables: GICR=0xE0
out GICR, r16
sei ; global interrupt enable
clr r16 ; counter starts at 0
;------------------------------------------------------------------------------
; Main loop: 1 Hz up-counter on the LEDs (active-low, so complement)
;------------------------------------------------------------------------------
Loop:
inc r16
mov r2, r16
com r2 ; LEDs are active-low
out PORTA, r2
rcall Delay
rjmp Loop
;------------------------------------------------------------------------------
; Delay ~1 second @ 1 MHz. Inner pass is 10 cycles (6 NOP + SUBI/SBCI*2 + BRNE)
;------------------------------------------------------------------------------
Delay:
push r17
push r18
push r19
ldi r17, low(delayIt)
ldi r18, byte2(delayIt)
ldi r19, byte3(delayIt)
Delay1:
nop
nop
nop
nop
nop
nop
subi r17, 1
sbci r18, 0
sbci r19, 0
brne Delay1
pop r19
pop r18
pop r17
ret
;------------------------------------------------------------------------------
; ISR helper: flash the pattern in r21 five times, one second apart.
; Expects the (active-high) pattern in r21 on entry. Clobbers r20,r21 -- both
; r22 are saved/restored by each ISR wrapper below.
;------------------------------------------------------------------------------
FlashFive:
ldi r20, 5
FlashLoop:
mov r22, r21 ; copy the requested pattern
com r22 ; active-low for the LEDs
out PORTA, r22
rcall Delay
ldi r22, 0xFF ; all LEDs off between flashes
out PORTA, r22
rcall Delay
dec r20
brne FlashLoop
ret
;------------------------------------------------------------------------------
; INT0 service routine -> pattern 0x03
;------------------------------------------------------------------------------
int_0:
push r16
in r16, SREG
push r16
push r20
push r21
push r22
ldi r21, 0x03
rcall FlashFive
pop r22
pop r21
pop r20
pop r16
out SREG, r16
pop r16
reti
;------------------------------------------------------------------------------
; INT1 service routine -> pattern 0xC0
;------------------------------------------------------------------------------
int_1:
push r16
in r16, SREG
push r16
push r20
push r21
push r22
ldi r21, 0xC0
rcall FlashFive
pop r22
pop r21
pop r20
pop r16
out SREG, r16
pop r16
reti
;------------------------------------------------------------------------------
; INT2 service routine -> pattern 0xAA
;------------------------------------------------------------------------------
int_2:
push r16
in r16, SREG
push r16
push r20
push r21
push r22
ldi r21, 0xAA
rcall FlashFive
pop r22
pop r21
pop r20
pop r16
out SREG, r16
pop r16
reti