From 7c4c284c4af4551627097f914ce048245213c481 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 14 Apr 2009 13:44:29 +0000 Subject: 2009-04-14 Michael Walle * 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. --- cpukit/score/cpu/lm32/ChangeLog | 12 ++ cpukit/score/cpu/lm32/Makefile.am | 2 +- cpukit/score/cpu/lm32/cpu_asm.S | 254 +++++++++++++++----------------- cpukit/score/cpu/lm32/irq.c | 83 +++++++++++ cpukit/score/cpu/lm32/rtems/score/cpu.h | 9 +- 5 files changed, 220 insertions(+), 140 deletions(-) create mode 100644 cpukit/score/cpu/lm32/irq.c (limited to 'cpukit/score/cpu/lm32') 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 + + * 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 * 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 , 2008, * Micro-Research Finland Oy + * + * Michael Walle , 2009 */ #include #include -#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 +#include +#include +#include + +/* + * 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; /** -- cgit v1.2.3