⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 4510b_cstartup.s79

📁 4510b的启动源码
💻 S79
📖 第 1 页 / 共 2 页
字号:
; 建立默认中断服务程序向量表

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 + -