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