📄 vectors.s
字号:
SVECT_TBL_ENTRY 66
SVECT_TBL_ENTRY 67
SVECT_TBL_ENTRY 68
SVECT_TBL_ENTRY 69
SVECT_TBL_ENTRY 70
SVECT_TBL_ENTRY 71
SVECT_TBL_ENTRY 72
SVECT_TBL_ENTRY 73
SVECT_TBL_ENTRY 74
SVECT_TBL_ENTRY 75
SVECT_TBL_ENTRY 76
SVECT_TBL_ENTRY 77
SVECT_TBL_ENTRY 78
SVECT_TBL_ENTRY 79
SVECT_TBL_ENTRY 80
SVECT_TBL_ENTRY 81
SVECT_TBL_ENTRY 82
SVECT_TBL_ENTRY 83
SVECT_TBL_ENTRY 84
SVECT_TBL_ENTRY 85
SVECT_TBL_ENTRY 86
SVECT_TBL_ENTRY 87
SVECT_TBL_ENTRY 88
SVECT_TBL_ENTRY 89
SVECT_TBL_ENTRY 90
SVECT_TBL_ENTRY 91
SVECT_TBL_ENTRY 92
SVECT_TBL_ENTRY 93
SVECT_TBL_ENTRY 94
SVECT_TBL_ENTRY 95
SVECT_TBL_ENTRY 96
SVECT_TBL_ENTRY 97
SVECT_TBL_ENTRY 98
SVECT_TBL_ENTRY 99
SVECT_TBL_ENTRY 100
SVECT_TBL_ENTRY 101
SVECT_TBL_ENTRY 102
SVECT_TBL_ENTRY 103
SVECT_TBL_ENTRY 104
SVECT_TBL_ENTRY 105
SVECT_TBL_ENTRY 106
SVECT_TBL_ENTRY 107
SVECT_TBL_ENTRY 108
SVECT_TBL_ENTRY 109
SVECT_TBL_ENTRY 110
SVECT_TBL_ENTRY 111
SVECT_TBL_ENTRY 112
SVECT_TBL_ENTRY 113
SVECT_TBL_ENTRY 114
SVECT_TBL_ENTRY 115
SVECT_TBL_ENTRY 116
SVECT_TBL_ENTRY 117
SVECT_TBL_ENTRY 118
SVECT_TBL_ENTRY 119
SVECT_TBL_ENTRY 120
SVECT_TBL_ENTRY 121
SVECT_TBL_ENTRY 122
SVECT_TBL_ENTRY 123
SVECT_TBL_ENTRY 124
SVECT_TBL_ENTRY 125
SVECT_TBL_ENTRY 126
SVECT_TBL_ENTRY 127
#endif // #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
//=============================================================================
// INTERRUPT ENTRY ROUTINE
// DESCRIPTION:
// We enter this routine by a call of jsr @interrupt_entry. This means
// the PC,CCR and EXR are pushed onto the stack (4 byte and the pushed
// PC value points to the interrupt_hook_table entry following
// the just called entry.
// When we jump into default_vsr we have a saved machine state on stack
// that looks like this:
//
// [SP -->] [MACH 4]
// [MACL 4]
// -------------------------------------
// SP --> ER6 4 ER0 - ER6
// ER5 4
// ER4 4
// ER3 4
// ER2 4
// ER1 4
// ER0 4
// SP 4 Pre-Exception Stack pointer
// --------------------------------------------
// EXR 1 EXR register
// RSV 1 reserved
// --------------------------------------------
// CCR 1 CCR register
// PC 4 program counter
//
// NOTES:
// We come here with I0-I2 masked in EXR.
//=============================================================================
//
// this trampoline code is required only for ROM or ROMRAM startup
//
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
.section .text
interrupt_entry:
//
// first we disable all interrupts in order to process the following code
// without danger of becoming interrupted
//
orc #7, exr
//
// we are here with PC + CCR + EXR pushed onto stack so we have to
// push the remaining registers er0-er7 only. er7 is the stack pointer
// and we would like to have the pre exception stack pointer in order to
// enable GDB to display the correct stack. The JSR instruction that brought
// us here stored PC+CCR on stack. We simply ignore it and use these 4 bytes
// on stack to store our SP later there.
//
stm.l er0 - er3, @ - sp // push er0-er3
stm.l er4 - er6, @ - sp // push er4-er6
//
// if we use the H8S/2600 MAC register then we have to store it now - the macro
// hal_push_mac is only valid if it is configured
//
hal_push_mac
mov.l @(SAVED_STATE_SP, sp), er5 // er5 is saved so we can store the PC before orc #7,exr and jsr @interrupt entry in er5
extu.w e5 // the high byte of e5 contains ccr - we clear this by extending the lower 8 bits
//
// Now we would execute the following two instructions
// sub.l #4, er0 // get the PC before execution of jsr @interrupt entry
// sub.l #__ram_int_svect_tbl, er0 // now we get the interrupt entry * 8 because each entry is 8 byte long
// We use only the following single instruction - this serves 3 states
//
sub.l #__ram_int_svect_tbl+4, er5 // er5 now contains intvector * 4
mov.l er5, er1 // we store the er5 value because it contains invect*4 and we require this for index in hal_vsr_table
shlr.l #2, er5 // let's devide by 4 to get the real entry - er5 now contains interrupt vector number
mov.l sp, er0 // er0 is saved so we can modify it
add.l #SIZE_SAVED_STATE, er0 // we need pre exception stack pointer er0-er7 = 8*4, EXR = 2, PAD = 2, PC+CCR = 4 --> 7*4+2+2+4
mov.l er0, @(SAVED_STATE_SP, sp) // save pre exception stack pointer bevore er0 on stack
//
// Now lets get into hal_vsr_table. We take the vector number and
// multiply with 4 (because each entry is 4 byte long). We stored this value
// before in er1 so we can simply take the er1 value now
//
mov.l @(CYG_LABEL_DEFN(hal_vsr_table),er1), er0 // get vsr_table entry
jmp @er0 // and now jump to the default vsr
#endif // #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
//=============================================================================
// DEFAULT EXCEPTION VSR
// DESCRIPTION:
// Most synchronous exception VSR table entries will point to a default
// exception VSR which is responsible for handling all exceptions in
// a generic manner. The default VSR simply saves the CPU state, makes any
// adjustments to the CPU state that is necessary, and calls
// cyg_hal_exception_handler().
//
// NOTES:
// We call:
// cyg_hal_exception_handler(HAL_SavedRegisters *regs, CYG_WORD vector)
//
// This means we have to store pointer to regs in er0 and vector in er1
// We come into this VSR with the saved machine state on stack that looks
// like this:
// SP ---> ER6 4 ER0 - ER6
// ER5 4
// ER4 4
// ER3 4
// ER2 4
// ER1 4
// ER0 4
// SP 4 pre exception SP
// -------------------------------------
// PAD 2 Padding byte
// EXR 1 EXR register
// RSV 1 reserved
// -------------------------------------
// CCR 1 CCR register
// PC 3 program counter
//=============================================================================
.section .text
.global CYG_LABEL_DEFN(__default_exception_vsr)
CYG_LABEL_DEFN(__default_exception_vsr):
//
// store interrupt vector from er5 in _hal_saved_intvec so we can use is later
// We have to do this here and not in trampoline code because if we do it
// in trampoline code, the we cant use it in an application because the
// trampoline code is only within the ROM monitor
//
mov.l er5, @CYG_LABEL_DEFN(_hal_saved_intvec)
mov.l er5, er1 // store interrupt vector number as arg1 in er1
mov.l sp, er0 // store pointer to HAL_SavedRegisters in er0
jsr @CYG_LABEL_DEFN(cyg_hal_exception_handler) // now lets call the exception handler
//
// now restore the saved machine state from stack by the
// macro hal_cpu_load all. This macro is defined in arch.inc
// variant.inc or platform.inc
//
hal_cpu_load_all
rte
//=============================================================================
// DEFAULT INTERRUPT VSR
// DESCRIPTION:
// Most asynchronous external interrupt vectors will point to a default
// interrupt VSR which decodes the actual interrupt being delivered from
// the interrupt controller and invokes the appropriate ISR. The default
// interrupt VSR has a number of responsibilities if it is going to
// interact with the Kernel cleanly and allow interrupts to cause thread
// preemption. To support this VSR an ISR vector table is needed.
// For each valid vector three pointers need to be stored: the ISR, its
// data pointer and an opaque (to the HAL) interrupt object pointer needed
// by the kernel. It is implementation defined whether these are stored
// in a single table of triples, or in three separate tables. The VSR
// follows the following approximate plan:
//
// NOTES:
// We come into this VSR with the saved machine state on stack that looks
// like this:
//
// SP ---> ER6 0 ER0 - ER6
// ER5 4
// ER4 8
// ER3 12
// ER2 16
// ER1 20
// ER0 24
// SP 28 pre exception SP
// EXR 32 EXR register
// PAD 33 reserved
// CCR 34 CCR register
// PC 35 program counter
//=============================================================================
.section .text
//
// We come here with all the registers pushed
// onto the stack and all interrupts masked
//
.global CYG_LABEL_DEFN(__default_interrupt_vsr)
CYG_LABEL_DEFN(__default_interrupt_vsr):
//
// hal_diag_int_start is a macro defined in arch.inc or platform.inc
//
hal_diag_intr_start
//
// The HAL can be configured to either support the full eCos kernel, or to support
// only very simple applications which do not require a full kernel. If kernel
// support is not required then some of the startup, exception, and interrupt handling
// code can be eliminated.
//
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
//
// Increment the scheduler lock
//
.extern CYG_LABEL_DEFN(cyg_scheduler_sched_lock)
mov.l @CYG_LABEL_DEFN(cyg_scheduler_sched_lock), er0
inc.l #1, er0
mov.l er0, @CYG_LABEL_DEFN(cyg_scheduler_sched_lock)
#endif
//
// (Optional) Switch to an interrupt stack if not already running on it.
// This allows nested interrupts to be delivered without needing every thread
// to have a stack large enough to take the maximum possible nesting.
// We have to check if it is a nested interrupt. We first inspect the stack pointer
// and switch only if it is not currently within the interrupt stack range
//
// __interrupt_stack_base
// ..
// SP ---> ..
// __interrupt_stack
//
// We switch only to interrupt stack, if SP < __interrupt_stack_base or
// SP > __interrupt_stack
//
mov.l sp, er4 // er4 = SP = pointer to saved thread state
// invector already saved in interrupt_entry in er5 // er5 = int vector
#if defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK)
mov.l #__interrupt_stack, er0 // A1 = er0 = interrupt stack
cmp.l #__interrupt_stack_base, sp // compare sp with base of stack
blt switch_to_istack // if sp < base then switch to int stack
cmp.l er0, sp // compare sp with stack
ble already_on_istack // if <= top then already on istack
//
// now switch to interrupt stack
//
switch_to_istack:
mov.l er0, sp // switch to new SP
//
// we are already running on interrupt stack
//
already_on_istack:
push.l er4 // save old SP
#endif
//
// The various parts of the kernel will invoke instrumentation routines whenever
// appropriate events occur, and these will be stored in a circular buffer for
// later reference.
// This option controls whether or not instrumentation support is compiled
// into the interrupt handling code.
//
#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
//
// Call cyg_instrument to record that this interrupt is being raised.
// void cyg_instrument(cyg_uint32 type, CYG_ADDRWORD arg1, CYG_ADDRWORD arg2)
//
// type = 0x0301 = INTR.RAISE (er0)
// arg1 = vector number (er1)
// arg1 = interrupt number (er2)
//
.extern CYG_LABEL_DEFN(cyg_instrument)
mov.l #0x0301, er0 // type = INTR,RAISE
mov.l er5, er1 // arg1 = vector number
mov.l er1, er2 // arg2 = interrupt number
jsr CYG_LABEL_DEFN(cyg_instrument) // call instrumentation
#endif
//
// When an interrupt occurs the HAL interrupt handling code can either leave
// interrupts disabled for the duration of the interrupt handling code, or by
// doing some extra work it can reenable interrupts before invoking the
// interrupt handler and thus allow nested interrupts to happen.
// If all the interrupt handlers being used are small and do not involve any loops
// then it is usually better to disallow nested interrupts. However if any of
// the interrupt handlers are more complicated than nested interrupts will
// usually be required.
//
#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
//
// To allow nested interrupts, we set the IE bits in exr. We do
// not touch the IPL bits, so only higher priority interrupts
// will be nested on top of us. Also, new interrupts will not
// be delivered until the ISR calls
// Cyg_Interrupt::acknowledge_interrupt(). At some future point
// we may want to do the ack stuff here to allow immediate nesting.
//
mov.b @(CYG_LABEL_DEFN(hal_int_prio_tbl), er5), r0l // get priority of interrupt
//
// now set interrupt mask in exr
//
stc.b exr, r0h // get EXR
and.b #0xf8, r0h // clear I0-I2 bits
or.b r0l, r0h // set I0-I2 bits
ldc.b r0h, exr // store r0h back into exr - now nesting is possible
#endif
//
// If we have Ctrl-C support enabled, save a pointer to the
// saved CPU state here so we can plant a breakpoint there if
// this is a ^C.
//
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || \
defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
.extern CYG_LABEL_DEFN(hal_saved_interrupt_state)
mov.l er4, @CYG_LABEL_DEFN(hal_saved_interrupt_state) // er4 contains pointer to saved state
#endif
//
// Now we need a pointer to the interrupt object and interrupt
// data in order to call the ISR
// isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
//
mov.l er5, er0 // get intvector from er5
shll.l #2, er0 // tables contain long entries so multiply with 4
mov.l @(CYG_LABEL_DEFN(hal_interrupt_handlers),er0), er2 // store address of ISR in er2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -