vectors.s
来自「ecos为实时嵌入式操作系统」· S 代码 · 共 761 行 · 第 1/2 页
S
761 行
#endif 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 add r0,ip,#ARMREG_SIZE str fp,[sp,#armreg_sp] // SP at time of interrupt#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS mov r0,sp bl abort_data#endif mov v1,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS b call_exception_handlerFIQ: ldr sp,.__startup_stack // get good stack sub lr,lr,#4 // PC at time of interrupt stmfd sp!,{r0,ip,lr} mrs r0,spsr stmfd sp!,{r0} 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 msr cpsr,r0 // sp,lr are now old values mov ip,sp ldr sp,.__startup_stack // get good stack sub sp,sp,#ARMREG_SIZE+16 // make space for frame stmea sp,{r0-r10,fp} // save immediately visible registers ldmfd ip,{r0-r3} // saved registers str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt str r1,[sp,#armreg_r0] // saved R0 str r2,[sp,#armreg_ip] // saved IP str r3,[sp,#armreg_pc] // PC at time of interrupt str lr,[sp,#armreg_lr] // LR at time of interrupt add r0,ip,#ARMREG_SIZE str r0,[sp,#armreg_sp] // SP at time of interrupt#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS mov r0,sp bl FIQ#endif mov v1,#CYGNUM_HAL_EXCEPTION_FIQ b call_exception_handler//// Dispatch an exception handler.call_exception_handler: str v1,[sp,#armreg_vector] mov r0,sp bl exception_handler#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS mov r0,sp bl exception_handler_returned#endif// Restore [interrupted] context mov ip,sp // get stack pointer ldr lr,[ip,#armreg_lr] ldr sp,[sp,#armreg_sp] mrs r0,cpsr // move back to IRQ mode 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).IRQ: // 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} 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 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 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 mov r0,v1 // vector # 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 mov lr,pc // invoke handler (call indirect mov pc,v3 // thru v3)#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] bl interrupt_end // post any bottom layer handler // threads and call scheduler#endif// mov r0,sp// bl show_frame_out mov ip,sp // get stack pointer ldr lr,[ip,#armreg_lr] ldr sp,[sp,#armreg_sp] mrs r0,cpsr // move back to IRQ mode 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_DSRshal_interrupt_stack_call_pending_DSRs: stmfd sp!,{r4,r5,lr} // Disable interrupts mrs r4,cpsr // disable IRQ's orr r2,r4,#CPSR_IRQ_DISABLE bic r5,r4,#CPSR_IRQ_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 bl cyg_interrupt_call_pending_DSRs // Disable interrupts mrs r1,cpsr // disable IRQ's orr r2,r1,#CPSR_IRQ_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 ldmfd sp!,{r4,r5,pc} // return#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK// Dummy functions .global __gccmain__gccmain: mov pc,lr .global _psr_psr: mrs r0,cpsr mov pc,lr .global _sp_sp: mov r0,sp mov pc,lr//// Pointers to various objects.//#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBSPTR(__GDB_stack_base)PTR(__GDB_stack)#endifPTR(__startup_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// -------------------------------------------------------------------------// Interrupt vector tables.// These tables contain the isr, data and object pointers used to deliver// interrupts to user code. .datainit_flag: .long 0 .extern hal_default_isr .globl hal_vsr_tablehal_vsr_table: .rept CYGNUM_HAL_VSR_COUNT .long 0 // hal_default_isr .endr .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__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__interrupt_stack_base: .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE .byte 0 .endr .balign 16__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:// --------------------------------------------------------------------------// end of vectors.S
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?