分类: 嵌入式
2011-05-05 13:30:26
;GET和INCLUDE功能相同
;功能:引进一个被编译过的文件。
GET option.inc
GET memcfg.inc
GET 2440addr.inc
;EQU为程序中的常量、标号等定义一个等效的字符名称
;定义SDRAM工作在Refresh模式,SDRAM有两种刷新方式:autorefresh和selfrefresh,前者是在其使用过程当中每隔一段时间发出刷新指令,SDRAM刷新一行,self refresh是在省电模式时使用
BIT_SELFREFRESH EQU (1<<22)
;系统的工作模式设定,共七种工作模式
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0
;系统的堆栈空间设定
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~
;这一段是为了统一处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译)
;arm有两种工作状态:32位,该状态执行字对准的arm指令;16位,该状态执行半字对准的Thumb指令
;不同的工作状态,编译器编译方式也不同
GBLL THUMBCODE ;定义一个全局变量
[ {CONFIG} = 16 ; CONFIG为ADS定义的内部变量
THUMBCODE SETL {TRUE} ;SETA 指令用于设置局部或全局算术变量的值,SETL 指令用于设置局部或全局逻辑变量的值,SETS 指令用于设置局部或全局字符串变量的值
CODE32 ;工作在arm状态
|
THUMBCODE SETL {FALSE} ;[ | ] 是ARM汇编控制伪指令,就是 IF ELSE ENDIF,简写成 [ | ]
]
MACRO ;宏定义
MOV_PC_LR
[ THUMBCODE
bx lr
|
mov pc,lr
]
MEND
MACRO
MOVEQ_PC_LR
[ THUMBCODE
bxeq lr
|
moveq pc,lr
]
MEND
;这段程序用于把中断服务程序的首地址装载到pc中,有人称之为“加载程序”。
;本初始化程序定义了一个数据区(在文件最后),存放相应中断服务程序的首地址。每个字空间都有一个标号,以Handle***命名。
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;用来存储PC地址
stmfd sp!,{r0} ;把将要使用的r0寄存器入栈
ldr r0,=$HandleLabel;给寄存器r0赋值
ldr r0,[r0] ;给寄存器r0赋值,将r0的地址放入r0
str r0,[sp,#4] ;将对应的中断函数首地址入栈
ldmfd sp!,{r0,pc} ;弹出工作寄存器ro和PC,也就完成了到ISR的跳转
MEND
IMPORT |Image$$RO$$Limit| ; 表示RO区末地址后面的地址,即RW数据源的起始地址
IMPORT |Image$$RW$$Base| ; RW区在RAM里的执行区起始地址,也就是编译器选项RW_Base指定的地址。
IMPORT |Image$$ZI$$Base| ; ZI区在RAM里面的起始地址
IMPORT |Image$$ZI$$Limit| ; ZI区在RAM里面的结束地址后面的一个地址
IMPORT Main
AREA Init,CODE,READONLY ;声明一个代码段
ENTRY
;下面的代码是小端和大端的转换
;条件编译,在编译成机器码前就设定好
ASSERT :DEF:ENDIAN_CHANGE ;判断ENDIAN_CHANGE是否定义
[ ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH ;如果已经定义了ENDIAN_CHANGE,判断ENTRY_BUS_WIDTH是否定义
[ ENTRY_BUS_WIDTH=32 ;判断是不是为32
b ChangeBigEndian ;DCD 0xea000007
]
[ ENTRY_BUS_WIDTH=16
andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00
]
[ ENTRY_BUS_WIDTH=8
streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
]
|
b ResetHandler
]
b HandlerUndef ;转跳到Undefined mode程序入口
b HandlerSWI ;转跳到SWI 中断程序入口
b HandlerPabort ;转跳到PAbort(指令异常)程序入口
b HandlerDabort ;转跳到DAbort(数据异常)程序入口
b . ;保留
b HandlerIRQ ;转跳到IRQ 中断程序入口
b HandlerFIQ ;转跳到FIQ 中断程序入口
;@0x20
b EnterPWDN ; Must be @0x20.
;通过设置CP15的C1的位7,设置存储格式为Bigendian,三种总线方式
ChangeBigEndian ;下面是改变大小端的程序,这里采用直接定义机器码的方式
;@0x24
[ ENTRY_BUS_WIDTH=32
DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian
DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0
]
[ ENTRY_BUS_WIDTH=16
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8
DCD 0x100f11ee
DCD 0x800080e3
DCD 0x100f01ee
]
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler
;掉电模式
;SDRAM自动刷新.
;进入PWDN