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

📄 4510b_cstartup.s79

📁 4510b的启动源码
💻 S79
📖 第 1 页 / 共 2 页
字号:
;---------------------------------------------------------------
; 文件说明
;
; 1.该文件包括了启动代码(针对ICCARM编译器).
; 2.文件中的模块含在库中,也可以被用户定义,例如?cstartup等.如整个文件被汇编并与库连接,
;   则在XLINK中使用-C参数(或勾选"Ignore CSTARTUP in library")以防与?RESET模块发生冲突.
; 3.所以代码除?RESET模块,都将被放在ICODE段中,并确保INTVEC段代码能跳转到.
; 4.该文件中包含?RESET,?cstartup,?_EXIT,?__EXIT,?INITTAB五个模块.
; 编者:汪仔,淳仔
; 时间:2002.5.20
; 版本:1.1
;
; 文件说明
;---------------------------------------------------------------

;---------------------------------------------------------------
; 历史说明
;
; 1.  v1.0  2002.3.26 汪仔编写主程序
; 2.  v1.1  2003.5.20 淳仔编写注释,添加头文件,删除多余的异常处理段定义(如FIQ_Handler)
;
; 历史说明
;---------------------------------------------------------------

;---------------------------------------------------------------
; 标志使用说明
; 注:标号(Label)指代表地址的符号(Symbols)

;  ?xxx	  - 外部标号仅供汇编访问
;  __xxx  - 外部标号供C定义/访问
;  xxx	  - 内部标号
;  main	  - 用户程序起点

; 标志使用说明
;---------------------------------------------------------------

          INCLUDE 4510b_cstartup.hdr    ; 包括头文件

;---------------------------------------------------------------
; 定义Arm或Thumb库

//#define __THUMB_LIBRARY__ 1
#define __ARM_LIBRARY__ 1               ; 定义Arm库       

#ifdef __ARM_LIBRARY__                  ; 确保不重复库定义
#ifdef __THUMB_LIBRARY__
#error "Cannot have both __ARM_LIBRARY__ and __THUMB_LIBRARY__ set!"
#endif
#else                                   ; 确保不缺少库定义
#ifndef __THUMB_LIBRARY__
#error "Must have one of  __ARM_LIBRARY__ or __THUMB_LIBRARY__ set!"
#endif
#endif

; 定义Arm或Thumb库
;---------------------------------------------------------------

;---------------------------------------------------------------
; 文件的宏与定义
; 说明:
; 1.对应ARM寄存器CPSR[5..0]决定了ARM的模式

#if __LITTLE_ENDIAN__==1                ; 定义大/小端
#define ENDIAN_MODE	"little"
#else
#define ENDIAN_MODE	"big"
#endif

#ifdef __THUMB_LIBRARY__                ; 如定义了Thumb库则
#define CPU_MODE_NAME	"thumb"         ; 定义CPU为Thumb态
#define LIB_SEGMENT	NEARFUNC_T      ; for库的代码段
CPU_MODE	MACRO                   ; 指令代码为16位,即Thumb指令
		CODE16
		ENDM
#else		/////// __ARM_LIBRARY__ ; 否则
#define CPU_MODE_NAME	"arm"           ; 定义CPU为Arm态
#define LIB_SEGMENT	NEARFUNC_A      ; for库的代码段
CPU_MODE	MACRO                   ; 指令代码为32位,即Arm指令
		CODE32
		ENDM
#endif

SEGMENT_ALIGN	DEFINE	2               ; 以下指令以2^2字节对齐

; 文件的宏与定义
;---------------------------------------------------------------

;---------------------------------------------------------------
; ?RESET程序模块
; 说明:
; 1.INTVEC指Interrupt Vector
; 2.复位后是INTVEC段,通常INTVEC段异常向量是放在地址0x0处,调试时可能处于其他位置.
; 3.即使INTVEC段不在0x00处,拥有其入口地址调试器将正常进入程序并执行.
; 4.第一次,把异常向量表写向flash.
; 5.规定注释用语:r0->r0值,[r0]->r0内容

		PROGRAM	?RESET            ; ?RESET程序模块开始
		COMMON	INTVEC:CODE:ROOT(2) ; 开始INTVEC段,是一个CODE段
		                          ; 通常把INTVEC指定成COMMON类型,是为了程序若干都能访问INTVEC
		EXTERN	?cstartup         ; ?cstartup不在本模块中,但在本模块使用到,需申明成外部类型
		CODE32	                  ; 复位后CPU是Arm态
		ORG	0	          ; 指定本模块放置在0x00地址处

		PUBLIC  FIQ_Handler
		PUBLIC  IRQ_Handler
		PUBLIC  Prefetch_Handler
		PUBLIC  Abort_Handler
		PUBLIC  Undefined_Handler
		PUBLIC  SWI_Handler

reset	                                  ; 复位标号
                B	?cstartup         ; 上电/复位后,PC跳至?cstartup,即启动代码处
                B       Undefined_Handler ; PC跳至非法指令异常处理入口
                B       SWI_Handler       ; PC跳至软件中断异常处理入口
                B       Prefetch_Handler  ; PC跳至预取中止异常处理入口
                B       Abort_Handler     ; PC跳至数据中止异常处理入口
                NOP     		  ; 保留备用
                B       IRQ_Handler       ; PC跳至IRQ异常处理入口
                B       FIQ_Handler       ; PC跳至FIQ异常处理入口

FIQ_Handler                               ; FIQ异常处理入口
	SUB	sp, sp, #4                ; 保存r0值到sp栈
	STMFD	sp!, {r0}
	LDR	r0, =HandleFiq            ; 把HandleFiq标号地址给r0
	LDR	r0, [r0]                  ; 把r0内容给r0
	STR	r0, [sp, #4]              ; 把r0值放在sp+4处
	LDMFD	sp!, {r0, pc}             ; 把sp出栈到r0与pc中
	                                  ; 此6行代码是使PC指向HandleFiq(即0x00006c)地址里放的代码
	                                  ; 下同

IRQ_Handler                               ; IRQ异常处理入口
	SUB	sp, sp, #4
	STMFD	sp!, {r0}
	LDR	r0, =HandleIrq
	LDR	r0, [r0]
	STR	r0, [sp, #4]
	LDMFD	sp!, {r0, pc}

Prefetch_Handler                          ; 预取中止异常处理入口
	SUB	sp, sp, #4
	STMFD	sp!, {r0}
	LDR	r0, =HandlePrefetch
	LDR	r0, [r0]
	STR	r0, [sp, #4]
	LDMFD	sp!, {r0, pc}

Abort_Handler                             ; 数据中止异常处理入口
	SUB	sp, sp, #4
	STMFD	sp!, {r0}
	LDR	r0, =HandleAbort
	LDR	r0, [r0]
	STR	r0, [sp, #4]
	LDMFD	sp!, {r0, pc}

Undefined_Handler                         ; 非法指令异常处理入口
	SUB	sp, sp, #4
	STMFD	sp!, {r0}
	LDR	r0, =HandleUndef
	LDR	r0, [r0]
	STR	r0, [sp, #4]
	LDMFD	sp!, {r0, pc}

SWI_Handler                               ; SWI异常处理入口
	SUB	sp, sp, #4
	STMFD	sp!, {r0}
	LDR	r0, =HandleSwi
	LDR	r0, [r0]
	STR	r0, [sp, #4]
	LDMFD	sp!, {r0, pc}

		ENDMOD                    ; ?RESET程序模块结束

; ?RESET程序模块
;---------------------------------------------------------------

;---------------------------------------------------------------
; 启动代码?CSTARTUP的设置与各程序模块申明
; 说明:
; 1.RTMODEL设置了模块的一些属性,使得各模块间在连接时要保证某些重要参数是统一的

		PROGRAM	?CSTARTUP         ; ?CSTARTUP程序模块开始
		RTMODEL "__endian", ENDIAN_MODE ; 设__endian为定义好的端模式
		RTMODEL "__thumb_aware", "enabled"  ; 设__thumb_aware为enabled
		RTMODEL "__cpu_mode", "*"       ; ARM/THUMB态都可以
		RTMODEL "__code_model", "*"	; ARM/THUMB指令都可以

#ifdef _ECPLUSPLUS
		RSEG	DIFUNCT(2)              ; 开始一个段,名为DIFUNCT
#endif /* _ECPLUSPLUS */
		RSEG	IRQ_STACK:DATA(2)       ; 开始一个数据段,作为IRQ_STACK堆栈
		RSEG    ABT_STACK:DATA(2)       ; 开始一个数据段,作为ABT_STACK堆栈
		RSEG    UND_STACK:DATA(2)       ; 开始一个数据段,作为UND_STACK堆栈
		RSEG    FIQ_STACK:DATA(2)       ; 开始一个数据段,作为FIA_STACK堆栈
		RSEG	SVC_STACK:DATA:NOROOT(2); 开始一个数据段,作为SVC_STACK堆栈
		RSEG	CSTACK:DATA(2)          ; 开始一个数据段,作为CSSTACK堆栈
		RSEG	ICODE:CODE:NOROOT(2)    ; 开始一个代码段,名为ICODE

		PUBLIC	?cstartup               ; ?cstartup申明为公用类型,可供其他模块使用
#ifdef __THUMB_LIBRARY__
		PUBLIC	?thumb_entry            ; ?thumb_entry申明为公用类型
#endif /*  __THUMB_LIBRARY__ */
		EXTERN	__segment_init          ; __segment_init申明为外部类型
		EXTERN	__low_level_init        ; __low_level_init申明为外部类型
#ifdef _ECPLUSPLUS
		EXTERN	__call_ctors            ; __call_ctors申明为外部类型
#endif /*  _ECPLUSPLUS */
		EXTERN	main                    ; main申明为外部类型
		EXTERN  exit                    ; exit申明为外部类型
		EXTERN	_exit                   ; _exit申明为外部类型

		EXTERN  FIQ_Handler
		EXTERN  IRQ_Handler
		EXTERN  Prefetch_Handler
		EXTERN  Abort_Handler
		EXTERN  Undefined_Handler
		EXTERN  SWI_Handler

; 启动代码?CSTARTUP的设置
;---------------------------------------------------------------

;---------------------------------------------------------------
; ?cstartup程序模块
; 说明:
; 1.上电/复位后,CPU为Arm态,处于管理模式下,关闭中断

		LTORG                           ; 指定一个数据缓冲池
		CODE32                          ; 以下是ARM指令

?cstartup                                       ; ?cstartup标号
                LDR	r1, =IntMask            ; 屏蔽所有中断服务
	        LDR	r0, =0xFFFFFFFF
	        STR	r0, [r1]
	                                        ; 设置super mode
	        ;LDR	r0, =HandleSwi	        ; SWI exception table address
 	        ;LDR	r1, =SystemSwiHandler
	        ;STR	r1, [r0]
 	        ;SWI    0xFF 			;/* Call SWI Vector  */

	        LDR	r0, =0x3FF0000          ; 设置SYSCFG=0x87FFFF90;RAM为SDRAM类型;设置了8KCache,但unenable;写缓冲disable		
	        LDR	r1, =0x87FFFF90
	        STR	r1, [r0]

                LDR     r13, PtInitRemap        ; PC入栈,保存remap后PC地址
                LDR     r0, =SystemInitDataSDRAM
	        LDMIA   r0, {r1-r12}            ; 将rEXTDBWTH~rSREFEXTCON入栈
	        LDR	r0, =0x3FF0000 + 0x3010 ; 从0x3FF3010开始写
	        STMIA   r0, {r1-r12}            ; rEXTDBWTH~rSREFEXTCON出栈写向EXTDBWTH,ROMCON0~ROMCON5,DRAMCON0~DRAMCON3,REFEXTCON等12个寄存器,实现remap
	        
                MOV     pc, r13                 ; PC出栈,恢复正确PC地址
                ;B      RemapJump
PtInitRemap
                DCD     RemapJump

SystemInitDataSDRAM:
	DC32            rEXTDBWTH
	DC32            rROMCON0
	DC32            rROMCON1
    	DC32            rROMCON2
	DC32            rROMCON3
	DC32            rROMCON4
	DC32            rROMCON5
	DC32            rSDRAMCON0  
	DC32            rSDRAMCON1
	DC32            rSDRAMCON2
	DC32            rSDRAMCON3
	DC32            rSREFEXTCON
;---------------------------------------------------------------
RemapJump:
; 说明:
; 1.初始化堆栈指针(下列方式用于异常的堆栈,例如FIQ,IRQ,SVC,ABT,UND,SYS),USR模式中使用SYS的堆栈,堆栈段必须在link文件中定义并申明

                                                        ; 设置IRQ堆栈指针
		mrs	r0,cpsr				; 拷贝CPSR到R0
		bic	r0,r0,#MODE_BITS		; 清模式位
		orr	r0,r0,#IRQ_MODE			; 设置IRQ模式位
		msr	cpsr_c,r0			; 改变处理器模式
		ldr	sp,=SFE(IRQ_STACK) & 0xFFFFFFF8	; SP指向IRQ_STACK尾部

                                                        ; 设置FIQ堆栈指针
                mrs	r0,cpsr				;
		bic	r0,r0,#MODE_BITS		;
		orr	r0,r0,#FIQ_MODE			;
		msr	cpsr_c,r0			;
		ldr	sp,=SFE(FIQ_STACK) & 0xFFFFFFF8	;

		                                        ; 设置ABT堆栈指针
		mrs	r0,cpsr				;
		bic	r0,r0,#MODE_BITS		;
		orr	r0,r0,#ABT_MODE			;
		msr	cpsr_c,r0			;
		ldr	sp,=SFE(ABT_STACK) & 0xFFFFFFF8	;

		                                        ; 设置UND堆栈指针
		mrs	r0,cpsr				;
		bic	r0,r0,#MODE_BITS		;
		orr	r0,r0,#UND_MODE			;
		msr	cpsr_c,r0			;
		ldr	sp,=SFE(UND_STACK) & 0xFFFFFFF8	;

                                                        ; 设置SYS堆栈指针
		bic	r0,r0,#MODE_BITS		;
		orr	r0,r0,#SVC_MODE			;
		msr	cpsr_c,r0		        ;
		ldr	sp,=SFE(SVC_STACK) & 0xFFFFFFF8	;
                
                                                        ; 拷贝中断向量表到地址0x00000000
                MOV     R8, #0
                ADR     R9, Vector_Init_Block
                LDMIA   R9!, {R0-R7}
                STMIA   R8!, {R0-R7}
                LDMIA   R9!, {R0-R7}
                STMIA   R8!, {R0-R7}
                
                B       EXCEPTION_VECTOR_TABLE_SETUP    ; 跳转至设置异常向量表标号处

Vector_Init_Block                                       ; 异常向量表
                LDR     PC, Reset_Addr
                LDR     PC, Undefined_Addr
                LDR     PC, SWI_Addr
                LDR     PC, Prefetch_Addr
                LDR     PC, Abort_Addr
                NOP
                LDR     PC, IRQ_Addr
                LDR     PC, FIQ_Addr

Reset_Addr      DCD     ?cstartup
Undefined_Addr  DCD     Undefined_Handler
SWI_Addr        DCD     SWI_Handler
Prefetch_Addr   DCD     Prefetch_Handler
Abort_Addr      DCD     Abort_Handler
                DCD     0
IRQ_Addr        DCD     IRQ_Handler
FIQ_Addr        DCD     FIQ_Handler

;---------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -