之前一直为是否自己写一个启动代码而犹豫不决。现在下决心写了,努力了三天终于将这个代码写出来了,写的过程中学到了不少ARM的汇编,硬件知识,看来还是写启动代码对学习ARM也是很有帮助的。
很感谢大大luzhengmao 对我RO,RW,ZI理解的指点,谢谢了。
使用方法:
由于我手头上没有下载NAND的工具,我是用板上带的启动代码super vivi下到vivi分区运行的,如果有NAND下载工具的朋友就更好办了,将起始地址设为0,下到NAND就行了。由于启动代码中会进行sdram的清0,nand的复制,启动过程大概要等5,6秒(不要以为死机了~~~)。
待一会儿附上程序的讲解。。。
GET 2440addr.inc
GET memery.inc
GET option.inc
BLOCK_STA EQU 0 ;//起始BLOCK
BLOCK_END EQU 13 ;//结束BLOCK
SDRAM_ADDR EQU 0x30000000 ;//SDRAM起始地址
;//*************R0,RW,ZI*******************//
IMPORT |Image$$ALL_RO$$Base|
IMPORT |Image$$ALL_RO$$Limit|
IMPORT |Image$$ALL_RW$$Base|
IMPORT |Image$$ALL_RW$$Limit|
IMPORT |Image$$ALL_ZI$$Base|
IMPORT |Image$$ALL_ZI$$Limit|
;//引入异常处理函数//
IMPORT UNDEF
IMPORT SWI
IMPORT PABORT
IMPORT DABORT
IMPORT IRQ_DEPATE
IMPORT FIQ
;//引入主函数Main()//
IMPORT Main
AREA Init,code,readonly
ENTRY_POINT
ENTRY
b RESET
b UNDEF
b SWI
b PABORT
b DABORT
b .
b IRQ_DEPATE
b FIQ
RESET
;// 关闭看门狗 //
ldr r0,=WTCON
ldr r1,=0x0
str r1,[r0]
;// 关闭中断 //
ldr r0,=INTMSK
ldr r1,=0xffffffff
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x3ff
str r1,[r0]
;// 设置LOCK TIME //
ldr r0,=LOCKTIME
ldr r1,=0xffffffff
str r1,[r0]
;// 设置 FCLK:HCLK:PCLK //
ldr r0,=CLKDIVN
ldr r1,=0x7 ;//设置分频比为1:3:6
str r1,[r0]
;// 设置 UPLL 时钟 //
ldr r0,=UPLLCON
ldr r1,=((56<<12)+(2<<4)+(2<<0)) ;//设置USB时钟为48.00MHZ
str r1,[r0]
nop
nop
nop
nop
nop
nop
nop
;// 设置 MPLL 时钟 //
ldr r0,=MPLLCON
ldr r1,=((68<<12)+(1<<4)+(1<<0)) ;//设置MPLL时钟为304.00MHZ
str r1,[r0]
;// 设置 CAMARA 分频时钟 //
ldr r0,=CAMDIVN
ldr r1,=0x0
str r1,[r0]
;// 设置内存 //
;// BANK总设置 //
ldr r0,=BWSCON
ldr r1,=SET_BWSCON
str r1,[r0]
;// 设置BANK0时钟 //
ldr r0,=BANKCON0
ldr r1,=SET_BANKCON0
str r1,[r0]
;// 设置BANK1~BANK5时钟 //
ldr r0,=BANKCON1
ldr r3,=BANKCON5
ldr r1,=SET_BANKCON
loop
cmp r0,r3
strcc r1,[r0],#4
bcc loop
;// 设置BANK6,BANK7时钟,模式 //
ldr r0,=BANKCON6
ldr r3,=BANKCON7
ldr r1,=SET_BANKCON67
str r1,[r0]
str r1,[r3]
;// 设置BANK6,BANK7刷新控制 //
ldr r0,=REFRESH
ldr r1,=SET_REFRESH
str r1,[r0]
;// 设置BANKSIZE,MRSRB6,MRSRB7 //
ldr r0,=BANKSIZE
ldr r1,=MRSRB6
ldr r2,=MRSRB7
ldr r3,=SET_BANKSIZE
ldr r4,=SET_MRSRB67
str r3,[r0]
str r4,[r1]
str r4,[r2]
;// 初始化各模式堆栈 //
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack ; UndefStack=0x33FF_5C00
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack ; AbortStack=0x33FF_6000
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack ; IRQStack=0x33FF_7000
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack ; FIQStack=0x33FF_8000
bic r0,r0,#MODEMASK|NOINT;//允许FIQ,IRQ中断
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack ; SVCStack=0x33FF_5800 //最后设置SVC模式
;//清零SDRAM
mov r0,#0
ldr r8,=0x30000000
ldr r9,=0x34000000
CLR_SDRAM
cmp r8,r9
strcc r0,[r8],#4
strcc r0,[r8],#4
strcc r0,[r8],#4
strcc r0,[r8],#4
strcc r0,[r8],#4
strcc r0,[r8],#4
strcc r0,[r8],#4
strcc r0,[r8],#4
bcc CLR_SDRAM
;// 初始化NAND //
ldr r8,=NFCONF
ldr r9,=BLOCK_STA
ldr r10,=BLOCK_END
ldr r11,=SDRAM_ADDR
ldr r0,=SET_NFCONF
ldr r1,=SET_NFCONT
str r0,[r8];//设置NFCONF
str r1,[r8,#4];//设置NFCONT
bl READ_ID
ldr r0,=0xec76
cmp r3,r0;//检测NAND ID
beq READ_BLOCK
b . ;//ID不对,停止
;// 读取NAND //
READ_BLOCK
mov r5,r9,lsl #5;//得到row首地址
mov r6,r10,lsl #5;//得到row末地址
cmp r5,r6
beq ER_MOVE
b READ_PAGE
READ_ID
ldr r0,[r8,#4]
bic r0,r0,#2
str r0,[r8,#4];//使能NAND
ldr r0,=CMD_READ_ID
strb r0,[r8,#8];//写命令
mov r0,#0
strb r0,[r8,#12];//写地址
mov r0,#40
nop
nop
nop
ldrb r1,[r8,#16]
ldrb r2,[r8,#16];//获得ID
mov r3,r1,lsl #8
orr r3,r3,r2;//Maker code. Device code.
ldr r0,[r8,#4]
orr r0,r0,#2
str r0,[r8,#4];//禁止NAND
mov pc,lr
NAND_BUSY
WAIT
ldr r0,[r8,#32];//读NFSTAT
ands r0,r0,#1;//读状态
beq WAIT
mov pc,lr
READ_PAGE
mov r7,#512
ldr r0,[r8,#4]
bic r0,r0,#2
str r0,[r8,#4];//使能NAND
ldr r0,=CMD_READ0
strb r0,[r8,#8];//写命令
mov r0,#0
strb r0,[r8,#12];//写cloumn地址
mov r0,r5
strb r0,[r8,#12];//写row地址
mov r0,r5,lsr #8
strb r0,[r8,#12];//写row地址
mov r0,r5,lsr #16
strb r0,[r8,#12];//写row地址
bl NAND_BUSY;//读状态
READ_LOOP
ldr r0,[r8,#16];//读取一个字
ldr r1,[r8,#16];//读取一个字
ldr r2,[r8,#16];//读取一个字
ldr r3,[r8,#16];//读取一个字
stmia r11!,{r0-r3};//转移四个字到SDRAM
subs r7,r7,#16
bne READ_LOOP;//读完512字节?
ldr r0,[r8,#4]
orr r0,r0,#2
str r0,[r8,#4];//禁止NAND
add r5,r5,#1;//row地址加1
cmp r5,r6
beq ER_MOVE
b READ_PAGE
ER_MOVE
ldr r3,= |Image$$ALL_RO$$Base|
ldr r4,= |Image$$ALL_RO$$Limit|
ldr r5,= |Image$$ALL_RW$$Base|
ldr r6,= |Image$$ALL_RW$$Limit|
ldr r7,= |Image$$ALL_ZI$$Base|
ldr r8,= |Image$$ALL_ZI$$Limit|
ldr r9,= ENTRY_POINT
mov r0,#0
ALL_ZI_CLR ;//清零ZI段
cmp r7,r8
strcc r0,[r7],#4
bcc ALL_ZI_CLR
;// 跳到主函数Main() //
bl Main
LTORG
END