📄 4510b_cstartup.s79
字号:
;---------------------------------------------------------------
; 文件说明
;
; 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 + -