全部博文(85)
分类: 嵌入式
2009-12-08 22:48:36
;GET和INCLUDE功能相同
;功能:引进一个被编译过的文件。
GET option.inc
GET memcfg.inc
GET 244addr.inc
;EQU为程序中的常量、标号等定义一个等效的字符名称
;定义SDRAM工作在Refresh模式,SDRAM有两种刷新方式:autorefresh和selfrefresh,前者是在其使用过程当中每隔一段时间发出刷新指令,SDRAM刷新一行,self refresh是在省电模式时使用
BIT_SELFREFRESH EQU (1<<22)
;系统的工作模式设定,共七种工作模式
USERMODE EQU x1
FIQMODE EQU x11
IRQMODE EQU x12
SVCMODE EQU x13
ABORTMODE EQU x17
UNDEFMODE EQU x1b
MODEMASK EQU x1f
NOINT EQU xc
;系统的堆栈空间设定
UserStack EQU (_STACK_BASEADDRESS-x38) ;x33ff48 ~
SVCStack EQU (_STACK_BASEADDRESS-x28) ;x33ff58 ~
UndefStack EQU (_STACK_BASEADDRESS-x24) ;x33ff5c ~
AbortStack EQU (_STACK_BASEADDRESS-x2) ;x33ff6 ~
IRQStack EQU (_STACK_BASEADDRESS-x1) ;x33ff7 ~
FIQStack EQU (_STACK_BASEADDRESS-x) ;x33ff8 ~
;这一段是为了统一处理器工作状态和软件编译方式(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!,{r} ;把将要使用的r寄存器入栈
ldr r,=$HandleLabel;给寄存器r赋值
ldr r,[r] ;给寄存器r赋值,将r的地址放入r
str r,[sp,#4] ;将对应的中断函数首地址入栈
ldmfd sp!,{r,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 xea7
]
[ ENTRY_BUS_WIDTH=16
andeq r14,r7,r,lsl #2 ;DCD x7ea
]
[ ENTRY_BUS_WIDTH=8
streq r,[r,-r1,ror #1] ;DCD x7ea
]
|
b ResetHandler
]
b HandlerUndef ;转跳到Undefined mode程序入口
b HandlerSWI ;转跳到SWI 中断程序入口
b HandlerPabort ;转跳到PAbort(指令异常)程序入口
b HandlerDabort ;转跳到DAbort(数据异常)程序入口
b . ;保留
b HandlerIRQ ;转跳到IRQ 中断程序入口
b HandlerFIQ ;转跳到FIQ 中断程序入口
;@x2
b EnterPWDN ; Must be @x2.
;通过设置CP15的C1的位7,设置存储格式为Bigendian,三种总线方式
ChangeBigEndian ;下面是改变大小端的程序,这里采用直接定义机器码的方式
;@x24
[ ENTRY_BUS_WIDTH=32
DCD xee11f1 ;xee11f1 => mrc p15,,r,c1,c,
DCD xe388 ;xe388 => orr r,r,#x8; //Big-endian
DCD xee1f1 ;xee1f1 => mcr p15,,r,c1,c,
]
[ ENTRY_BUS_WIDTH=16
DCD xf1ee11
DCD x8e38
DCD xf1ee1
]
[ ENTRY_BUS_WIDTH=8
DCD x1f11ee
DCD x88e3
DCD x1f1ee
]
DCD xffffffff
DCD xffffffff
DCD xffffffff
DCD xffffffff
DCD xffffffff
b ResetHandler
;掉电模式
;SDRAM自动刷新.
;进入PWDN
EnterPWDN
mov r2,r ;r2=rCLKCON
tst r,#x8 ;测试是否是SLEEP mode?
bne ENTER_SLEEP
ENTER_STOP ;进入PWDN后如果不是sleep则进入stop
ldr r,=REFRESH
ldr r3,[r] ;r3=rREFRESH
mov r1, r3
orr r1, r1, #BIT_SELFREFRESH
str r1, [r] ;使SDRAM自动刷新
mov r1,#16 ;等待刷新,也可能不需要
subs r1,r1,#1
bne %B
ldr r,=CLKCON ;进入STOP mode.
str r2,[r]
mov r1,#32
subs r1,r1,#1
bne %B
; 进入SLEEP mode, 只有通过唤醒复位.
ldr r,=REFRESH ;退出SDRAM self refresh mode.
str r3,[r]
MOV_PC_LR
ENTER_SLEEP
;rGSTATUS3有一个返回地址
ldr r,=REFRESH
ldr r1,[r] ;r1=rREFRESH
orr r1, r1, #BIT_SELFREFRESH
str r1, [r] ;启用SDRAM self-refresh
mov r1,#16 ;等待self-refresh,也可能不需要.
subs r1,r1,#1
bne %B
ldr r1,=MISCCR
ldr r,[r1]
orr r,r,#(7<<17) ;设置SCLK=, SCLK1=, SCKE=.
str r,[r1]
ldr r,=CLKCON ;进入sleep mode
str r2,[r]
b . ;CPU不工作.
WAKEUP_SLEEP
;Release SCLKn after wake-up from the SLEEP mode.
ldr r1,=MISCCR
ldr r,[r1]
bic r,r,#(7<<17) ;SCLK:->SCLK, SCLK1:->SCLK, SCKE:->=SCKE.
str r,[r1]
;设置存储控制寄存器
ldr r,=SMRDATA
ldr r1,=BWSCON ;总线宽度和等待控制寄存器
add r2, r, #52 ;SMRDATA的结束地址
ldr r3, [r], #4
str r3, [r1], #4
cmp r2, r
bne %B
;数据在以SMRDATA为起始的存储区
mov r1,#256
subs r1,r1,#1 ;1) wait until the SelfRefresh is released.
bne %B
ldr r1,=GSTATUS3 ;GSTATUS3 has the start address just after SLEEP wake-up
ldr r,[r1]
mov pc,r
;异常中断宏调用
LTORG
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
;=======
; ENTRY
;板子上电和复位后,程序开始从位于x执行b ResetHandler,程序跳转到这里执行
;=======
ResetHandler
ldr r,=WTCON ;屏蔽看门狗
ldr r1,=x
str r1,[r]
ldr r,=INTMSK
ldr r1,=xffffffff ;屏蔽所有的中断
str r1,[r]
ldr r,=INTSUBMSK
ldr r1,=x3ff ;屏蔽所有的子中断
str r1,[r]
[ {FALSE}
; rGPFDAT = (rGPFDAT & ~(xf<<4)) | ((~data & xf)<<4);
; Led_Display
ldr r,=GPFCON
ldr r1,=x55
str r1,[r]
ldr r,=GPFDAT
ldr r1,=x1
str r1,[r]
]
;根据工作频率设置pll
ldr r,=LOCKTIME
ldr r1,=xffffff
str r1,[r]
[ PLL_ON_START
; 为244添加时钟设备.
; 设置Fclk:Hclk:Pclk
ldr r,=CLKDIVN
ldr r1,=CLKDIV_VAL ; =1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.
str r1,[r]
;Configure UPLL
ldr r,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) ;设定系统主时钟频率
str r1,[r]
nop ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
nop
nop
nop
nop
nop
nop
;配置MPLL
ldr r,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)
str r1,[r]
]
;检查启动是从休眠模式唤醒.
ldr r1,=GSTATUS2
ldr r,[r1]
tst r,#x2
;是从休眠模式唤醒,跳转到SLEEP_WAKEUP handler.
bne WAKEUP_SLEEP
EXPORT StartPointAfterSleepWakeUp
StartPointAfterSleepWakeUp
;设置存储相关寄存器的程序
;SMRDATA中涉及的值请参考memcfg.inc程序
ldr r,=SMRDATA
ldr r1,=BWSCON ;BWSCON地址
add r2, r, #52 ;SMRDATA结束地址
ldr r3, [r], #4
str r3, [r1], #4
cmp r2, r
bne %B
;初始化堆栈
bl InitStacks
; 设置缺省中断处理函数
ldr r,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ ;if there isn't 'subs pc,lr,#4' at x18, x1c
str r1,[r]
;将数据段拷贝到RAM中,将ZI数据段清零,跳入C语言的main函数执行。
;If main() is used, the variable initialization will be done in __main().
[ :LNOT:USE_MAIN
;Copy and paste RW data/zero initialized data
LDR r, =|Image$$RO$$Limit| ; Get pointer to ROM data
LDR r1, =|Image$$RW$$Base| ; and RAM copy
LDR r3, =|Image$$ZI$$Base|
;Zero init base => top of initialised data
CMP r, r1 ; Check that they are different
BEQ %F2
1
CMP r1, r3 ; Copy init data
LDRCC r2, [r], #4 ;--> LDRCC r2, [r] + ADD r, r, #4
STRCC r2, [r1], #4 ;--> STRCC r2, [r1] + ADD r1, r1, #4
BCC %B1
2
LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment
MOV r2, #
3
CMP r3, r1 ; Zero init
STRCC r2, [r3], #4
BCC %B3
]
[ :LNOT:THUMBCODE
bl Main ;Don't use main() because ......
b .
]
[ THUMBCODE ;for start-up code for Thumb mode
orr lr,pc,#1
bx lr
CODE16
bl Main ;Don't use main() because ......
b .
CODE32
]
;初始化各模式下的堆栈指针
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
mrs r,cpsr
bic r,r,#MODEMASK
orr r1,r,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack ; UndefStack=x33FF_5C
orr r1,r,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack ; AbortStack=x33FF_6
orr r1,r,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack ; IRQStack=x33FF_7
orr r1,r,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack ; FIQStack=x33FF_8
bic r,r,#MODEMASK|NOINT
orr r1,r,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack ; SVCStack=x33FF_58
;USER mode has not be initialized.
mov pc,lr
;The LR register won't be valid if the current mode is not SVC mode.
;=====================================================================
; 时钟测试
; Assemble code, because VSYNC time is very short
;=====================================================================
EXPORT CLKDIV124
EXPORT CLKDIV144
CLKDIV124
ldr r, = CLKDIVN
ldr r1, = x3 ; x3 = 1:2:4
str r1, [r]
;延时时钟稳定
nop
nop
nop
nop
nop
ldr r, = REFRESH
ldr r1, [r]
bic r1, r1, #xff
bic r1, r1, #(x7<<8)
orr r1, r1, #x47 ; REFCNT135
str r1, [r]
nop
nop
nop
nop
nop
mov pc, lr
CLKDIV144
ldr r, = CLKDIVN
ldr r1, = x4 ; x4 = 1:4:4
str r1, [r]
;延时时钟稳定
nop
nop
nop
nop
nop
ldr r, = REFRESH
ldr r1, [r]
bic r1, r1, #xff
bic r1, r1, #(x7<<8)
orr r1, r1, #x63 ; REFCNT675 - 152
str r1, [r]
nop
nop
nop
nop
nop
mov pc, lr
LTORG
SMRDATA DATA
;存储器控制寄存器的定义区
; 存储器访问周期参数
; The memory settings is safe parameters even at HCLK=75Mhz.
; SDRAM refresh period is for HCLK<=75Mhz.
DCD (+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<2)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
DCD ((B_Tacs<<13)+(B_Tcos<<11)+(B_Tacc<<8)+(B_Tcoh<<6)+(B_Tah<<4)+(B_Tacp<<2)+(B_PMC)) ;GCS
DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<2)+(Trc<<18)+(Tchr<<16)+REFCNT)
DCD x32 ;SCLK power saving mode, BANKSIZE 128M/128M
DCD x3 ;MRSR6 CL=3clk
DCD x3 ;MRSR7 CL=3clk
ALIGN
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=x33FF_FF
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;不要使用标签'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable
;@x33FF_FF2
HandleEINT # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleCAM # 4 ; Added for 244.
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
;@x33FF_FF6
HandleLCD # 4
HandleDMA # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI # 4
HandleUART1 # 4
HandleNFCON # 4 ; Added for 244.
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
;@x33FF_FFA
END