📄 vectors.s
字号:
#endif
// 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 2f
1: str r0,[r1],#4
cmp r1,r2
bls 1b
2:
// 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,function
reset_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 32
undefined_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 32
software_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 32
abort_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 32
abort_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 32
call_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,r5
10:
#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 2f
1:
#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 pointer
2:
// 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 2f
1:
#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 mode
2:
// 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 32
FIQ:
// 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
mrs r4,cpsr // switch to Supervisor Mode
bic r4,r4,#CPSR_MODE_BITS
// When handling an IRQ we must disable FIQ unless the current
// mode in CPSR is IRQ. If we were to get a FIQ while in another
// mode, the FIQ handling code would transform the FIQ into an
// IRQ and call the non-reentrant IRQ handler again. As a result,
// for example, the stack pointer would be set to the beginning
// of the exception_stack clobbering the registers we have just
// saved.
orr r4,r4,#CPSR_SUPERVISOR_MODE|CPSR_FIQ_DISABLE
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -