summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2002-07-17 17:17:53 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2002-07-17 17:17:53 +0000
commitd5136d96396beafa7fd475f861d0b42d25562f6b (patch)
tree3aadf86c809ae5f6bc54f14364e75a301a64a99b
parent2002-07-17 Jay Monkman <jtm@smoothsmoothie.com> (diff)
downloadrtems-d5136d96396beafa7fd475f861d0b42d25562f6b.tar.bz2
2002-07-17 Jay Monkman <jtm@smoothsmoothie.com>
* irq/irq_asm.S: Significant rework in attempt to make interrupts work. They appear to be very close to correct but not 100%.
-rw-r--r--c/src/lib/libbsp/arm/shared/ChangeLog5
-rw-r--r--c/src/lib/libbsp/arm/shared/irq/irq_asm.S238
2 files changed, 154 insertions, 89 deletions
diff --git a/c/src/lib/libbsp/arm/shared/ChangeLog b/c/src/lib/libbsp/arm/shared/ChangeLog
index 99c50d008e..5d4ddb56d2 100644
--- a/c/src/lib/libbsp/arm/shared/ChangeLog
+++ b/c/src/lib/libbsp/arm/shared/ChangeLog
@@ -1,3 +1,8 @@
+2002-07-17 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * irq/irq_asm.S: Significant rework in attempt to make interrupts
+ work. They appear to be very close to correct but not 100%.
+
2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* comm/Makefile.am: Remove AUTOMAKE_OPTIONS.
diff --git a/c/src/lib/libbsp/arm/shared/irq/irq_asm.S b/c/src/lib/libbsp/arm/shared/irq/irq_asm.S
index e6b740eb9a..274979363a 100644
--- a/c/src/lib/libbsp/arm/shared/irq/irq_asm.S
+++ b/c/src/lib/libbsp/arm/shared/irq/irq_asm.S
@@ -2,9 +2,15 @@
*
* This file contains the implementation of the IRQ handler
*
+ * Copyright (c) 2002 Advent Networks, Inc.
+ * Jay Monkman <jmonkman@adventnetworks.com>
+ *
* CopyRight (C) 2000 Canon Research France SA.
* Emmanuel Raguet, mailto:raguet@crf.canon.fr
*
+ * Modified Andy Dachs <a.dachs@sstl.co.uk>
+ * Copyright (c) 2001 Surrey Satellite Technolgy Limited
+ *
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
@@ -14,96 +20,150 @@
#include "asm.h"
#define __asm__
-#include <registers.h>
+ .globl _ISR_Handler
+_ISR_Handler:
+ stmdb sp!, {r0, r1, r2, r3} /* save regs on INT stack */
+ stmdb sp!, {lr} /* now safe to call C funcs */
+
+
+/* one nest level deeper */
+ ldr r0, =_ISR_Nest_level
+ ldr r1, [r0]
+ add r1, r1,#1
+ str r1, [r0]
+
+/* disable multitasking */
+ ldr r0, =_Thread_Dispatch_disable_level
+ ldr r1, [r0]
+ add r1, r1,#1
+ str r1, [r0]
+
+/* BSP specific function to INT handler */
+ /* FIXME: I'm not sure why I can't save just r12. I'm also */
+ /* not sure which of r1-r3 are important. */
+ stmdb sp!, {r0-r12}
+ bl ExecuteITHandler
+ ldmia sp!, {r0-r12}
+
+/* one less nest level */
+ ldr r0, =_ISR_Nest_level
+ ldr r1, [r0]
+ sub r1, r1,#1
+ str r1, [r0]
+
+/* unnest multitasking */
+ ldr r0, =_Thread_Dispatch_disable_level
+ ldr r1, [r0]
+ sub r1, r1,#1
+ str r1, [r0]
+
+/* If thread dispatching is disabled, exit */
+ cmp r1, #0
+ bne exitit
+
+/* If a task switch is necessary, call scheduler */
+ ldr r0, =_Context_Switch_necessary
+ ldr r1, [r0]
+ cmp r1, #0
+
+ /* since bframe is going to clear _ISR_Signals_to_thread_executing, */
+ /* we need to load it here */
+ ldr r0, =_ISR_Signals_to_thread_executing
+ ldr r1, [r0]
+ bne bframe
+
+/* If a signals to be sent (_ISR_Signals_to_thread_executing != 0), */
+/* call scheduler */
+ cmp r1, #0
+ beq exitit
+
+/* _ISR_Signals_to_thread_executing = FALSE */
+ mov r1, #0
+ str r1, [r0]
-/*
- * WARNING : register r5 is important. If you need to use it,
- * to forget to save it !!!!!!!!!!
- */
-
- .globl _ISR_Handler
-_ISR_Handler:
- stmdb sp!, {r4,r5,lr} /* save regs on INT stack */
- mrs r4, cpsr /* save current CSPR */
- mov r5, r4 /* copy CSPR */
- orr r4, r4, #3
- msr cpsr, r4 /* switch to SVC mode */
-
- stmdb sp!, {r0-r3,r12,r14} /* save scratch regs on SVC stack */
-
- msr cpsr, r5 /* switch back to INT mode */
-
- ldr r0, =_ISR_Nest_level /* one nest level deeper */
- ldr r1, [r0]
- add r1, r1,#1
- str r1, [r0]
-
- ldr r0, =_Thread_Dispatch_disable_level /* disable multitasking */
- ldr r1, [r0]
- add r1, r1,#1
- str r1, [r0]
-
- b ExecuteITHandler /* BSP specific function to INT handler */
-
- .globl ReturnFromHandler
-ReturnFromHandler :
- ldr r0, =_ISR_Nest_level /* one less nest level */
- ldr r1, [r0]
- sub r1, r1,#1
- str r1, [r0]
-
- ldr r0, =_Thread_Dispatch_disable_level /* unnest multitasking */
- ldr r1, [r0]
- sub r1, r1,#1
- str r1, [r0]
-
- cmp r1, #0 /* is dispatch enabled */
- bne exitit /* Yes, then exit */
-
- ldr r0, =_Context_Switch_necessary /* task switch necessary ? */
- ldr r1, [r0]
- cmp r1, #0
- bne schedule /* yes, call scheduler */
-
- ldr r0, =_ISR_Signals_to_thread_executing
- ldr r1, [r0] /* signals sent to Run_thread */
- cmp r1, #0 /* while in interrupt handler ? */
- beq exitit /* No, exit */
-
bframe:
- mov r1, #0 /* _ISR_Signals_to_thread_executing = FALSE */
- str r1, [r0]
- /*
- * At this point, we need a complete exception context for the
- * current thread. We need to complete the interrupt exception
- * with the "not-yet-saved" registers
- */
- /*
- * currently exception context = interrupt handler
- * it needs to be optimized
- */
- bl _ThreadProcessSignalsFromIrq
- b exitit
-
-schedule:
- /*
- * the scratch registers have already been saved and we are already
- * back on the thread system stack. So we can call _Thread_Displatch
- * directly
- */
- bl _Thread_Dispatch
- /*
- * fall through exit to restore complete contex (scratch registers
- * eip, CS, Flags).
- */
+
+/* Now we need to set up the return from this ISR to be _ISR_Dispatch */
+/* To do that, we need to save the current lr_int and spsr_int on the */
+/* SVC stack */
+ mrs r0, spsr
+ ldmia sp!, {r1} /* get lr off stack */
+ stmdb sp!, {r1}
+ mrs r2, cpsr
+ orr r3, r2, #0x1 /* change to SVC mode */
+ msr cpsr_c, r3
+
+ /* now in SVC mode */
+ stmdb sp!, {r0, r1} /* put spsr_int and lr_int on SVC stack */
+ msr cpsr_c, r2 /* change back to INT mode */
+
+ /* now in INT mode */
+
+ /* replace lr with address of _ISR_Dispatch */
+ ldr lr, =_ISR_Dispatch
+ add lr, lr, #0x4 /* On entry to an ISR, the lr is */
+ /* the return address + 4, so */
+ /* we have to emulate that */
+ ldmia sp!, {r0} /* out with the old */
+ stmdb sp!, {lr} /* in with the new (lr) */
+
+
+ mrs r0, spsr
+ orr r0, r0, #0xc0
+ msr spsr, r0
+
exitit:
- b AckControler /* BSP specific function to ack PIC */
-
- .globl ReturnFromAck
-ReturnFromAck :
- ldmia sp!, {r0-r3,r12,r14} /* restore regs from SVC stack */
- msr cpsr, r5 /* switch back to INT mode */
- ldmia sp!, {r4,r5,lr} /* restore regs from INT stack */
- subs pc,r14,#4 /* return */
-
+ ldmia sp!, {lr} /* restore regs from INT stack */
+ ldmia sp!, {r0, r1, r2, r3} /* restore regs from INT stack */
+ subs pc, lr, #4 /* return */
+
+
+
+ /* on entry to _ISR_Dispatch, we're in SVC mode */
+ .globl _ISR_Dispatch
+_ISR_Dispatch:
+ stmdb sp!, {r0-r12,lr} /* save regs on SVC stack */
+ /* (now safe to call C funcs) */
+ /* we don't save lr, since */
+ /* it's just going to get */
+ /* overwritten */
+
+ bl _Thread_Dispatch
+ ldmia sp!, {r0-r12, lr}
+
+ stmdb sp!, {r0-r2}
+ /* Now we have to screw with the stack */
+ mov r0, sp /* copy the SVC stack pointer */
+
+ mrs r1, cpsr
+ bic r2, r1, #0x1 /* change to INT mode */
+ orr r2, r2, #0xc0 /* disable interrupts */
+ msr cpsr_c, r2
+
+ /* now in INT mode */
+ stmdb sp!, {r4, r5, r6} /* save temp vars on INT stack */
+ ldmia r0!, {r4, r5, r6} /* Get r0-r3 from SVC stack */
+ stmdb sp!, {r4, r5, r6} /* and save them on INT stack */
+
+ ldmia r0!, {r4, r5} /* get saved values from SVC stack */
+ /* r4=spsr, r5=lr */
+ mov lr, r5 /* restore lr_int */
+ msr spsr, r4 /* restore spsr_int */
+
+ /* switch to SVC mode, update sp, then return to INT mode */
+ msr cpsr_c, r1 /* switch to SVC mode */
+ mov sp, r0 /* update sp_svc */
+ msr cpsr_c, r2 /* switch back to INT mode */
+
+ /* pop all the registers from the stack */
+ ldmia sp!, {r0, r1, r2}
+ ldmia sp!, {r4, r5, r6}
+
+ /* Finally, we can return to the interrupted task */
+ subs pc, lr, #4
+
+
+
+
+