📄 4510b_cstartup.s79
字号:
; 建立默认中断服务程序向量表
EXCEPTION_VECTOR_TABLE_SETUP
LDR r0, =HandleReset ; r0指向HandleReset(0x000050)
LDR r1, =ExceptionHandlerTable ; 异常处理分配
MOV r2, #8 ; 共8种异常
ExceptLoop ; 拷贝
LDR r3, [r1], #4
STR r3, [r0], #4
SUBS r2, r2, #1
BNE ExceptLoop
B EXCEPTION_VECTOR_TABLE_SETUP_EXIT ; 退出异常向量表设置
;---------------------------------------------------------------
; 设置异常向量服务程序入口地址
ExceptionHandlerTable
DCD UserCodeArea
DCD SystemUndefinedHandler
DCD SystemSwiHandler
DCD SystemPrefetchHandler
DCD SystemAbortHandler
DCD SystemReserv
DCD SystemIrqHandler
DCD SystemFiqHandler
;---------------------------------------------------------------
; 异常向量服务程序定义与跳转,服务程序将由C语言构成
SystemUndefinedHandler
IMPORT ISR_UndefHandler ; 从外部文件取ISR_UndefHandler标号(在main.c文件中)
STMFD sp!, {r0-r12} ; 将r0~r12压栈
B ISR_UndefHandler ; 跳转到ISR_UndefHandler服务程序
LDMFD sp!, {r0-r12, pc}^ ; r0~r12出栈,将跳转前PC备份的r14给PC,变更CPSR
; 下同
SystemSwiHandler
STMFD sp!, {r0-r12,lr}
LDR r0, [lr, #-4] ; 调整lr->调整PC
BIC r0, r0, #0xff000000
CMP r0, #0xff
BEQ MakeSVC
LDMFD sp!, {r0-r12, pc}^
MakeSVC
MRS r1, spsr
BIC r1, r1, #MODE_MASK
ORR r2, r1, #SUP_MODE
MSR spsr_cf, r2
LDMFD sp!, {r0-r12, pc}^
SystemPrefetchHandler
IMPORT ISR_PrefetchHandler ; 申明ISR_PrefetchHandler
STMFD sp!, {r0-r12, lr}
B ISR_PrefetchHandler
LDMFD sp!, {r0-r12, lr}
;ADD sp, sp, #4
SUBS pc, lr, #4 ; 调整PC,恢复CPSR
SystemAbortHandler
IMPORT ISR_AbortHandler ; 申明ISR_AbortHandler
STMFD sp!, {r0-r12, lr}
B ISR_AbortHandler
LDMFD sp!, {r0-r12, lr}
;ADD sp, sp, #4
SUBS pc, lr, #8 ; 调整PC,恢复CPSR
SystemReserv
SUBS pc, lr, #4
SystemIrqHandler
IMPORT ISR_IrqHandler ; 申明ISR_IrqHandler
STMFD sp!, {r0-r12, lr} ; 压栈
BL ISR_IrqHandler ; 带备份CPSR的跳转
LDMFD sp!, {r0-r12, lr} ; 出栈
SUBS pc, lr, #4 ; 调整PC,恢复CPSR(IRQ调整量为-4)
SystemFiqHandler
IMPORT ISR_FiqHandler ; 申明ISR_FiqHandler
STMFD sp!, {r0-r7, lr} ; 压栈
BL ISR_FiqHandler ; 带备份CPSR的跳转
LDMFD sp!, {r0-r7, lr} ; 出栈
SUBS pc, lr, #4 ; 调整PC,恢复CPSR(FIQ调整量为-4)
EXCEPTION_VECTOR_TABLE_SETUP_EXIT:
; 异常向量服务程序定义与跳转,服务程序由C语言构成
;---------------------------------------------------------------
;---------------------------------------------------------------
; 始初化段并调用 __segment_init,__low_level_init,main
; 说明:
; 1.三个程序分别在segment_init.c,low_level_init.c,main.c文件中
#ifdef __THUMB_LIBRARY__
ADD r12,pc,#1 ; 若用THUMB库,调整PC
BX r12 ; THUMB态跳转
#endif
CPU_MODE ; 即CODE32/16
#ifdef __THUMB_LIBRARY__
?thumb_entry: ; 定义THUMB入口标号
#endif
LDR r4,=__low_level_init ; 设置__low_level_init
LDR r5,=after__low_level_init
LDR r6,=__segment_init ; 设置__segment_init
LDR r7,=after__segment_init
MOV lr,r5 ; 指定返回地址
BX r4 ; 调用__low_level_init 程序(在low_level_init.c文件中)
after__low_level_init:
CMP r0,#0
BEQ after__segment_init ; 如__low_level_init 返回0,则跳至after__segment_init标志
MOV lr,r7 ; 指定返回地址
BX r6 ; 否则跳至__segment_init程序(在segment_init.c文件中)
LTORG
CPU_MODE ; 即CODE32/16
after__segment_init:
REQUIRE ?jump_to_main ; 定义了?jump_to_main标号的文件/段将被连接器包含
;---------------------------------------------------------------
; 对main程序之前定义的全局变量,调用全局EC++的对象构造器对这些对象进行构造
#ifdef _ECPLUSPLUS
RSEG ICODE:CODE:NOROOT(2)
PUBLIC ?call_ctors
CPU_MODE ; 即CODE32/16
?call_ctors:
LDR r0,=SFB(DIFUNCT) ; r0指向DIFUNCT的始端
LDR r1,=SFE(DIFUNCT) ; r1指向DIFUNCT的尾端
LDR r4,=__call_ctors ; r4指向__call_ctors
LDR r5,=after__call_ctors
MOV lr,r5 ; r5指向返回地址
BX r4 ; 调用__call_ctors
LTORG
CPU_MODE ; 即CODE32/16
after__call_ctors:
#endif /* _ECPLUSPLUS */
;---------------------------------------------------------------
; main设置与调用
; 说明:
; 1.用BX指令跳转到main程序中,_exit作为返回地址.
; 2.main程序可放置在存储器任何位置,而且可为Arm或Thumb态,所以使用BX指令跳转之.
; 3.main使用BX (_interwork)返回,否则当与cstartup启动代码不为同一态时会出现错误,引起不可想象的后果,恐怖哦!: )
RSEG ICODE:CODE:NOROOT(2) ; 开始一个可重定位代码段,名称为ICODE,NOROOT->该段在没被用时可被放弃连接
PUBLIC __main ; 申明__main
CPU_MODE ; 即CODE32/16
?jump_to_main:
; 设置user sp,如果用操作系统此段代码屏蔽(运行在sys模式)
BIC r0,r0,#MODE_BITS ; 清模式
ORR r0,r0,#USR_MODE ; 设置USER模式位
MSR cpsr_c,r0 ; 改变到USER模式
LDR sp,=SFE(CSTACK) & 0xFFFFFFF8 ; sp指向CSTACK尾端
LDR r4,=main ; r4指向main(在main.c文件中)
LDR r5,=__main ; 返回地址指向__main
MOV r0,#0 ; r0 = 0,表示无参数调用
MOV lr,r5 ; lr指向__main,以使程序返回时给PC
BX r4 ; 跳至用户main程序(在main.c文件中)
CPU_MODE ; 即CODE32/16
__main:
?call_exit:
LDR r4,=exit
LDR r5,=_exit ; _exit被接续到另一个段中,所以不可能继续执行到_exit中
MOV lr,r5
BX r4 ; 跳至exit程序
LTORG
ENDMOD ?cstartup ; ?cstartup程序模块结束
; ?cstartup程序模块
;---------------------------------------------------------------
;---------------------------------------------------------------
; ?_EXIT程序模块
; 说明:
; 1.main程序执行可能会给出返回码至r0,或者_exit可能被main的返回码r0调用.
; 2.如果需要使用返回码r0,r0则要保存在R4~R7之一中,使得调用当调用__call_dtors与_Close_all时被保护.
MODULE ?_EXIT ; ?_EXIT程序模块开始
RSEG LIB_SEGMENT:CODE:NOROOT(SEGMENT_ALIGN) ; 代码段,名为LIB_SEGMENT,可被略弃
PUBLIC _exit ; 申明_exit
REQUIRE ?jump_to_exit ; 连接时包含定义?jump_to_exit标号的段
CPU_MODE ; 即CODE32/16
_exit:
; 继续下一个模块
RSEG LIB_SEGMENT:CODE:NOROOT(SEGMENT_ALIGN)
REQUIRE ?exit_restore ; 连接时包含定义?exit_restore标号的段
PUBLIC ?exit_save ; 申明?exit_save
CPU_MODE ; 即CODE32/16
?exit_save:
MOV r7,r0 ; 保存r0至r7
;---------------------------------------------------------------
; ?CALL_DTORS模块
; 说明:
; 1.该模块仅在需要main程序自动退出时才被连接.
RSEG LIB_SEGMENT:CODE:NOROOT(SEGMENT_ALIGN)
PUBLIC __cstart_call_dtors
REQUIRE ?exit_save ; 连接时包含定义?exit_save标号的段
CPU_MODE ; 即CODE32/16
__cstart_call_dtors: ; 此标志被__record_needed_destruction调用
LDR r4,?constants ; r4指向__call_dtors(外部)
LDR r5,?constants+4 ; r5指向after__call_dtors
MOV lr,r5
BX r4 ; 调用__call_dtors
after__call_dtors: ; 继续下一段
;---------------------------------------------------------------
; ?CALL_CLOSE段
; 说明:
; 1.该段仅在需要关闭文件时才被连接.
RSEG LIB_SEGMENT:CODE:NOROOT(SEGMENT_ALIGN)
PUBLIC __cstart_closeall
EXTERN _Close_all
REQUIRE ?exit_save ; 连接时包含定义?exit_save标号的段
CPU_MODE ; 即CODE32/16
__cstart_closeall: ; 对文件操作时需要__cstart_closeall标志
LDR r4,?constants+8 ; r4指向_Close_all
LDR r5,?constants+12 ; r5指向after_Close_all
MOV lr,r5
BX r4 ; 跳至_Close_all
after_Close_all:
;---------------------------------------------------------------
; ?_EXIT_END段
RSEG LIB_SEGMENT:CODE:NOROOT(SEGMENT_ALIGN)
PUBLIC ?exit_restore
CPU_MODE ; 即CODE32/16
?exit_restore:
MOV r0,r7 ; 从r7恢复r0
;---------------------------------------------------------------
; ?JUMP_TO_EXIT段
; 说明:
; 1.不会继续执行去调用__exit,除非在当调试时使用XLINK -r来连接
RSEG LIB_SEGMENT:CODE:NOROOT(SEGMENT_ALIGN)
PUBLIC ?jump_to_exit ; 申明?jump_to_exit
EXTERN __exit
?jump_to_exit:
LDR r4,?constants+16 ; r4指向__exit
MOV lr,r4
BX r4 ; 跳至__exit
RSEG LIB_SEGMENT:CODE:NOROOT(SEGMENT_ALIGN)
EXTERN __call_dtors
EXTERN _Close_all
EXTERN __exit
DATA
?constants:
DC32 __call_dtors ; ?constants+0
DC32 after__call_dtors ; ?constants+4
DC32 _Close_all ; ?constants+8
DC32 after_Close_all ; ?constants+12
DC32 __exit ; ?constants+16
ENDMOD ; ?_EXIT程序模块结束
; ?_EXIT程序模块
;---------------------------------------------------------------
;---------------------------------------------------------------
; ?__EXIT程序模块
; 说明
; 1.__exit被申明为PUBWEAK型,当其他拥有__exit公共段的模块被连接时,连接器将略弃该处的?__EXIT模块
MODULE ?__EXIT ; ?__EXIT程序模块开始
RSEG LIB_SEGMENT:CODE:NOROOT(2)
PUBWEAK __exit
CPU_MODE ; 即CODE32/16
__exit
#ifdef __THUMB_LIBRARY__
BX pc
NOP
#endif
CODE32
B . ; 永久循环
ENDMOD ; ?__EXIT程序模块结束
; ?__EXIT程序模块
;---------------------------------------------------------------
;---------------------------------------------------------------
; ?INITTAB模块
; 说明:
; 1.该模块仅在__segment_init程序中需要时才被连接.
; 2.该模块包含了段初始化入口(参见segment_init.h).
MODULE ?INITTAB ; ?INITTAB程序模块开始
RSEG INITTAB:CONST(2) ; Declaration for SFB/SFE below
RSEG HUGE_C:CONST:NOROOT(2)
DATA
PUBLIC __segment_begin_INITTAB
PUBLIC __segment_end_INITTAB
__segment_begin_INITTAB DC32 SFB(INITTAB)
__segment_end_INITTAB DC32 SFE(INITTAB)
ENDMOD ; ?INITTAB程序模块结束
; ?INITTAB程序模块
;---------------------------------------------------------------
END
; 文件结束
;---------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -