-
Notifications
You must be signed in to change notification settings - Fork 0
/
irq.s
225 lines (197 loc) · 6.14 KB
/
irq.s
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
.global _start
.text
.equ CPSR_MODE_USER, 0x10
.equ CPSR_MODE_FIQ, 0x11
.equ CPSR_MODE_IRQ, 0x12
.equ CPSR_MODE_SVR, 0x13
.equ CPSR_MODE_ABORT, 0x17
.equ CPSR_MODE_UNDEFINED, 0x1B
.equ CPSR_MODE_SYSTEM, 0x1F
.equ CPSR_IRQ_INHIBIT, 0x80
.equ CPSR_FIQ_INHIBIT, 0x40
_start:
@ Vetor de interrupcoes
B _Reset
LDR pc, _undefined_instruction
LDR pc, _software_interrupt
LDR pc, _prefetch_abort
LDR pc, _data_abort
LDR pc, _not_used
LDR pc, _irq
LDR pc, _fiq
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
INTPND: .word 0x10140000 @Interrupt status register
INTSEL: .word 0x1014000C @interrupt select register( 0 = irq, 1 = fiq)
INTEN: .word 0x10140010 @interrupt enable register
TIMER0L: .word 0x101E2000 @Timer 0 load register
TIMER0V: .word 0x101E2004 @Timer 0 value registers
TIMER0C: .word 0x101E2008 @timer 0 control register
TIMER0X: .word 0x101E200c @timer 0 interrupt clear register
_Reset:
LDR r1, =0x1000 @ stack size
LDR r2, =stack_top
MOV sp, r2 @set svr stack
ADD r2, r2, r1 @ adds space on stack
MOV r0, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) @ load irq mode cpsr value
MSR cpsr_c, r0 @ go to irq mode
MOV sp, r2 @ set irq stack
MOV r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) @ load svr mode cpsr value
MSR cpsr_c, r0 @ go to svr mode
BL main
B .
undefined_instruction:
B .
software_interrupt:
B do_software_interrupt @vai para o handler de interrupções de software
prefetch_abort:
B .
data_abort:
B .
not_used:
B .
irq:
B do_irq_interrupt @vai para o handler de interrupções IRQ
fiq:
B .
do_software_interrupt: @Rotina de Interrupçãode software
ADD r1, r2, r3 @r1 = r2 + r3
MOV pc, r14 @volta p/ o endereço armazenado em r14
escolhe_pilha:
LDR r11, current_task
CMP r11, #0
LDREQ r12, =linhaA
CMP r11, #1
LDREQ r12, =linhaB
CMP r11, #2
LDREQ r12, =linhaC
MOV pc, lr
do_irq_interrupt: @Rotina de interrupções IRQ
SUB lr, lr, #4
STMFD sp!, {r11, lr}
STMFD sp!, {r12}
BL escolhe_pilha
LDMFD sp!, {r11} @ r11=r12
STMFD r12!, {r11}
LDMFD sp!, {r11} @ r11=r11
STMFD r12!, {r11}
STMFD r12!, {r0 - r10}
LDMFD sp!, {r1} @ r1=pc (lr)
MOV r0, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) @ load svr mode cpsr value
MSR cpsr_c, r0 @ go to srv mode
MOV r2, lr @ r2 = lr (r14)
MOV r3, sp @ r3 = sp (r13)
MOV r0, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) @ load irq mode cpsr value
MSR cpsr_c, r0 @ go to irq mode
MRS R0, spsr @ r0 = cpsr
STMFD r12!, {r0-r3} @ puts on linha sp lr pc cpsr
LDR r0, INTPND @Carrega o registrador de status de interrupção
LDR r0, [r0]
TST r0, #0x0010 @verifica se é uma interupção de timer
LDR r0, =current_task
LDR r1, [r0] @ load current_task value
LDR r2, =num_tasks
LDR r2, [r2] @ num_tasks
ADD r1, r1, #1
CMP r1, r2 @ num_tasks starts on 1 not zero. So if its equal, goes to 0
LDREQ r1, =0
STR r1, [r0] @ guarda o current_task
BL escolhe_pilha
SUB r12, r12, #68
LDMFD r12!, {r0-r3} @ pega os regs sp lr pc cpsr novos
BIC r0,r0,#0x80 @reativa a interrupção
MOV r4, #(CPSR_MODE_SVR | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) @ load svr mode cpsr value
MSR cpsr_c, r4 @ go to svr mode
MOV r3, sp @ recupera o sp da nova current_task
MOV r2, lr @ mesmo para o lr
MOV r4, #(CPSR_MODE_IRQ | CPSR_IRQ_INHIBIT | CPSR_FIQ_INHIBIT) @ load irq mode cpsr value
MSR cpsr_c, r4 @ go to irq mode
MSR spsr_cxsf, r0
STMFD sp!, {r1} @ pc
BL c_entry @vai para o rotina de tratamento da interupção de timer
LDMFD r12, {r0-r12} @retorna registradores ao estado anterior
LDMFD sp!, {pc}^
timer_init:
LDR r0, INTEN
LDR r1,=0x10 @bit 4 for timer 0 interrupt enable
STR r1,[r0]
LDR r0, TIMER0C
LDR r1, [r0]
MOV r1, #0xA0 @enable timer module
STR r1, [r0]
LDR r0, TIMER0V
MOV r1, #0x1f @setting timer value
STR r1,[r0]
MRS r0, cpsr
BIC r0,r0,#0x80
MSR cpsr_c,r0 @enabling interrupts in the cpsr
MOV pc, lr
setup_linhaB:
LDR r12, =linhaB
LDR r1, =0x1
LDR r2, =0x2
LDR r3, =0x3
LDR r4, =0x4
LDR r5, =0x5
LDR r6, =0x6
LDR r7, =0x7
LDR r8, =0x8
LDR r9, =0x9
LDR r10, =0x10
LDR r11, =0x12
STMFD r12!, {r11} @ stack r12
LDR r11, =0x11
STMFD r12!, {r0-r11} @ stack r0-r11
LDR r3, =stack_top
SUB r3, r3, #0x1000 @sp (r13)
LDR r2, =0x14 @ lr (r14)
LDR r1, =imp_taskB @pc (r15)
MRS r0, cpsr
BIC r0,r0,#0x80
STMFD r12!, {r0-r3} @ mock r12-r14. pc é o imp_taskB
MOV pc, lr
setup_linhaC:
LDR r12, =linhaC
LDR r1, =0x1
LDR r2, =0x2
LDR r3, =0x3
LDR r4, =0x4
LDR r5, =0x5
LDR r6, =0x6
LDR r7, =0x7
LDR r8, =0x8
LDR r9, =0x9
LDR r10, =0x10
LDR r11, =0x12
STMFD r12!, {r11} @ stack r12
LDR r11, =0x11
STMFD r12!, {r0-r11} @ stack r0-r11
LDR r3, =stack_top
SUB r3, r3, #0x1000 @ sp
LDR r2, =0x14 @ lr
LDR r1, =imp_taskC @ pc
MRS r0, cpsr
BIC r0,r0,#0x80
STMFD r12!, {r0-r3}
MOV pc, lr
main:
BL setup_linhaB
BL setup_linhaC
BL timer_init @initialize interrupts and timer 0
imp:
BL imp_taskA
B imp
@ r12 r11 r10 r9 r8 r7 r6 r5 r4 r3 r2 r1 0 sp lr pc cpsr
linhaA: .space 200
top_linhaA: .space 200
top_linhaB: .space 200
linhaB: .space 200
linhaC: .space 200
top_linhaC: .space 200
current_task: .word 0
num_tasks: .word 3