📄 vectors.s
字号:
.code 32 .thumb_func10:#endif// Restore [interrupted] context mov ip,sp // get stack pointer mrs r0,cpsr // move back to IRQ mode orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE msr cpsr,r0 nop nop ldr lr,[ip,#armreg_lr] ldr sp,[sp,#armreg_sp] bic r0,r0,#CPSR_MODE_BITS orr r0,r0,#CPSR_IRQ_MODE msr cpsr,r0 mov sp,ip ldr lr,[sp,#armreg_pc] ldr r0,[sp,#armreg_cpsr] ldr ip,[sp,#armreg_ip] msr spsr,r0 ldmfd sp,{r0-r10,fp} movs pc,lr // restore PC from LR, CPSR from SPSR// Handle device interrupts// This is slightly more complicated than the other exception handlers because// it needs to interface with the kernel (if present). .code 32FIQ: // Note: I use this exception stack while saving the context because // the current SP does not seem to be always valid in this CPU mode. ldr sp,.__FIQ_exception_stack // get good stack sub lr,lr,#4 // PC at time of interrupt stmfd sp!,{r0,fp,ip,lr} mrs r0,spsr stmfd sp!,{r0} b handle_IRQ_or_FIQIRQ: // Note: I use this exception stack while saving the context because // the current SP does not seem to be always valid in this CPU mode. ldr sp,.__exception_stack // get good stack sub lr,lr,#4 // PC at time of interrupt stmfd sp!,{r0,fp,ip,lr} mrs r0,spsr stmfd sp!,{r0}handle_IRQ_or_FIQ: mov ip,sp // save SP which will vanish with // mode switch mrs r0,cpsr // switch to Supervisor Mode bic r0,r0,#CPSR_MODE_BITS orr r0,r0,#CPSR_SUPERVISOR_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE msr cpsr,r0 // sp,lr are now old values mov fp,sp // save old SP sub sp,sp,#ARMREG_SIZE // make space for frame stmea sp,{r0-r10,fp} // save immediately visible registers ldmfd ip,{r0-r4} // saved registers str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt str r1,[sp,#armreg_r0] // saved R0 str r2,[sp,#armreg_fp] // saved FP str r3,[sp,#armreg_ip] // saved IP str r4,[sp,#armreg_pc] // PC at time of interrupt str lr,[sp,#armreg_lr] // LR at time of interrupt str fp,[sp,#armreg_sp] // SP at time of interrupt mov v6,sp // Save pointer to register frame// mov r0,sp// bl _show_frame_in#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK // Switch to interrupt stack ldr r2,.irq_level // current number of nested interrupts ldr r0,[r2] add r1,r0,#1 str r1,[r2] // if was zero, switch stacks cmp r0,#0 moveq r1,sp // save old stack pointer ldreq sp,.__interrupt_stack stmeqfd sp!,{r1}10:#endif // The entire CPU state is now stashed on the stack, // increment the scheduler lock and handle the interrupt#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT .extern cyg_scheduler_sched_lock ldr r3,.cyg_scheduler_sched_lock ldr r4,[r3] add r4,r4,#1 str r4,[r3]#endif#ifdef __thumb__// Switch to thumb mode ldr r3,=10f+1 bx r3 .pool .code 16 .thumb_func10:#endif mov r0,v6 bl hal_IRQ_handler // determine interrupt source mov v1,r0 // returned vector ##if defined(CYGPKG_KERNEL_INSTRUMENT) && \ defined(CYGDBG_KERNEL_INSTRUMENT_INTR) ldr r0,=RAISE_INTR // arg0 = type = INTR,RAISE mov r1,v1 // arg1 = vector mov r2,#0 // arg2 = 0 bl cyg_instrument // call instrument function#endif#ifdef __thumb__// Switch to ARM mode ldr r0,=10f bx r0 .pool .code 3210:#endif mov r0,v1 // vector ##ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS cmp r0,#0 // ignore spurious interrupts beq spurious_IRQ#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS ldr r1,.hal_interrupt_data ldr r1,[r1,v1,lsl #2] // handler data ldr r2,.hal_interrupt_handlers ldr v3,[r2,v1,lsl #2] // handler (indexed by vector #) mov r2,v6 // register frame (this is necessary // for the ISR too, for ^C detection)#ifdef __thumb__ ldr lr,=10f bx v3 // invoke handler (thumb mode) .pool .code 16 .thumb_funcIRQ_10T:10: ldr r2,=15f bx r2 // switch back to ARM mode .pool .code 3215:IRQ_15A:#else mov lr,pc // invoke handler (call indirect mov pc,v3 // thru v3)#endif#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS spurious_IRQ: #endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS #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. ldr r2,.irq_level ldr r3,[r2] subs r1,r3,#1 str r1,[r2] ldreq sp,[sp] // This should be the saved stack pointer#endif#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT // The return value from the handler (in r0) will indicate whether a // DSR is to be posted. Pass this together with a pointer to the // interrupt object we have just used to the interrupt tidy up routine. ldr r1,.hal_interrupt_objects ldr r1,[r1,v1,lsl #2] mov r2,v6 // register frame#ifdef __thumb__// Switch to thumb mode ldr r3,=10f+1 bx r3 .pool .code 16 .thumb_func10:IRQ_20T:#endif bl interrupt_end // post any bottom layer handler // threads and call scheduler#endif#ifdef __thumb__// Switch to ARM mode ldr r1,=10f bx r1 .pool .code 3210:IRQ_20A:#endif// mov r0,sp// bl show_frame_out mov ip,sp // get stack pointer mrs r0,cpsr // move back to IRQ mode orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE msr cpsr,r0 nop nop ldr lr,[ip,#armreg_lr] ldr sp,[sp,#armreg_sp] bic r0,r0,#CPSR_MODE_BITS orr r0,r0,#CPSR_IRQ_MODE msr cpsr,r0 mov sp,ip ldr lr,[sp,#armreg_pc] ldr r0,[sp,#armreg_cpsr] ldr ip,[sp,#armreg_ip] msr spsr,r0 ldmfd sp,{r0-r10,fp} movs pc,lr // restore PC from LR, CPSR from SPSR#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK// Execute pending DSRs the interrupt stack// Note: this can only be called from code running on a thread stack .global hal_interrupt_stack_call_pending_DSRs#ifdef __thumb__ .code 16 .thumb_func#endifhal_interrupt_stack_call_pending_DSRs:#ifdef __thumb__ ldr r1,=10f bx r1 .pool .code 3210:hal_interrupt_stack_call_pending_DSRs_ARM:#endif stmfd sp!,{r4,r5,lr} // Disable interrupts mrs r4,cpsr // disable IRQ's orr r2,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE bic r5,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE msr cpsr,r2 // Switch to interrupt stack mov r3,sp // save old stack pointer ldr sp,.__interrupt_stack stmfd sp!,{r3} // stored at top of interrupt stack ldr r2,.irq_level // current number of nested interrupts ldr r3,[r2] add r3,r3,#1 // bump nesting level str r3,[r2] msr cpsr,r5 // enable interrupts#ifdef __thumb__ ldr r1,=20f+1 bx r1 .pool .code 16 .thumb_func20:#endif bl cyg_interrupt_call_pending_DSRs#ifdef __thumb__ ldr r1,=22f bx r1 .pool .code 3222:#endif // Disable interrupts mrs r1,cpsr // disable IRQ's orr r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE msr cpsr,r2 // Move back to the thread stack. ldr r2,.irq_level ldr r3,[r2] sub r3,r3,#1 // decrement nesting level str r3,[r2] ldr sp,[sp] // This should be the saved stack pointer msr cpsr,r4 // restore interrupts to original state#ifdef __thumb__ ldmfd sp!,{r4,r5,lr} // return bx lr#else ldmfd sp!,{r4,r5,pc} // return#endif // __thumb__#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK // Thumb-only support functions#ifdef __thumb__ .global hal_disable_interrupts .code 16 .thumb_funchal_disable_interrupts: ldr r1,=hal_disable_interrupts_ARM bx r1 // switch to 32 bit mode .pool .code 32hal_disable_interrupts_ARM: mrs r0,cpsr // current state orr r1,r0,#0xC0 // mask both FIQ and IRQ msr cpsr,r1 bx lr // exit, _old_ in r0 .global hal_enable_interrupts .code 16 .thumb_funchal_enable_interrupts: ldr r1,=hal_enable_interrupts_ARM bx r1 // switch to 32 bit mode .pool .code 32hal_enable_interrupts_ARM: mrs r0,cpsr // current state bic r1,r0,#0xC0 // mask both FIQ and IRQ msr cpsr,r1 bx lr // exit .global hal_restore_interrupts .code 16 .thumb_funchal_restore_interrupts: ldr r1,=hal_restore_interrupts_ARM bx r1 // switch to 32 bit mode .pool .code 32hal_restore_interrupts_ARM: mrs r1,cpsr // current state bic r1,r1,#0xC0 // mask out FIQ/IRQ bits and r0,r0,#0xC0 // keep only FIQ/IRQ orr r1,r1,r0 // mask both FIQ and IRQ msr cpsr,r1 bx lr // exit .global hal_query_interrupts .code 16 .thumb_funchal_query_interrupts: ldr r1,=hal_query_interrupts_ARM bx r1 // switch to 32 bit mode .pool .code 32hal_query_interrupts_ARM: mrs r0,cpsr // current state bx lr // exit, state in r0#endif // __thumb__// Dummy/support functions .global __gccmain .global _psr .global _sp#ifdef __thumb__ .code 16 .thumb_func__gccmain: bx lr .code 16 .thumb_func_psr: ldr r1,=_psr_ARM bx r1 .pool .code 32_psr_ARM: mrs r0,cpsr bx lr .code 16 .thumb_func_sp: mov r0,sp bx lr#else__gccmain: mov pc,lr _psr: mrs r0,cpsr mov pc,lr_sp: mov r0,sp mov pc,lr#endif //// Pointers to various objects.//#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBSPTR(__GDB_stack_base)PTR(__GDB_stack)#endifPTR(__startup_stack)PTR(__FIQ_exception_stack)PTR(__exception_stack)PTR(__undef_exception_stack)PTR(__bss_start)PTR(__bss_end)PTR(_end)PTR(__rom_data_start)PTR(__ram_data_start)PTR(__ram_data_end)PTR(hal_interrupt_handlers)PTR(hal_interrupt_data)PTR(hal_interrupt_objects)PTR(__exception_handlers)PTR(init_flag)#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORTPTR(cyg_scheduler_sched_lock)#endif#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACKPTR(irq_level)PTR(__interrupt_stack)#endif//// Identification - useful to find out when a system was configured_eCos_id: .asciz "eCos : " __DATE__// -------------------------------------------------------------------------// Interrupt vector tables.// These tables contain the isr, data and object pointers used to deliver// interrupts to user code.// Despite appearances, their sizes are not #defines, but .equ symbols// generated by magic without proper dependencies in arm.inc// Recompiling will not DTRT without manual intervention. .datainit_flag: .long 0 .extern hal_default_isr .globl hal_interrupt_handlershal_interrupt_handlers: .rept CYGNUM_HAL_ISR_COUNT .long hal_default_isr .endr .globl hal_interrupt_datahal_interrupt_data: .rept CYGNUM_HAL_ISR_COUNT .long 0 .endr .globl hal_interrupt_objectshal_interrupt_objects: .rept CYGNUM_HAL_ISR_COUNT .long 0 .endr// -------------------------------------------------------------------------// Temporary interrupt stack .section ".bss"// Small stacks, only used for saving information between CPU modes__exception_stack_base: .rept 32 .long 0 .endr__FIQ_exception_stack: .rept 32 .long 0 .endr__exception_stack: .rept 32 .long 0 .endr__undef_exception_stack:// Runtime stack used during all interrupt processing#ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE#define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096#endif#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK .balign 16 .global cyg_interrupt_stack_basecyg_interrupt_stack_base:__interrupt_stack_base: .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE .byte 0 .endr .balign 16 .global cyg_interrupt_stackcyg_interrupt_stack:__interrupt_stack:irq_level: .long 0#endif#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS .balign 16__GDB_stack_base: .rept 0x400 .byte 0 .endr__GDB_stack:#endif .balign 16__startup_stack_base:#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK .rept 512#else .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE#endif .byte 0 .endr .balign 16__startup_stack:#ifdef PLATFORM_EXTRAS#include PLATFORM_EXTRAS#endif // --------------------------------------------------------------------------// end of vectors.S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -