📄 vectors.s
字号:
ldr r1,.__exception_handlers
ldr r2,[r1,#0x00] // reset vector intstruction
str r2,[r0,#0x00]
ldr r2,=warm_reset
str r2,[r0,#0x20]
// Relocate [copy] data from ROM to RAM
ldr r3,.__rom_data_start
ldr r4,.__ram_data_start
ldr r5,.__ram_data_end
cmp r4,r5 // jump if no data to move
beq 2f
sub r3,r3,#4 // loop adjustments
sub r4,r4,#4
1: ldr r0,[r3,#4]! // copy info
str r0,[r4,#4]!
cmp r4,r5
bne 1b
2:
#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 sp,.__startup_stack
#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]
//
.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
// 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
// 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]
mov lr,pc
ldr pc,[r1,r2,lsl #2]
#endif
// call exception handler
mov r0,sp
THUMB_MODE(r9,10)
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]
msr spsr,r0
// return to supervisor mode is simple
and r1,r0,#CPSR_MODE_BITS
cmp r1,#CPSR_SUPERVISOR_MODE
ldmeqfd sp,{r0-r14,pc}^
//
// return to other non-user modes is a little trickier
//
// switch to pre-exception mode and restore r8-r14
add r2,sp,#armreg_r8
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
// 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).
.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
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
// 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
// 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.
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]
mov v6,sp // Save pointer to register frame
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -