mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 00:04:58 +08:00
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+119
-135
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user