FreeCalypso > hg > freecalypso-sw
comparison gsm-fw/nucleus/demo/irqshell.S @ 143:afceeeb2cba1
Our nuc-fw is destined to become gsm-fw, so I went ahead and did the big hg mv
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 12 Nov 2013 05:35:48 +0000 |
parents | nuc-fw/nucleus/demo/irqshell.S@85994b210f6a |
children |
comparison
equal
deleted
inserted
replaced
142:15d5977390c2 | 143:afceeeb2cba1 |
---|---|
1 /* | |
2 * FreeNucleus Calypso port by Michael Spacefalcon | |
3 * | |
4 * This assembly module contains IRQ handler shell | |
5 * and some closely related support functions. | |
6 * | |
7 * The approach to IRQ handling implemented in the present version | |
8 * is exactly the same as was found in XVilka's original nucleus_plus.tar.gz | |
9 * code targeting OMAP1510. I personally consider it very dumb and | |
10 * suboptimal, but the present version is merely a proof of concept - | |
11 * changing as little as possible from our starting point will (hopefully) | |
12 * make it easier to get this code to compile, link and maybe even run. | |
13 */ | |
14 | |
15 #include "asm_defs.h" | |
16 #include "calirq.h" | |
17 | |
18 .code 32 | |
19 | |
20 /* | |
21 ********************************** | |
22 * GLOBAL VARIABLE DECLARATIONS * | |
23 ********************************** | |
24 */ | |
25 | |
26 .data | |
27 | |
28 @ Define vector table used by INT_IRQ to branch to necessary ISR | |
29 | |
30 .globl INT_IRQ_Vectors | |
31 INT_IRQ_Vectors: | |
32 .word INT_Interrupt_Shell @ Vector 0 | |
33 .word INT_Interrupt_Shell @ Vector 1 | |
34 .word INT_Timer_Interrupt @ Vector 2 - TIMER2 | |
35 .word INT_Interrupt_Shell @ Vector 3 | |
36 .word INT_Interrupt_Shell @ Vector 4 | |
37 .word INT_Interrupt_Shell @ Vector 5 | |
38 .word INT_Interrupt_Shell @ Vector 6 | |
39 .word INT_Interrupt_Shell @ Vector 7 | |
40 .word INT_Interrupt_Shell @ Vector 8 | |
41 .word INT_Interrupt_Shell @ Vector 9 | |
42 .word INT_Interrupt_Shell @ Vector 10 | |
43 .word INT_Interrupt_Shell @ Vector 11 | |
44 .word INT_Interrupt_Shell @ Vector 12 | |
45 .word INT_Interrupt_Shell @ Vector 13 | |
46 .word INT_Interrupt_Shell @ Vector 14 | |
47 .word INT_Interrupt_Shell @ Vector 15 | |
48 .word INT_Interrupt_Shell @ Vector 16 | |
49 .word INT_Interrupt_Shell @ Vector 17 | |
50 .word INT_Interrupt_Shell @ Vector 18 | |
51 .word INT_Interrupt_Shell @ Vector 19 | |
52 .word INT_Interrupt_Shell @ Vector 20 | |
53 | |
54 @ Define the order in which the interrupts will be executed by software(INT_IRQ) | |
55 @ Level 1 Interrupt Handler | |
56 .globl INT_IRQ_Priority | |
57 INT_IRQ_Priority: | |
58 .word 0 | |
59 .word 1 | |
60 .word 2 | |
61 .word 3 | |
62 .word 4 | |
63 .word 5 | |
64 .word 6 | |
65 .word 7 | |
66 .word 8 | |
67 .word 9 | |
68 .word 10 | |
69 .word 11 | |
70 .word 12 | |
71 .word 13 | |
72 .word 14 | |
73 .word 15 | |
74 .word 16 | |
75 .word 17 | |
76 .word 18 | |
77 .word 19 | |
78 .word 20 | |
79 INT_Priority_End: | |
80 | |
81 .text | |
82 | |
83 /* | |
84 ************************************************************************ | |
85 * | |
86 * FUNCTION | |
87 * | |
88 * INT_Setup_Vector | |
89 * | |
90 * DESCRIPTION | |
91 * | |
92 * This function sets up the specified vector with the new vector | |
93 * value. The previous vector value is returned to the caller. | |
94 * | |
95 * | |
96 * Major Revision: | |
97 * | |
98 * M. Kyle Craig, Accelerated Technology, Inc. | |
99 * | |
100 * | |
101 * | |
102 * CALLED BY | |
103 * | |
104 * Application | |
105 * TCC_Register_LISR Register LISR for vector | |
106 * | |
107 * CALLS | |
108 * | |
109 * None | |
110 * | |
111 * INPUTS | |
112 * | |
113 * vector Vector number to setup | |
114 * new Pointer to new assembly | |
115 * language ISR | |
116 * | |
117 * OUTPUTS | |
118 * | |
119 * old vector contents | |
120 * | |
121 * HISTORY | |
122 * | |
123 * NAME DATE REMARKS | |
124 * | |
125 * W. Lamie 08-27-1994 Created initial version 1.0 | |
126 * D. Lamie 08-27-1994 Verified version 1.0 | |
127 * | |
128 ************************************************************************ | |
129 */ | |
130 | |
131 @VOID *INT_Setup_Vector(INT vector, VOID *new) | |
132 @{ | |
133 | |
134 .globl INT_Setup_Vector | |
135 INT_Setup_Vector: | |
136 | |
137 @VOID *old_vector; /* Old interrupt vector */ | |
138 @VOID **vector_table; /* Pointer to vector table */ | |
139 | |
140 @ Calculate the starting address of the actual vector table. | |
141 @ vector_table = (VOID **) 0; | |
142 | |
143 @ Pickup the old interrupt vector. | |
144 @ old_vector = vector_table[vector]; | |
145 @ | |
146 @ Setup the new interrupt vector. | |
147 @ vector_table[vector] = new; | |
148 @ | |
149 @ Return the old interrupt vector. | |
150 @ return(old_vector); | |
151 | |
152 | |
153 LDR r2, =INT_IRQ_Vectors @ Load the vector table address | |
154 MOV r0, r0, LSL #2 @ Multiply vector by 4 to get offset into table | |
155 LDR r3, [r2,r0] @ Load the old pointer | |
156 STR r1, [r2,r0] @ Store the new pointer into the vector table | |
157 | |
158 MOV r0, r3 @ Put the old pointer into the return register | |
159 | |
160 BX lr @ Return to caller | |
161 | |
162 @} | |
163 | |
164 /* | |
165 ************************************************************************ | |
166 * | |
167 * FUNCTION | |
168 * | |
169 * INT_Retrieve_Shell | |
170 * | |
171 * DESCRIPTION | |
172 * | |
173 * This function retrieves the pointer to the shell interrupt | |
174 * service routine. The shell interrupt service routine calls | |
175 * the LISR dispatch routine. | |
176 * | |
177 * | |
178 * Major Revision: | |
179 * | |
180 * M. Kyle Craig, Accelerated Technology, Inc. | |
181 * | |
182 * | |
183 * | |
184 * CALLED BY | |
185 * | |
186 * TCC_Register_LISR Register LISR for vector | |
187 * | |
188 * CALLS | |
189 * | |
190 * None | |
191 * | |
192 * INPUTS | |
193 * | |
194 * vector Vector number to setup | |
195 * | |
196 * OUTPUTS | |
197 * | |
198 * shell pointer | |
199 * | |
200 * HISTORY | |
201 * | |
202 * NAME DATE REMARKS | |
203 * | |
204 * W. Lamie 08-27-1994 Created initial version 1.0 | |
205 * D. Lamie 08-27-1994 Verified version 1.0 | |
206 * | |
207 ************************************************************************ | |
208 */ | |
209 | |
210 @VOID *INT_Retrieve_Shell(INT vector) | |
211 @{ | |
212 | |
213 .globl INT_Retrieve_Shell | |
214 INT_Retrieve_Shell: | |
215 | |
216 @ Return the LISR Shell interrupt routine. | |
217 @ return(INT_Vectors[vector]); | |
218 | |
219 LDR r1, =INT_IRQ_Vectors @ Load the vector table address | |
220 MOV r0, r0, LSL #2 @ Multiply vector by 4 to get offset into table | |
221 LDR r0, [r1,r0] @ Load interrupt handler pointer into return register | |
222 | |
223 BX lr @ Return to caller | |
224 | |
225 | |
226 @} | |
227 | |
228 /* | |
229 ************************************************************************ | |
230 * | |
231 * FUNCTION | |
232 * | |
233 * _INT_IRQ | |
234 * | |
235 * DESCRIPTION | |
236 * | |
237 * This routine is the board-specific section for | |
238 * level 1 interrupt handling | |
239 * | |
240 * CALLED BY | |
241 * | |
242 * None | |
243 * | |
244 * CALLS | |
245 * | |
246 * TMT_Timer_Interrupt | |
247 * | |
248 * INPUTS | |
249 * | |
250 * None | |
251 * | |
252 * | |
253 * OUTPUTS | |
254 * | |
255 * None | |
256 * | |
257 * HISTORY | |
258 * | |
259 * NAME DATE REMARKS | |
260 * | |
261 * B. Ronquillo 05-10-00 Created initial version 1.0 | |
262 * | |
263 ************************************************************************ | |
264 */ | |
265 | |
266 .globl _INT_IRQ | |
267 _INT_IRQ: | |
268 | |
269 STMDB sp!,{r0-r4} @ Save r0-r4 on temporary IRQ stack | |
270 SUB lr,lr,#4 @ Adjust IRQ return address | |
271 | |
272 /* | |
273 ******************************** | |
274 * Begin Hardware Specific Code * | |
275 ******************************** | |
276 */ | |
277 | |
278 LDR r3, =INTH_BASE_ADDR @ load Interrupt Control Base | |
279 @ Get enable register value | |
280 @ original instr was: LDR r4, [r3,#INT_CNTRL_MIR] | |
281 @ but on the Calypso we have to read two 16-bit regs | |
282 ldrh r0, [r3, #MASK_IT_REG1] | |
283 ldrh r1, [r3, #MASK_IT_REG2] | |
284 @ now combine them into a 32-bit word in r4 for the old code to work as-is | |
285 orr r4, r0, r1, lsl #16 | |
286 | |
287 /* | |
288 ****************************** | |
289 * End Hardware Specific Code * | |
290 ****************************** | |
291 */ | |
292 | |
293 STMDB sp!,{r4} @ Put the enable register value on the IRQ stack | |
294 MVN r4,#0 @ Start with 0xFFFFFFFF to allow nesting of interrupts | |
295 | |
296 /* | |
297 ******************************** | |
298 * Begin Hardware Specific Code * | |
299 ******************************** | |
300 */ | |
301 | |
302 @ Read Pending reg | |
303 @ original instr was: LDR r2, [r3,#INT_CNTRL_ITR] | |
304 @ do the same trick as we did for the mask regs | |
305 ldrh r0, [r3, #IT_REG1] | |
306 ldrh r1, [r3, #IT_REG2] | |
307 orr r2, r0, r1, lsl #16 | |
308 | |
309 /* | |
310 ****************************** | |
311 * End Hardware Specific Code * | |
312 ****************************** | |
313 */ | |
314 | |
315 LDR r3, =INT_IRQ_Priority @ Get the Priority table address | |
316 | |
317 IRQ_VECTOR_LOOP: | |
318 LDR r0, [r3,#0] @ Load first vector to be checked from priority table | |
319 MOV r1, #1 @ Build mask | |
320 MOV r1, r1, LSL r0 @ Use vector number to set mask to correct bit position | |
321 TST r1, r2 @ Test if pending bit is set | |
322 BNE IRQ_VECTOR_FOUND @ If bit is set, branch to found section... | |
323 | |
324 BIC r4,r4,r1 @ Clear mask bit to keep higher priority ints active | |
325 ADD r3, r3, #4 @ Move to next word in the priority table | |
326 LDR r0, =INT_Priority_End @ Load the end address for the priority table | |
327 CMP r0, r3 @ Make sure not at the end of the table (shouldn't happen!) | |
328 BNE IRQ_VECTOR_LOOP @ Continue to loop if not at the end of the table | |
329 | |
330 @ No bits in pending register set, restore registers and exit interrupt servicing | |
331 ADD sp,sp,#4 @ Adjust sp above IRQ enable value | |
332 LDMIA sp!,{r0-r4} @ Restore r0-r4 | |
333 STMDB sp!,{lr} @ Put return address for IRQ on stack | |
334 LDMIA sp!,{pc}^ @ return to the point of the exception and restore SPSR | |
335 | |
336 IRQ_VECTOR_FOUND: | |
337 | |
338 /* | |
339 ******************************** | |
340 * Begin Hardware Specific Code * | |
341 ******************************** | |
342 */ | |
343 | |
344 LDR r3, =INTH_BASE_ADDR @ load Interrupt Control Base | |
345 | |
346 MVN r2, r1 @ Get the inverse of the interrupt vector | |
347 @ Write a zero to the interrupt being handled (IT_REGn) | |
348 cmp r0, #16 | |
349 strloh r2, [r3, #IT_REG1] | |
350 mov r2, r2, lsr #16 | |
351 strhsh r2, [r3, #IT_REG2] | |
352 | |
353 @ Read the Mask reg - just like we did before | |
354 ldrh r1, [r3, #MASK_IT_REG1] | |
355 ldrh r2, [r3, #MASK_IT_REG2] | |
356 orr r2, r1, r2, lsl #16 | |
357 @ was LDR r2, [r3,#INT_CNTRL_MIR] | |
358 | |
359 ORR r4, r2, r4 @ Turn off lower priority pending bits and currently masked bits | |
360 | |
361 @ write both mask registers | |
362 @ was STR r4, [r3,#INT_CNTRL_MIR] | |
363 strh r4, [r3, #MASK_IT_REG1] | |
364 mov r1, r4, lsr #16 | |
365 strh r1, [r3, #MASK_IT_REG2] | |
366 | |
367 MOV r1, #1 @ Clear the pending interrupt | |
368 STRH r1, [r3,#IRQ_CTRL] @ by writing a 1 to the Control Reg | |
369 | |
370 /* | |
371 ****************************** | |
372 * End Hardware Specific Code * | |
373 ****************************** | |
374 */ | |
375 | |
376 LDR r3, =INT_IRQ_Vectors @ Get IRQ vector table address | |
377 MOV r2, r0, LSL #2 @ Multiply vector by 4 to get offset into table | |
378 ADD r3, r3, r2 @ Adjust vector table address to correct offset | |
379 LDR r2, [r3,#0] @ Load branch address from vector table | |
380 | |
381 MOV PC, r2 @ Jump to correct branch location based on vector table | |
382 | |
383 @ END: INT_IRQ | |
384 | |
385 /* | |
386 ************************************************************************ | |
387 * | |
388 * FUNCTION | |
389 * | |
390 * INT_Interrupt_Shell | |
391 * | |
392 * DESCRIPTION | |
393 * | |
394 * Handles all interrupts which use NU_Register_LISR. | |
395 * | |
396 * | |
397 * CALLED BY | |
398 * | |
399 * INT_IRQ | |
400 * | |
401 * CALLS | |
402 * | |
403 * TCT_Dispatch_LISR | |
404 * TCT_Interrupt_Context_Restore | |
405 * | |
406 * INPUTS | |
407 * | |
408 * vector (register r0) | |
409 * | |
410 * OUTPUTS | |
411 * | |
412 * None | |
413 ************************************************************************ | |
414 */ | |
415 | |
416 .globl INT_Interrupt_Shell | |
417 INT_Interrupt_Shell: | |
418 | |
419 MOV r4,lr @ Put IRQ return address into r4 | |
420 | |
421 BL TCT_Interrupt_Context_Save | |
422 | |
423 BL TCC_Dispatch_LISR | |
424 | |
425 MRS r1,CPSR @ Pickup current CPSR | |
426 BIC r1,r1,#MODE_MASK @ Clear the mode bits | |
427 ORR r1,r1,#(IRQ_MODE_OR_LOCKOUT) @ Set the IRQ mode bits and Lockout interrupts | |
428 MSR CPSR,r1 @ Lockout interrupts/change to IRQ mode | |
429 | |
430 /* | |
431 ******************************** | |
432 * Begin Hardware Specific Code * | |
433 ******************************** | |
434 */ | |
435 LDMIA sp!,{r1} @ Get IRQ enable value off IRQ stack | |
436 | |
437 LDR r2, =INTH_BASE_ADDR @ Get IRQ0 base register address | |
438 @ write it into both mask regs | |
439 @was STR r1,[r2,#INT_CNTRL_MIR] | |
440 strh r1, [r2, #MASK_IT_REG1] | |
441 mov r1, r1, lsr #16 | |
442 strh r1, [r2, #MASK_IT_REG2] | |
443 /* | |
444 ****************************** | |
445 * End Hardware Specific Code * | |
446 ****************************** | |
447 */ | |
448 | |
449 MRS r1,CPSR @ Pickup current CPSR | |
450 BIC r1,r1,#MODE_MASK @ Clear the mode bits | |
451 ORR r1,r1,#SUP_MODE @ Set the SVC mode bits | |
452 MSR CPSR,r1 @ Change to SVC mode | |
453 | |
454 B TCT_Interrupt_Context_Restore | |
455 | |
456 /* | |
457 ************************************************************************ | |
458 * | |
459 * FUNCTION | |
460 * | |
461 * INT_Timer_Interrupt | |
462 * | |
463 * DESCRIPTION | |
464 * | |
465 * This routine is the board-specific section of the timer | |
466 * interrupt handling | |
467 * | |
468 * CALLED BY | |
469 * | |
470 * None | |
471 * | |
472 * CALLS | |
473 * | |
474 * TMT_Timer_Interrupt | |
475 * | |
476 * INPUTS | |
477 * | |
478 * None | |
479 * | |
480 * | |
481 * OUTPUTS | |
482 * | |
483 * None | |
484 * | |
485 * HISTORY | |
486 * | |
487 * NAME DATE REMARKS | |
488 * | |
489 * B.Ronquillo 05-10-00 Created initial version 1.0 | |
490 * | |
491 ************************************************************************ | |
492 */ | |
493 | |
494 .globl INT_Timer_Interrupt | |
495 INT_Timer_Interrupt: | |
496 | |
497 /* | |
498 ******************************** | |
499 * Begin Hardware Specific Code * | |
500 ******************************** | |
501 * Clear the pending timer interrupt | |
502 * | |
503 * This is done in the INT_IRQ function by writing a zero to the | |
504 * timer bit. | |
505 * | |
506 ****************************** | |
507 * End Hardware Specific Code * | |
508 ****************************** | |
509 */ | |
510 | |
511 MOV r4,lr @ Put IRQ return address into r4 | |
512 | |
513 BL TCT_Interrupt_Context_Save | |
514 | |
515 BL TMT_Timer_Interrupt @ Call the timer interrupt | |
516 @ processing. | |
517 | |
518 MRS r1,CPSR @ Pickup current CPSR | |
519 BIC r1,r1,#MODE_MASK @ Clear the mode bits | |
520 ORR r1,r1,#IRQ_MODE @ Set the IRQ mode bits | |
521 MSR CPSR,r1 @ Change to IRQ mode | |
522 | |
523 /* | |
524 ******************************** | |
525 * Begin Hardware Specific Code * | |
526 ******************************** | |
527 */ | |
528 LDMIA sp!,{r1} @ Get IRQ enable value off IRQ stack | |
529 | |
530 LDR r2, =INTH_BASE_ADDR @ Get IRQ0 base register address | |
531 @ write it into both mask regs | |
532 @was STR r1,[r2,#INT_CNTRL_MIR] | |
533 strh r1, [r2, #MASK_IT_REG1] | |
534 mov r1, r1, lsr #16 | |
535 strh r1, [r2, #MASK_IT_REG2] | |
536 /* | |
537 ****************************** | |
538 * End Hardware Specific Code * | |
539 ****************************** | |
540 */ | |
541 | |
542 MRS r1,CPSR @ Pickup current CPSR | |
543 BIC r1,r1,#MODE_MASK @ Clear the mode bits | |
544 ORR r1,r1,#SUP_MODE @ Set the SVC mode bits | |
545 MSR CPSR,r1 @ Change to SVC mode | |
546 | |
547 B TCT_Interrupt_Context_Restore | |
548 | |
549 @} | |
550 @ End of INT_Timer_Interrupt | |
551 | |
552 /* | |
553 * INT_Interrupt_Init function written by Michael Spacefalcon | |
554 * for the FreeNucleus Calypso port - takes the place of | |
555 * INT_Install_Vector_Table, called from INT_Initialize. | |
556 */ | |
557 | |
558 .globl INT_Interrupt_Init | |
559 INT_Interrupt_Init: | |
560 | |
561 @ first mask all interrupts in the INTH | |
562 | |
563 ldr r0, =INTH_BASE_ADDR | |
564 mvn r1, #0 | |
565 strh r1, [r0, #MASK_IT_REG1] | |
566 strh r1, [r0, #MASK_IT_REG2] | |
567 | |
568 @ now install our IRQ vector into the magic IRAM jump table slot | |
569 | |
570 ldr r0, =_INT_IRQ | |
571 mov r1, #0x800000 | |
572 str r0, [r1, #0x14] | |
573 | |
574 @ we are done! | |
575 bx lr | |
576 | |
577 /* | |
578 * Need to define an INT_Vectors_Loaded() function | |
579 * that returns 1. | |
580 */ | |
581 .globl INT_Vectors_Loaded | |
582 INT_Vectors_Loaded: | |
583 mov r0, #1 | |
584 bx lr |