ADS1.2环境下2416的初始化代码
CPU S3C2416
DDR K4T51163DJ
这几句话相当于调用头文件,#include<…>
GET option.s
GET memcfg.s
GET 2416addr.s
这个相当于C语言上的#define,这是切换成对应模式的数据
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 ~
GBLL THUMBCODE 定义一个全局变量,如果总线是16位宽度,就会置1,是32位就置0
[ {CONFIG} = 16 ---- 这个参数是通过软件上面设置的
THUMBCODE SETL {TRUE}
CODE32
|
THUMBCODE SETL {FALSE}
]
// MACRO … MEND 定义红变量
在这里定义 MOV_PC_LR 和 MOVEQ_PC_LR
MACRO
MOV_PC_LR
[ THUMBCODE
bx lr
|
mov pc,lr
]
MEND
MACRO
MOVEQ_PC_LR
[ THUMBCODE
bxeq lr
|
moveq pc,lr
]
MEND
定义中断函数
MACRO
$HandlerLabel HANDLER $HandleLabel
KaTeX parse error: Expected 'EOF', got '#' at position 25: …bel sub sp,sp,#̲4 ;将栈指针-4 stmf…HandleLabel;把要跳转的地址存到R0
ldr r0,[r0] ;把地址里面的数据存到R0
str r0,[sp,#4] ;把R0里的数据存到栈里面sp+4的地址上
ldmfd sp!,{r0,pc} ;还原数据到R0,并渎职数据到PC上面
MEND
//代码段,数据段,未初始化的全局变量段(BBS)
//IMPORT是汇编里面引用外部变量与函数
IMPORT |Image|RAM_EXEC|Base| ; 代码段首地址
IMPORT |Image|RO|Limit| ; 代码段的结束地址
IMPORT |Image|RAM|Base| ; 数据段首地址
IMPORT |Image|ZI|Base| ; BBS首地址
IMPORT |Image|ZI|Limit| ; BBS结束地址
(注:实际上面的|是$$的代码,排版太难看我就用|代替)
IMPORT __main
AREA Init,CODE,READONLY
IMPORT __use_no_semihosting_swi
ENTRY
ResetEntry
ASSERT :DEF:ENDIAN_CHANGE //判断是否有定义变量 **ENDIAN_CHANGE**
[ ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH //判断是否有定义变量 **ENDIAN_CHANGE**
[ ENTRY_BUS_WIDTH=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
]
ChangeBigEndian — 设置对应的总线
[ 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 ;swinv 0xffffff is similar with NOP and run well in both endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler
/
ResetHandler
ldr r0,=WTCON ;关开门狗
ldr r1,=0x0
str r1,[r0]
ldr r0,=INTMSK
ldr r1,=0xffffffff ;关中断
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x7fff ;关中断
str r1,[r0]
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
;//时钟初始化///
LDR R0, =CLOCK_BASE
LDR R1, =3600
;// MPLL锁定时间大于300us,以外部晶振12M计
STR R1, [R0, #LOCKCON0_OFS]
LDR R1, =3600
;// EPLL锁定时间大于300us
STR R1, [R0, #LOCKCON1_OFS]
LDR R1, =(0x1<<0)+(1<<2)+(1<<3)+(0x1<<4)+(0x0<<9)
STR R1, [R0, #CLKDIV0_OFS]
LDR R1, =(0x0<<4)+(0x3<<6)+(0x0<<8)+(0x0<<12)+ \
(0x0<<16)+(0x0<<24)
STR R1, [R0, #CLKDIV1_OFS]
LDR R1, =(0x0<<0)+(0x3<<6)
STR R1, [R0, #CLKDIV2_OFS]
;// 设置EPLL输出96M,
LDR R1, =(2<<0)+(1<<8)+(32<<16)+(0x0<<24)+(0x0<<25)
STR R1, [R0, #EPLLCON_OFS]
;// 外部晶振12M,设置MPLL输出为400M
LDR R1, =(1<<0)+(3<<5)+(267<<14)+(0x0<<24)+(0x0<<25)
STR R1, [R0, #MPLLCON_OFS]
LDR R1, =(1<<4)+(1<<6)
STR R1, [R0, #CLKSRC_OFS]
;// 初始化动态变量///
LDR R0, =DRAM_BASE
LDR R1, =(2<<17)+(2<<14)+(2<<11)+(2<<8)+(1<<6)+(1<<4)+(1<<1)+(1<<0)
STR R1, [R0, #BANKCFG_OFS]
;// DQS delay 3,Write buffer,Auto pre-charge,bank address 在高位
LDR R1, =(3<<28)+(1<<26)+(1<<8)+(0<<7)+
(1<<6)+(0<<5)+(1<<4)
STR R1, [R0, #BANKCON1_OFS]
LDR R1, =(5<<20)+(13<<16)+(3<<4)+(1<<2)+(1<<0)
STR R1, [R0, #BANKCON2_OFS]
;// issue a PALL(pre-charge all) command
LDR R1, [R0, #BANKCON1_OFS]
BIC R1, R1, #0x03
ORR R1, R1, #0x01
STR R1, [R0, #BANKCON1_OFS]
;// issue an EMRS(extern mode register) command to EMR(2)
LDR R1, [R0, #BANKCON3_OFS]
LDR R2, =0xFFFF0000
BIC R1, R1, R2
ORR R1, R1, #(2<<30)
STR R1, [R0, #BANKCON3_OFS]
LDR R1, [R0, #BANKCON1_OFS]
ORR R1, R1, #0x03
STR R1, [R0, #BANKCON1_OFS]
;// issue an EMRS(extern mode register) command to EMR(3)
LDR R1, [R0, #BANKCON3_OFS]
LDR R2, =0xFFFF0000
BIC R1, R1, R2
ORR R1, R1, #(3<<30)
STR R1, [R0, #BANKCON3_OFS]
LDR R1, [R0, #BANKCON1_OFS]
ORR R1, R1, #0x03
STR R1, [R0, #BANKCON1_OFS]
;// issue an EMRS to enable DLL and RDQS, nDQS, ODT disable
LDR R1, =0xFFFF0000
LDR R2, [R0, #BANKCON3_OFS]
BIC R2, R2, R1
LDR R1, =(0x1<<30)+(0<<27)+(1<<26)+
(0<<23)+(0<<16)
ORR R1, R1, R2
STR R1, [R0, #BANKCON3_OFS]
LDR R1, [R0, #BANKCON1_OFS]
ORR R1, R1, #0x03
STR R1, [R0, #BANKCON1_OFS]
;// issue a mode register set command for DLL reset
LDR R1, =0x0000FFFF
LDR R2, [R0, #BANKCON3_OFS]
BIC R2, R2, R1
LDR R1, =(1<<8)+(0<<7)+(3<<4)
ORR R1, R1, R2
STR R1, [R0, #BANKCON3_OFS]
LDR R1, [R0, #BANKCON1_OFS]
BIC R1, R1, #0x03
ORR R1, R1, #0x02
STR R1, [R0, #BANKCON1_OFS]
;// Issue 2 or more auto-refresh commands
LDR R1, =0x20
STR R1, [R0, #REFRESH_OFS]
;// Issue a MRS command with LOW to A8 to initialize device operation
LDR R1, =0x0000FFFF
LDR R2, [R0, #BANKCON3_OFS]
BIC R2, R2, R1
LDR R1, =(0<<8)+(0<<7)+(3<<4)
ORR R1, R1, R2
STR R1, [R0, #BANKCON3_OFS]
LDR R1, [R0, #BANKCON1_OFS]
BIC R1, R1, #0x03
ORR R1, R1, #0x02
STR R1, [R0, #BANKCON1_OFS]
;// Wait 200 clock, execute OCD Calibration
LDR R1, =200
0 SUBS R1, R1, #1
BNE %B0
;// Issue a EMRS1 command to over OCD Mode Calibration
LDR R1, =0xFFFF0000
LDR R2, [R0, #BANKCON3_OFS]
BIC R2, R2, R1
LDR R1, =(0x1<<30)+(0<<27)+(1<<26)+
(0<<23)+(0<<19)+(0<<22)+(0<<18)+
(0x0<<17)+(0<<16)
ORR R1, R1, R2
STR R1, [R0, #BANKCON3_OFS]
LDR R1, [R0, #BANKCON1_OFS]
ORR R1, R1, #0x03
STR R1, [R0, #BANKCON1_OFS]
;// Refresh period is 7.8us, HCLK=133M, REFCYC=1037
LDR R1, =1037
STR R1, [R0, #REFRESH_OFS]
;// issue a Normal mode
LDR R1, [R0, #BANKCON1_OFS]
BIC R1, R1, #0x03
STR R1, [R0, #BANKCON1_OFS]
//到这里就吧内存设置好了
[ {TRUE} //将BBS段清零
clean_bss
ldr r0, BaseOfZero
ldr r1, EndOfBSS
mov r3, #0
cmp r0, r1
beq on_ddr
clean_loop
str r3, [r0], #4
cmp r0, r1
bne clean_loop
]
on_ddr
bl InitStacks //初始化栈区
BL NandBoot_Init ;// Nand初始化
MOV R0,#0
LDR R1, BaseOfROM
LDR R2, =0x300000
BL NandBoot_ReadSkipBad ;// 调用Nand读函数,检查坏块
MOVS R0, R0 ;// 返回值确定函数成功还是失败
Nand_Boot_Loop
BNE Nand_Boot_Loop ;// 返回非0说明拷贝失败
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c'
str r1,[r0]
ldr pc,=__main --开始执行main
halt
b halt
//栈的初始化
InitStacks
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack ; UndefStack=0x31FF_5C00
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack ; AbortStack=0x31FF_6000
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack ; IRQStack=0x31FF_7000
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack ; FIQStack=0x31FF_8000
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack ; SVCStack=0x31FF_5800
;USER mode has not be initialized.
mov pc,lr
;The LR register won't be valid if the current mode is not SVC mode.'
LTORG
LDR R0,(某地址)的指令来解决. 这就是一般的解决之道.
呵呵, 但是我们必须再度想一下,LDR指令能寻址多远呢? LDR指令最多处理4K的偏移!!! 也是因为CPU指令集的问题. 我们的CODE SECTION如果很大, 导致0X12345678放置的地方超过了LDR指令寻址能力, 将再度出现错误! OK, 了解了这点, 我们就应该能够预防这里问题的出现. 我们需要的是让编译器尽可能近地处理这个常量. 查看一下编译器手册, 请使用LTORG巴. LTORG将立刻在当前计数器上放置所有的那些已经出现,并且需要解决的常量. 这样,我们在那些FUNC的尾部加上LTORG指令, 就可以处理调那些加载常量导致的麻烦.