NAND启动代码
ldr r0, =BWSCON
ldr r0, [r0]
ands r0, r0, #6 ;OM[1:0] != 0, NOR FLash boot
bne copy_proc_beg ;don't read nand flash'
adr r0, ResetEntry ;OM[1:0] == 0, NAND FLash boot
cmp r0, #0 ;if use Multi-ice, 如果使用JTAG调试,ResetEntry会是多少?
bne copy_proc_beg ;don't read nand flash for boot'
;nop
;===========================================================
nand_boot_beg ;//从上面看出只有从NAND启动,且ResetEntry为0时才会执行这个程序段。
mov r5, #NFCONF
;set timing value
ldr r0, =(7 < <12)|(7 < <8)|(7 < <4)
str r0, [r5]
;enable control
ldr r0, =(0 < <13)|(0 < <12)|(0 < <10)|(0 < <9)|(0 < <8)|(1 < <6)|(1 < <5)|(1 < <4)|(1 < <1)|(1 < <0)
str r0, [r5, #4]
bl ReadNandID
mov r6, #0
ldr r0, =0xec73
cmp r5, r0
beq %F1
ldr r0, =0xec75
cmp r5, r0
beq %F1
mov r6, #1
1
bl ReadNandStatus
mov r8, #0
ldr r9, =ResetEntry ; 【从NANDFLASH启动时ResetEntry指向0?? 】
2
ands r0, r8, #0x1f ;
bne %F3
mov r0, r8
bl CheckBadBlk
cmp r0, #0
addne r8, r8, #32
bne %F4
3
mov r0, r8
mov r1, r9 ;//该句第一次执行时,R9指向ResetEntry,使R1指向ResetEntry;
bl ReadNandPage ;//读取一页(512 Byte);
add r9, r9, #512
add r8, r8, #1
4
cmp r8, #256 ;//判断是否已经拷贝了0~255共256个Page
bcc %B2 ;//if(R8 <256),跳转到B2继续拷贝。共拷贝数据的大小为128K;
mov r5, #NFCONF ;DsNandFlash
ldr r0, [r5]
and r0, r0, #~0x8000
str r0, [r5]
ldr pc, =copy_proc_beg
;===========================================================
copy_proc_beg ;//
adr r0, ResetEntry ;//
ldr r2, BaseOfROM ;//
cmp r0, r2
ldreq r0, TopOfROM
beq InitRam
ldr r3, TopOfROM
0 ;//如果BaseOfROM与ResetEntry不相等,将RO段搬到SDRAM中,目的地址为Image$$RO$$Base到Image$$RO$$Limit,接着继续执行InitRam。如果相等则跳过这一段代码直接到InitRam,那么BaseOfROM和ResetEntry会相等吗?
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r2, r3
bcc %B0
sub r2, r2, r3 ;//
sub r0, r0, r2 ;//
InitRam
ldr r2, BaseOfBSS ;//BaseOfBSS为RW数据的起始地址;
ldr r3, BaseOfZero ;//BaseOfZero为ZI数据的起始地址,即BaseOfBSS的结束地址;
0 ;//将RW段搬到SDRAM中,目的地址为Image$$RW$$Base到Image$$ZI$$Base
cmp r2, r3
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc %B0
mov r0,#0
ldr r3,EndOfBSS
1 ;//将SDRAM中ZI段初始化为0,地址为从Image$$ZI$$Base到Image$$ZI$$Limit
cmp r2,r3
strcc r0, [r2], #4
bcc %B1
;send reset status to main function
ldr r1, =GSTATUS2
ldr r0, [r1]
str r0, [r1] ;clear reset status
;//--------------------------------------------------------
ReadNandPage
mov r7,lr
mov r4,r1
mov r5,#NFCONF
ldr r1,[r5,#0] ;NFChipEn()
bic r1,r1,#0x800
str r1,[r5,#0]
mov r1,#0 ;WrNFCmd(READCMD0)
strb r1,[r5,#4]
strb r1,[r5,#8] ;WrNFAddr(0) ;//[地址周期1]:发送地址A[7:0];
strb r0,[r5,#8] ;WrNFAddr(addr) ;//[地址周期2]:发送地址A[16:9];
mov r1,r0,lsr #8 ;WrNFAddr(addr>>8
strb r1,[r5,#8] ;//[地址周期3]:发送地址A[24:17]
cmp r6,#0 ;//if(NandAddr)
movne r0,r0,lsr #16 ;
strneb r0,[r5,#8] ;//[地址周期4]:发送地址A[25]。
ldr r0,[r5,#0] ;InitEcc()
orr r0,r0,#0x1000
str r0,[r5,#0]
bl WaitNandBusy ;WaitNFBusy() ;//等待Nand内部操作完毕;
mov r0,#0 ;for(i=0; i <512; i++) ;//i为R0;
1
ldrb r1,[r5,#0xc] ;buf = RdNFDat() ;//[r5,#0xc]指向数据寄存器;
R1=RdNFDat();
strb r1,[r4,r0] ;//【[r4,r0] 指向的是不是还在Steppingstone内??? 】
add r0,r0,#1 ;//i++;
bic r0,r0,#0x10000
cmp r0,#0x200 ;//if(i <512)跳转到B1 ;//判断是否拷贝完一个Page,
bcc %B1
ldr r0,[r5,#0] ;//NFChipDs()
orr r0,r0,#0x800
str r0,[r5,#0]
mov pc,r7
;//------------------------------
【问题1】:start.s 其中关于nand flash启动,我的理解是:从NAND FLASH启动时,应该是前4KB映射到NGCS0,这4K代码将NAND中存放的大小为128K(这个值可以自己设定)的Boot程序拷贝到SDRAM中;但该文件提供的程序好象是先从NAND拷贝128K的代码到ResetEntry开始的地方,这时ResetEntry表示的地址应该为Steppingstone中的0地址,但是Steppingstone只有4KB的RAM区,怎么能存储128K的代码??是不是我理解有错误?
【问题2】:如果[问题1]中的ResetEntry真的为Steppingstone中的0地址,那么Boot程序拷贝nandflash的128K的数据岂不会将正在执行的4K代码重写,难道不会冲突吗?
【问题3】:如果我上述理解有误的话,那么ldr r9, =ResetEntry;该句指令使得R9指向的地址是多少?即ResetEntry的地址到底是多少?
【问题4】:S3C2440微控制器从Nand flash的引导功能:2440CPU内部有一个叫做“起步石(Steppingstone)”的 SRAM缓冲器,系统启动时,Nand flash存储器的前面4KByte字节将被自动载入到起步石中,然后系统自动执行这些载入的引导代码。引导代码执行完毕后,自动跳转到SDRAM执行(书中原文)。
因为Nand flash相对于Nor flash有价格,容量等方面的优势,现在很多系统都不装Nor flash,而是采用从Nand flash启动和引导系统。而nand bootloader的映像文件(一般为几百K)是一个整体,现在硬件系统能自动把它前4KB内容载入到“起步石”中,那么我们怎么精确地做到前4KB刚好就是引导部分?应该说引导部分就是start.s这个汇编程序吧,它恰好就是4KB吗,事实上我们也没有把它们分开来编译呀?
这个贴是我从另一个地方转过来的,我做了一些修改,加入了我的疑问,望大家讨论研究,高手答复啊,谢谢!!!
在官司方的BSP中BOOTLOADER是分两个部分的,一个是stepldr,一部分是EBOOT,stepldr就是前4K的内容,包含初始化的STARTUP.S和C文件,目的是初始化RAM,并把EBOOT复制到RAM中去,这部分代码4K足够,而EBOOT去做下载NK及跳操作,这部分你应该是了解的,所以STEPLDR和EBOOT是分开编译的。
没用过这样的BOOTLOADER,分析应该是这样的:
NAND启动中已经将前4K的内容复制到内部RAM里边,0地址开始的地方,STARTUP.S开始的代码,在这4K代码中判断当前地址是不是0地址起始,如果是就说明程序运行在内部RAM,便把整个128K内容复制到外部RAM里边去,并从外部RAM的起始地址开始执行,这样再执行到判断语句的时候因为已经在外部RAM中了,所以不会再次执行代码的复制过程。
因为程序运行过程中各函数及变量地址用的是相对地址,所以程序在0地址开始执行或者是从0X30000000开始执行都不会有错误。
我终于想通了,得出一个结论。
如果指定ro-base为SDRAM的地址,比如0X30080000。并且程序大于4KB,需要拷贝到SDRAM,如果在拷贝之前用LDR PC ,=Main ,则必然要完蛋。如果用BL Main ,并且Main在小于4KB的地方,则可以调用Main,如果Main不在小于4kb的地方,则也要完蛋。