⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vectors.s

📁 开放源码实时操作系统源码.
💻 S
📖 第 1 页 / 共 2 页
字号:
        
        | Call spurious interrupt handler
        .extern hal_spurious_interrupt
        jsr hal_spurious_interrupt

        | Remove the arguments from the stack.
        addq.l  #4,%sp

        | Restore the preserved registers for the current thread.        
        int_rest_regs

#endif /* ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS */
        
        | Just return from interrupt.
        rte


| ----------------------------------------------------------------------------
| User interrupt vector handler
|
| Control is transferred here from a user interrupt vector (#64-255).
| Before branching to common code, load a value to translate the
| vector table offset to the ISR table offset.

        .text
        .balign 4
        .globl cyg_hal_default_interrupt_vsr
cyg_hal_default_interrupt_vsr:

        | Disable all interrupts. On the first instruction, interrupt sampling
        | is always disabled.
        hal_cpu_int_disable

        | Preserve all registers that this handler needs to preserve.
        | The C code will preserve all other registers.
        int_pres_regs

        | It is safe to use breakpoints below this point.
        .globl _cyg_hal_default_interrupt_vsr_bp_safe
_cyg_hal_default_interrupt_vsr_bp_safe:
        
        | Adding this value to the vector table offset will result in the
        | corresponding offset into the ISR table.
        move.l #(-CYGNUM_HAL_ISR_MIN)*4,%d2

        | d2.l: Contains a value to translate the vector table offset to
        | the ISR table offset.

        | Calculate the vector offset. The format/vector word on the stack
        | contains the vector number. Mask off all unused bits. The bit
        | position of the vector number field makes it automatically multiplied
        | by four.
        move.w  CYGARC_CF_FMTVECWORD(%sp),%d1
        and.l   #0x000003fc,%d1

        | Calculate the ISR table offset. Add the vector table offset to the
        | translation value.
        add.l   %d1,%d2

        | Calculate the vector number using the vector table offset.
        asr.l   #2,%d1

        | d2.l: Contains the offset into the ISR table.
        | d1.l: Contains the vector number.

#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)

        | If we are supporting Ctrl-C interrupts from GDB, we must squirrel
        | away a pointer to the saved interrupt state here so that we can
        | plant a breakpoint at some later time.

        .extern hal_saved_interrupt_state
        move.l %sp,(hal_saved_interrupt_state)

#endif

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT

        | Lock the scheduler if we are using the kernel.
        .extern cyg_scheduler_sched_lock
        addq.l  #1,cyg_scheduler_sched_lock

#endif /* CYGFUN_HAL_COMMON_KERNEL_SUPPORT */

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
        
        | a0 = sp. We'll need it later
        move.l %sp,%a0

        cmp.l #__interrupt_stack_base,%sp
        
        | If sp < base : not on istack
        blt 1f
        
        cmp.l #__interrupt_stack,%sp
        
        | If sp <= top : already on istack
        ble 2f

1:
        | Switch to istack
        lea __interrupt_stack,%sp

2:
        | Save old SP on istack
        pea (%a0)

#endif

#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)

        .extern cyg_instrument

        | Save d1
        move.l %d1,-(%sp)

        | arg2 = 0
        move.l #0,-(%sp)

        | arg1 = vector number
        move.l %d1,-(%sp)

        | type = INTR,RAISE
        move.l #0x0301,-(%sp)

        | Call instrumentation
        jsr cyg_instrument

        | Remove args from stack
        add.l #12,%sp

        | Restore %d1
        move.l (%sp)+,%d1

#endif


#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING

        | If interrupt nesting is enabled, we have to determine the IPL of the
        | current interrupt. We inline the following macro, which is defined
        | by ColdFire variants. The vector number of the current interrupt
        | is passed in d0, and the return value is in d0.
        | Registers a0-a1/d0-d1 are for use by the macro, other registers
        | must be saved explicitly before being used.

        | Save %d1
        move.l %d1,-(%sp)

        | Pass d1 as argument to macro
        move.l %d1,%d0

        | Retrieve IPL, which will be contained in d0
        hal_variant_retrieve_ipl

        | Shift IPL up to the same position occupied in sr
        lsl.l #8,%d0

        | Transform d0 in a mask to be applied to sr
        or.l #0xfffff0ff,%d0

        | Update sr. Use d1 as working register
        move.w %sr,%d1
        and.l %d0,%d1
        move.w %d1,%sr

        | Restore d1
        move.l (%sp)+,%d1

#endif

        | We need to call the following routines. The isr address, data, and
        | intr are all from the ISR table. The interrupt_end routine is
        | only called if we are using the kernel. regs points to the saved
        | registers on the stack. isr_ret is the return value from the ISR.
        | vector is the vector number.

        | static cyg_uint32 isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)

        | externC void interrupt_end(cyg_uint32 isr_ret, Cyg_Interrupt *intr,
        |     HAL_SavedRegisters  *regs)


        | Push the data value from the table.
        .extern cyg_hal_interrupt_data
        lea     cyg_hal_interrupt_data,%a0
        move.l  (%a0,%d2.l),-(%sp)

        | Get the address of the ISR from the table.
        .extern cyg_hal_interrupt_handlers
        lea     cyg_hal_interrupt_handlers,%a0
        move.l  (%a0,%d2.l),%a0

        | Push the vector number parameter.
        move.l  %d1,-(%sp)

        | Call the ISR.
        jsr   (%a0)

        | Remove the isr parameters from the stack.
        addq.l  #4*2,%sp
                                            
        | d0.l now contains the return value from the ISR.

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK

        | If we are returning from the last nested interrupt, move back
        | to the thread stack. interrupt_end() must be called on the
        | thread stack since it potentially causes a context switch.
        | Since we have arranged for the top of stack location to
        | contain the sp we need to go back to here, just pop it off
        | and put it in SP.

        move.l (%sp),%sp                           | sp = *sp
        
#endif

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT

        | We only need to call interrupt_end() when there is a kernel
        | present to do any tidying up. To keep the following code simple,
        | we enable all interrupts before calling DSRs only if a common
        | interrupt stack is in use.

        | Push the regs pointer.
        pea     (%sp)

        | Push the intr object pointer from the table.        
        .extern cyg_hal_interrupt_objects
        lea     cyg_hal_interrupt_objects,%a0
        move.l  (%a0,%d2.l),-(%sp)

        | Push ISR return value
        move.l %d0,-(%sp)

        | Even when this is not the last nested interrupt, we must call
        | interrupt_end() to post the DSR and decrement the scheduler
        | lock.

        | Call the interrupt_end C routine.
        .extern interrupt_end
        jsr    interrupt_end

        | Remove the isr_ret, intr, and regs parameters from the stack.
        lea     (4*3)(%sp),%sp
                                            
#endif /* ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT */

        | Restore the preserved registers for the current thread.        
        int_rest_regs

        | Restore the SR and PC.
        rte


| ----------------------------------------------------------------------------
| Execute pending DSRs on the interrupt stack with interrupts enabled.
| Note: this can only be called from code running on a thread stack

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK

        .extern cyg_interrupt_call_pending_DSRs

FUNC_START(hal_interrupt_stack_call_pending_DSRs)
        | Change to interrupt stack, save state and set up stack for
        | calls to C code.
        | By virtue of GNU C calling conventions, we are free to use registers
        | %d0-%d1 and %a0-%a1 without saving them.

        | a0 = sp
        move.l %sp, %a0

        | Switch to istack
        lea __interrupt_stack,%sp

        | Save old SP on istack
        pea (%a0)

        | Save sr
        move.w %sr,%d0
        move.l %d0,-(%sp)

        | Enable interrupts
        hal_cpu_int_enable %d0
        
        | Call into kernel which will execute DSRs
        jsr cyg_interrupt_call_pending_DSRs

        move.l (%sp)+,%d0

        | Restore previous interrupt state
        hal_cpu_int_merge %d0,%d1

        | Restore sp
        move.l (%sp),%sp

        | return to caller
        rts

#endif


| ----------------------------------------------------------------------------
| Interrupt and reset stack
|
| WARNING: Do not put this in any memory section that gets initialized.
| Doing so may cause the C code to initialize its own stack.

        .section ".uninvar","aw",@nobits

        .balign 16
        .global cyg_interrupt_stack_base
cyg_interrupt_stack_base:
__interrupt_stack_base:
        .skip   CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
        .balign 16
        .global cyg_interrupt_stack
cyg_interrupt_stack:
__interrupt_stack:
        .skip   0x10

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -