📄 vectors.s
字号:
// initialize interrupt/exception environments ldr sp,.__startup_stack mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE) msr cpsr,r0 ldr sp,.__exception_stack mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE) msr cpsr,r0 ldr sp,.__exception_stack // initialize CPSR (machine state register) mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE) msr cpsr,r0 // Note: some functions in LIBGCC1 will cause a "restore from SPSR"!! msr spsr,r0 // initialize stack#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK // use interrupt stack for system initialization since it's bigger // than the "startup" stack in this configuration ldr sp,.__interrupt_stack#else ldr sp,.__startup_stack#endif // clear BSS ldr r1,.__bss_start ldr r2,.__bss_end mov r0,#0 cmp r1,r2 beq 2f1: str r0,[r1],#4 cmp r1,r2 bls 1b2: // Run kernel + application in THUMB mode THUMB_MODE(r1,10) LED 3 // Call platform specific hardware initialization bl hal_hardware_init#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS bl initialize_stub // Now that stub is initialized, change vector. It is possible // to single-step through most of the init code, except the below. // Put a breakpoint at the call to cyg_hal_invoke_constructors to // pass over this bit (s-s depends on internal state in the stub).#endif#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) || \ defined(CYGIMP_HAL_PROCESS_ALL_EXCEPTIONS) mov r0,#0 // move vectors ldr r1,=__exception_handlers ldr r2,[r1,#0x04] // undefined instruction str r2,[r0,#0x04] ldr r2,[r1,#0x24] str r2,[r0,#0x24]#endif#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) .extern hal_ctrlc_isr_init bl hal_ctrlc_isr_init#endif LED 2 // Run through static constructors bl cyg_hal_invoke_constructors LED 1 // This starts up the eCos kernel#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK ldr r1,=__startup_stack mov sp,r1#endif bl cyg_start_start_hang: b _start_hang .code 32 .global reset_platform .type reset_platform,functionreset_platform: #ifdef CYGSEM_HAL_ROM_MONITOR // initialize CPSR (machine state register) mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE) msr cpsr,r0 b warm_reset#else mov r0,#0 mov pc,r0 // Jump to reset vector #endif init_done: .long 0xDEADB00B//// Exception handlers// Assumption: get here from a non-user context [mode]// except in case of standalone app. running in user mode// (CYGOPT_HAL_ARM_WITH_USER_MODE should have been defined)// .code 32undefined_instruction: ldr sp,.__undef_exception_stack // get good stack stmfd sp!,{r0-r5} // save some supervisor regs mrs r1,spsr tst r1,#CPSR_THUMB_ENABLE subeq r0,lr,#4 // PC at time of interrupt (ARM) subne r0,lr,#2 // PC at time of interrupt (thumb) mov r2,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION mov r3,sp b call_exception_handler .code 32software_interrupt: stmfd sp!,{r8} ldr r8,.__undef_exception_stack // get good stack stmfd r8!,{r0-r5} // save some supervisor regs mov r3,r8 ldmfd sp!,{r8} mrs r1,spsr tst r1,#CPSR_THUMB_ENABLE subeq r0,lr,#4 // PC at time of SWI (ARM) subne r0,lr,#2 // PC at time of SWI (thumb) mov r2,#CYGNUM_HAL_EXCEPTION_INTERRUPT b call_exception_handler .code 32abort_prefetch: ldr sp,.__undef_exception_stack // get good stack stmfd sp!,{r0-r5} // save some supervisor regs sub r0,lr,#4 // PC at time of interrupt mrs r1,spsr mov r2,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS mov r3,sp b call_exception_handler .code 32abort_data: ldr sp,.__undef_exception_stack // get good stack stmfd sp!,{r0-r5} // save some supervisor regs sub r0,lr,#4 // PC at time of interrupt mrs r1,spsr mov r2,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS mov r3,sp b call_exception_handler //// Dispatch an exception handler. .code 32call_exception_handler: // // On Entry: // // r4,r5 = scratch // r3 = pointer to temp save area // r2 = vector number // r1 = exception psr // r0 = exception pc // // [r3+20]: exception r5 // [r3+16]: exception r4 // [r3+12]: exception r3 // [r3+8] : exception r2 // [r3+4] : exception r1 // [r3] : exception r0 mrs r4,cpsr // switch to Supervisor Mode bic r4,r4,#CPSR_MODE_BITS orr r4,r4,#CPSR_SUPERVISOR_MODE msr cpsr,r4 mov r5,sp // save original svc sp mov r4,lr // and original svc lr#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS // Make sure we use the GDB stack. ldr sp,.__GDB_stack cmp r5,sp // already on GDB stack? bhi 10f ldr r4,.__GDB_stack_base cmp r5,r4 movhi sp,r510:#endif // // r5 holds original svc sp, current sp is stack to use // r4 holds original svc lr, which must also be preserved // stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE // did exception occur in user mode ? and r2, r1, #CPSR_MODE_BITS cmp r2, #CPSR_USER_MODE bne 1f stmfd sp, {r8-r12, sp, lr}^ // get user mode regs nop sub sp, sp, #4*7 bal 2f1:#endif // switch to pre-exception mode to get banked regs mov r0,sp // r0 survives mode switch mrs r2,cpsr // Save current psr for return orr r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE bic r1,r1,#CPSR_THUMB_ENABLE msr cpsr,r1 stmfd r0!,{r8-r12,sp,lr} msr cpsr,r2 // back to svc mode mov sp,r0 // update stack pointer2: // now save pre-exception r0-r7 on current stack ldmfd r3,{r0-r5} stmfd sp!,{r0-r7} // SP needs fixing if exception occured in SVC mode. // The original SVC LR is still in place so that // does not need to be fixed here. ldr r1,[sp,#armreg_cpsr] and r1,r1,#CPSR_MODE_BITS cmp r1,#CPSR_SUPERVISOR_MODE ldreq r1,[sp,#armreg_svcsp] streq r1,[sp,#armreg_sp]#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS mov r0,sp ldr r1,.__dump_procs ldr r2,[sp,#armreg_vector] ldr r1,[r1,r2,lsl #2] THUMB_MODE(r9,10) mov lr,pc mov pc,r1#else THUMB_MODE(r9,10)#endif // call exception handler mov r0,sp bl exception_handler#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS mov r0,sp bl cyg_hal_report_exception_handler_returned#endif ARM_MODE(r1,10) // // Return from exception //return_from_exception: ldr r0,[sp,#armreg_cpsr] // return to supervisor mode is simple and r1,r0,#CPSR_MODE_BITS cmp r1,#CPSR_SUPERVISOR_MODE#ifndef CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR msr spsr,r0 ldmeqfd sp,{r0-r14,pc}^#else // we must take care of not corrupting the current (svc) // spsr which happens to be also the pre-exception spsr bne 1f tst r0, #CPSR_THUMB_ENABLE // when returning to thumb/svc mode, there is no easy way to preserve // spsr. It is possible to do so, but would add a lot of instructions. // The purpose of CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR is to allow stepping // through SWI exception handling code, so not preserving spsr in this // case should be okay. msrne spsr,r0 ldmnefd sp,{r0-r14,pc}^ // we are returning to arm/svc mode thus we must restore the // pre-exception cpsr before returning to interrupted code msr cpsr, r0 ldmfd sp, {r0-r14, pc}1: // we are not returning to svc mode thus we can safely restore // svc spsr msr spsr, r0#endif#ifdef CYGOPT_HAL_ARM_WITH_USER_MODE // are we returning to user mode ? and r2, r1, #CPSR_MODE_BITS cmp r2, #CPSR_USER_MODE add r2, sp, #armreg_r8 bne 1f ldmfd r2, {r8-r14}^ // restore user mode regs nop bal 2f1:#else add r2, sp, #armreg_r8#endif // // return to other non-user modes is a little trickier // // switch to pre-exception mode and restore r8-r14 mrs r1,cpsr orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE bic r0,r0,#CPSR_THUMB_ENABLE msr cpsr,r0 ldmfd r2,{r8-r14} msr cpsr, r1 // back to svc mode2: // move sp,lr and pc for final load ldr r0,[sp,#armreg_svcsp] str r0,[sp,#armreg_r8] ldr r0,[sp,#armreg_svclr] str r0,[sp,#armreg_r9] ldr r0,[sp,#armreg_pc] str r0,[sp,#armreg_r10] // restore r0-r7,sp,lr and return from exception ldmfd sp,{r0-r7,sp,lr,pc}^#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS__dump_procs: .word 0 // placeholder for reset .word cyg_hal_report_undefined_instruction .word cyg_hal_report_software_interrupt .word cyg_hal_report_abort_prefetch .word cyg_hal_report_abort_data .word 0 // reserved#endif// Handle device interrupts// This is slightly more complicated than the other exception handlers because// it needs to interface with the kernel (if present).// Assumption: can get here from any mode, including user mode// (spurious interrupt while standalone app. is running in user mode) .code 32FIQ: // We can get here from any non-user mode. mrs r8,spsr // CPSR at time of interrupt and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode cmp r9,#CPSR_IRQ_MODE bne 1f // If FIQ interrupted IRQ mode, just return with FIQ disabled. // The common interrupt handling takes care of the rest. orr r8,r8,#CPSR_FIQ_DISABLE msr spsr,r8 subs pc,lr,#4 1: // If FIQ interrupted other non-user mode, switch to IRQ mode and // fall through to IRQ handler. ldr sp,.__exception_stack // get good stack to save lr and spsr stmdb sp,{r8,lr} mov r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE msr cpsr,r8 // switch to IRQ mode ldr sp,.__exception_stack // get regs saved in FIQ mode ldmdb sp,{sp,lr} msr spsr,sp // now it looks like we got an IRQ instead of an FIQ except that // FIQ is disabled so we don't recurse.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 stmfd sp!,{r0-r5} // save some supervisor regs sub r0,lr,#4 // PC at time of interrupt mrs r1,spsr mov r2,#CYGNUM_HAL_VECTOR_IRQ mov r3,sp handle_IRQ_or_FIQ: mrs r4,cpsr // switch to Supervisor Mode bic r4,r4,#CPSR_MODE_BITS orr r4,r4,#CPSR_SUPERVISOR_MODE msr cpsr,r4 mov r5,sp // save original svc sp mov r4,lr // save original svc lr stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE // did exception occur in user mode ? and r2, r1, #CPSR_MODE_BITS cmp r2, #CPSR_USER_MODE bne 1f stmfd sp, {r8-r12, sp, lr}^ // get user mode regs nop sub sp, sp, #4*7 bal 2f1:#endif // switch to pre-exception mode to get banked regs
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -