From d5136d96396beafa7fd475f861d0b42d25562f6b Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 17 Jul 2002 17:17:53 +0000 Subject: 2002-07-17 Jay Monkman * irq/irq_asm.S: Significant rework in attempt to make interrupts work. They appear to be very close to correct but not 100%. --- c/src/lib/libbsp/arm/shared/ChangeLog | 5 + c/src/lib/libbsp/arm/shared/irq/irq_asm.S | 238 +++++++++++++++++++----------- 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 + + * 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 * 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 + * * CopyRight (C) 2000 Canon Research France SA. * Emmanuel Raguet, mailto:raguet@crf.canon.fr * + * Modified Andy Dachs + * 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 + .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 + + + + + -- cgit v1.2.3