summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/lm32
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2009-04-14 13:44:29 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2009-04-14 13:44:29 +0000
commit7c4c284c4af4551627097f914ce048245213c481 (patch)
treeb4ca21e9cb1f8a2896755f8ad1443001f2dbf2ee /cpukit/score/cpu/lm32
parentFix attribution. (diff)
downloadrtems-7c4c284c4af4551627097f914ce048245213c481.tar.bz2
2009-04-14 Michael Walle <michael@walle.cc>
* cpu.h: corrected the registers in Context_Control and in CPU_Interrupt_frame to correspond to the saved frame in cpu_asm.S Also switched on CPU_ISR_PASSES_FRAME_POINTER. * cpu_asm.S: Moved the restore part of _CPU_Context_switch for easier reading. Fixed _CPU_Context_restore, it now moves the argument and branches to a label in _CPU_Context_switch. Removed unnecessary saves of registers in context switch and irq handling. Rewrote irq code to call the C helper. Added some documentation * irq.c: New file derived from c4x and nios2.
Diffstat (limited to 'cpukit/score/cpu/lm32')
-rw-r--r--cpukit/score/cpu/lm32/ChangeLog12
-rw-r--r--cpukit/score/cpu/lm32/Makefile.am2
-rw-r--r--cpukit/score/cpu/lm32/cpu_asm.S254
-rw-r--r--cpukit/score/cpu/lm32/irq.c83
-rw-r--r--cpukit/score/cpu/lm32/rtems/score/cpu.h9
5 files changed, 220 insertions, 140 deletions
diff --git a/cpukit/score/cpu/lm32/ChangeLog b/cpukit/score/cpu/lm32/ChangeLog
index e4d7ed1c86..01caaeab61 100644
--- a/cpukit/score/cpu/lm32/ChangeLog
+++ b/cpukit/score/cpu/lm32/ChangeLog
@@ -1,3 +1,15 @@
+2009-04-14 Michael Walle <michael@walle.cc>
+
+ * cpu.h: corrected the registers in Context_Control and
+ in CPU_Interrupt_frame to correspond to the saved frame in cpu_asm.S
+ Also switched on CPU_ISR_PASSES_FRAME_POINTER.
+ * cpu_asm.S: Moved the restore part of _CPU_Context_switch for
+ easier reading. Fixed _CPU_Context_restore, it now moves the
+ argument and branches to a label in _CPU_Context_switch. Removed
+ unnecessary saves of registers in context switch and irq handling.
+ Rewrote irq code to call the C helper. Added some documentation
+ * irq.c: New file derived from c4x and nios2.
+
2009-04-06 Michael Walle <michael@walle.cc>
* cpu_asm.S: We cannot use any other register than r0 without saving
diff --git a/cpukit/score/cpu/lm32/Makefile.am b/cpukit/score/cpu/lm32/Makefile.am
index 9d9b833f75..86af92f057 100644
--- a/cpukit/score/cpu/lm32/Makefile.am
+++ b/cpukit/score/cpu/lm32/Makefile.am
@@ -12,7 +12,7 @@ include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/lm32.h \
rtems/score/cpu_asm.h rtems/score/types.h
noinst_LIBRARIES = libscorecpu.a
-libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S irq.c
libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
include $(srcdir)/preinstall.am
diff --git a/cpukit/score/cpu/lm32/cpu_asm.S b/cpukit/score/cpu/lm32/cpu_asm.S
index 80501bad1d..d169c5f611 100644
--- a/cpukit/score/cpu/lm32/cpu_asm.S
+++ b/cpukit/score/cpu/lm32/cpu_asm.S
@@ -13,44 +13,70 @@
*
* Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
* Micro-Research Finland Oy
+ *
+ * Michael Walle <michael@walle.cc>, 2009
*/
#include <rtems/asm.h>
#include <rtems/score/cpu_asm.h>
-#define MICO32_FULL_CONTEXT_SAVE_RESTORE
-
/* void _CPU_Context_switch(run_context, heir_context)
*
* This routine performs a normal non-FP context switch.
*
* LM32 Specific Information:
*
- * XXX document implementation including references if appropriate
+ * Saves/restores all callee-saved general purpose registers as well as
+ * the stack pointer, return address and interrupt enable status register
+ * to/from the context.
+ *
*/
.globl _CPU_Context_switch
_CPU_Context_switch:
- sw (r1+0), r9
- sw (r1+4), r10
- sw (r1+8), r11
- sw (r1+12), r12
- sw (r1+16), r13
- sw (r1+20), r14
- sw (r1+24), r15
- sw (r1+28), r16
- sw (r1+32), r17
- sw (r1+36), r18
- sw (r1+40), r19
- sw (r1+44), r20
- sw (r1+48), r21
- sw (r1+52), r22
- sw (r1+56), r23
- sw (r1+60), r24
- sw (r1+64), r25
- sw (r1+68), gp
- sw (r1+72), fp
- sw (r1+76), sp
- sw (r1+80), ra
+ sw (r1+0), r11 /* r1 is the first argument */
+ sw (r1+4), r12
+ sw (r1+8), r13
+ sw (r1+12), r14
+ sw (r1+16), r15
+ sw (r1+20), r16
+ sw (r1+24), r17
+ sw (r1+28), r18
+ sw (r1+32), r19
+ sw (r1+36), r20
+ sw (r1+40), r21
+ sw (r1+44), r22
+ sw (r1+48), r23
+ sw (r1+52), r24
+ sw (r1+56), r25
+ sw (r1+60), gp
+ sw (r1+64), fp
+ sw (r1+68), sp
+ sw (r1+72), ra
+ rcsr r3, IE
+ sw (r1+76), r3
+_CPU_Context_switch_restore:
+ lw r11, (r2+0) /* r2 is the second argument */
+ lw r12, (r2+4)
+ lw r13, (r2+8)
+ lw r14, (r2+12)
+ lw r15, (r2+16)
+ lw r16, (r2+20)
+ lw r17, (r2+24)
+ lw r18, (r2+28)
+ lw r19, (r2+32)
+ lw r20, (r2+36)
+ lw r21, (r2+40)
+ lw r22, (r2+44)
+ lw r23, (r2+48)
+ lw r24, (r2+52)
+ lw r25, (r2+56)
+ lw gp, (r2+60)
+ lw fp, (r2+64)
+ lw sp, (r2+68)
+ lw ra, (r2+72)
+ lw r3, (r2+76)
+ wcsr IE, r3
+ ret
/*
* _CPU_Context_restore
@@ -58,112 +84,90 @@ _CPU_Context_switch:
* This routine is generally used only to restart self in an
* efficient manner. It may simply be a label in _CPU_Context_switch.
*
- * NOTE: May be unnecessary to reload some registers.
- *
* LM32 Specific Information:
*
- * XXX document implementation including references if appropriate
+ * Moves argument #1 to #2 and branches to the restore part of the
+ * context switch code above.
*/
.globl _CPU_Context_restore
_CPU_Context_restore:
- lw r9, (r2+0)
- lw r10, (r2+4)
- lw r11, (r2+8)
- lw r12, (r2+12)
- lw r13, (r2+16)
- lw r14, (r2+20)
- lw r15, (r2+24)
- lw r16, (r2+28)
- lw r17, (r2+32)
- lw r18, (r2+36)
- lw r19, (r2+40)
- lw r20, (r2+44)
- lw r21, (r2+48)
- lw r22, (r2+52)
- lw r23, (r2+56)
- lw r24, (r2+60)
- lw r25, (r2+64)
- lw gp, (r2+68)
- lw fp, (r2+72)
- lw ra, (r2+80)
- /* Stack pointer must be restored last, in case it has been updated */
- lw sp, (r2+76)
- nop
- ret
-
-/* void __ISR_Handler()
+ mv r2, r1
+ bi _CPU_Context_switch_restore
+
+/* void _ISR_Handler()
*
* This routine provides the RTEMS interrupt management.
*
* LM32 Specific Information:
*
- * XXX document implementation including references if appropriate
+ * Saves all the caller-saved general purpose registers as well as the
+ * return address, exception return address and breakpoint return address
+ * (the latter may be unnecessary) onto the stack, which is either the task
+ * stack (in case of a interrupted task) or the interrupt stack (if an
+ * interrupt was interrupted).
+ * After that, it figures out the pending interrupt with the highest
+ * priority and calls the main ISR handler written in C, which in turn
+ * handles interrupt nesting, software interrupt stack setup etc and
+ * finally calls the user ISR.
+ * At the end the saved registers are restored.
+ *
*/
.globl _ISR_Handler
_ISR_Handler:
- xor r0, r0, r0
- addi sp, sp, -128
- sw (sp+4), r1
- sw (sp+8), r2
- sw (sp+12), r3
- sw (sp+16), r4
- sw (sp+20), r5
- sw (sp+24), r6
- sw (sp+28), r7
- sw (sp+32), r8
- sw (sp+36), r9
- sw (sp+40), r10
-#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
- sw (sp+44), r11
- sw (sp+48), r12
- sw (sp+52), r13
- sw (sp+56), r14
- sw (sp+60), r15
- sw (sp+64), r16
- sw (sp+68), r17
- sw (sp+72), r18
- sw (sp+76), r19
- sw (sp+80), r20
- sw (sp+84), r21
- sw (sp+88), r22
- sw (sp+92), r23
- sw (sp+96), r24
- sw (sp+100), r25
- sw (sp+104), r26
- sw (sp+108), r27
-#endif
- sw (sp+116), ra
- sw (sp+120), ea
- sw (sp+124), ba
+ xor r0, r0, r0
+ addi sp, sp, -52
+ sw (sp+4), r1
+ sw (sp+8), r2
+ sw (sp+12), r3
+ sw (sp+16), r4
+ sw (sp+20), r5
+ sw (sp+24), r6
+ sw (sp+28), r7
+ sw (sp+32), r8
+ sw (sp+36), r9
+ sw (sp+40), r10
+ sw (sp+44), ra
+ sw (sp+48), ea
+ sw (sp+52), ba
- /* Scan through (IP & IM) bits starting from LSB until irq found */
- rcsr r2,IP
- rcsr r3,IM
- and r4,r2,r3
- or r1,r0,r0
- ori r5,r0,1
-find_irq:
- and r6,r4,r5
- bne r6,r0,found_irq
- sli r5,r5,1
- addi r1,r1,1
- bne r5,r0,find_irq
- /* If we end up here there was no interrupt - this should never
- happen! */
- bi exit_isr
+ /*
+ * Scan through IP & IM bits starting from LSB until irq vector is
+ * found. The vector is stored in r1, which is the first argument for
+ * __ISR_Handler.
+ */
+ rcsr r2, IP
+ rcsr r3, IM
+ mv r1, r0 /* r1: counter for the vector number */
+ and r2, r2, r3 /* r2: pending irqs, which are enabled */
+ mvi r3, 1 /* r3: register for the walking 1 */
+ /*
+ * If r2 is zero, there was no interrupt.
+ * This should never happen!
+ */
+ be r2, r0, exit_isr
+find_irq:
+ and r4, r2, r3
+ bne r4, r0, found_irq
+ sli r3, r3, 1
+ addi r1, r1, 1
+ bi find_irq
found_irq:
- .extern _ISR_Vector_table
- sli r1,r1,2
- mvhi r7,hi(_ISR_Vector_table)
- ori r7,r7,lo(_ISR_Vector_table)
- lw r6,(r7+0)
- add r6,r6,r1
- lw r5,(r6+0)
- call r5
+ /*
+ * Call __ISR_Handler for further processing.
+ * r1 is the vector number, calculated above
+ * r2 is the pointer to the CPU_Interrupt_frame
+ */
+ addi r2, sp, 4
+ .extern __ISR_Handler
+ mvhi r3, hi(__ISR_Handler)
+ ori r3, r3, lo(__ISR_Handler)
+ call r3
+
exit_isr:
+ /* Restore the saved registers */
lw r1, (sp+4)
lw r2, (sp+8)
lw r3, (sp+12)
@@ -174,29 +178,9 @@ exit_isr:
lw r8, (sp+32)
lw r9, (sp+36)
lw r10, (sp+40)
-#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
- lw r11, (sp+44)
- lw r12, (sp+48)
- lw r13, (sp+52)
- lw r14, (sp+56)
- lw r15, (sp+60)
- lw r16, (sp+64)
- lw r17, (sp+68)
- lw r18, (sp+72)
- lw r19, (sp+76)
- lw r20, (sp+80)
- lw r21, (sp+84)
- lw r22, (sp+88)
- lw r23, (sp+92)
- lw r24, (sp+96)
- lw r25, (sp+100)
- lw r26, (sp+104)
- lw r27, (sp+108)
-#endif
- lw ra, (sp+116)
- lw ea, (sp+120)
- lw ba, (sp+124)
- addi sp, sp, 128
- nop
+ lw ra, (sp+44)
+ lw ea, (sp+48)
+ lw ba, (sp+52)
+ addi sp, sp, 52
eret
diff --git a/cpukit/score/cpu/lm32/irq.c b/cpukit/score/cpu/lm32/irq.c
new file mode 100644
index 0000000000..3eb723d3d8
--- /dev/null
+++ b/cpukit/score/cpu/lm32/irq.c
@@ -0,0 +1,83 @@
+/*
+ * lm32 interrupt handler
+ *
+ * Derived from c4x/irq.c and nios2/irq.c
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/cpu.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+
+/*
+ * This routine provides the RTEMS interrupt management.
+ *
+ * Upon entry, interrupts are disabled
+ */
+
+#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
+ unsigned long *_old_stack_ptr;
+#endif
+
+register unsigned long *stack_ptr asm("sp");
+
+void __ISR_Handler(uint32_t vector, CPU_Interrupt_frame *ifr)
+{
+ register uint32_t level;
+
+ /* Interrupts are disabled upon entry to this Handler */
+
+ _Thread_Dispatch_disable_level++;
+
+#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
+ if ( _ISR_Nest_level == 0 ) {
+ /* Install irq stack */
+ _old_stack_ptr = stack_ptr;
+ stack_ptr = _CPU_Interrupt_stack_high - 4;
+ }
+#endif
+
+ _ISR_Nest_level++;
+
+ if ( _ISR_Vector_table[ vector] )
+ {
+ (*_ISR_Vector_table[ vector ])(vector, ifr);
+ };
+
+ /* Make sure that interrupts are disabled again */
+ _CPU_ISR_Disable( level );
+
+ _ISR_Nest_level--;
+
+#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
+ if( _ISR_Nest_level == 0)
+ stack_ptr = _old_stack_ptr;
+#endif
+
+ _Thread_Dispatch_disable_level--;
+
+ _CPU_ISR_Enable( level );
+
+ if ( _ISR_Nest_level )
+ return;
+
+ if ( _Thread_Dispatch_disable_level ) {
+ _ISR_Signals_to_thread_executing = FALSE;
+ return;
+ }
+
+ if ( _Context_Switch_necessary || _ISR_Signals_to_thread_executing ) {
+ _ISR_Signals_to_thread_executing = FALSE;
+ _Thread_Dispatch();
+ }
+}
+
diff --git a/cpukit/score/cpu/lm32/rtems/score/cpu.h b/cpukit/score/cpu/lm32/rtems/score/cpu.h
index 5ada499b95..44d1d23a16 100644
--- a/cpukit/score/cpu/lm32/rtems/score/cpu.h
+++ b/cpukit/score/cpu/lm32/rtems/score/cpu.h
@@ -175,7 +175,7 @@ extern "C" {
*
* XXX document implementation including references if appropriate
*/
-#define CPU_ISR_PASSES_FRAME_POINTER 0
+#define CPU_ISR_PASSES_FRAME_POINTER 1
/**
* @def CPU_HARDWARE_FP
@@ -462,8 +462,6 @@ extern "C" {
* to another.
*/
typedef struct {
- uint32_t r9;
- uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t r13;
@@ -483,6 +481,7 @@ typedef struct {
uint32_t fp;
uint32_t sp;
uint32_t ra;
+ uint32_t ie;
} Context_Control;
/**
@@ -520,9 +519,11 @@ typedef struct {
uint32_t r6;
uint32_t r7;
uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
uint32_t ra;
- uint32_t gp;
uint32_t ba;
+ uint32_t ea;
} CPU_Interrupt_frame;
/**