gooogleman请进。NAND启动代码问题。

zoujy518   2010-2-28 20:35 楼主
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吗,事实上我们也没有把它们分开来编译呀?

这个贴是我从另一个地方转过来的,我做了一些修改,加入了我的疑问,望大家讨论研究,高手答复啊,谢谢!!!

回复评论 (10)

在官司方的BSP中BOOTLOADER是分两个部分的,一个是stepldr,一部分是EBOOT,stepldr就是前4K的内容,包含初始化的STARTUP.S和C文件,目的是初始化RAM,并把EBOOT复制到RAM中去,这部分代码4K足够,而EBOOT去做下载NK及跳操作,这部分你应该是了解的,所以STEPLDR和EBOOT是分开编译的。
点赞  2010-2-28 22:04
答1:是4K,所以就存了128K的前4K。在前4K就完成复制工作,而Steppingstone之后就还是ROM的地址,形象来说就是把Steppingstone的4K空间覆盖ROM的前4K,我觉得这样理解是最合理的,而其没有什么冲突
答2:你说的4K是内部存储器,而NAND复制到的SDRAM是外部存储器,不存在冲突啊
答3:用反汇编你就可以看到,就是ROBase的值
答4:从来就没有做到精确,也是可以用反汇编看到。只要你入口到复制操作完这段代码小于4K就可以了
点赞  2010-2-28 23:16
没用过这样的BOOTLOADER,分析应该是这样的:
NAND启动中已经将前4K的内容复制到内部RAM里边,0地址开始的地方,STARTUP.S开始的代码,在这4K代码中判断当前地址是不是0地址起始,如果是就说明程序运行在内部RAM,便把整个128K内容复制到外部RAM里边去,并从外部RAM的起始地址开始执行,这样再执行到判断语句的时候因为已经在外部RAM中了,所以不会再次执行代码的复制过程。
因为程序运行过程中各函数及变量地址用的是相对地址,所以程序在0地址开始执行或者是从0X30000000开始执行都不会有错误。
点赞  2010-3-1 09:04
走错地方了,我不是gooogleman…
点赞  2010-3-1 09:22
引用: 引用 3 楼 veabol 的回复:
没用过这样的BOOTLOADER,分析应该是这样的:
NAND启动中已经将前4K的内容复制到内部RAM里边,0地址开始的地方,STARTUP.S开始的代码,在这4K代码中判断当前地址是不是0地址起始,如果是就说明程序运行在内部RAM,便把整个128K内容复制到外部RAM里边去,并从外部RAM的起始地址开始执行,这样再执行到判断语句的时候因为已经在外部RAM中了,所以不会再次执行代码的复制过程。
因为程序运行过程中各函数及变量地址用的是相对地址,所以程序在0地址开始执行或者是从0X30000000开始执行都不会有错误。
引用: 引用 2 楼 kkjiongquan 的回复:
答1:是4K,所以就存了128K的前4K。在前4K就完成复制工作,而Steppingstone之后就还是ROM的地址,形象来说就是把Steppingstone的4K空间覆盖ROM的前4K,我觉得这样理解是最合理的,而其没有什么冲突
答2:你说的4K是内部存储器,而NAND复制到的SDRAM是外部存储器,不存在冲突啊
答3:用反汇编你就可以看到,就是ROBase的值
答4:从来就没有做到精确,也是可以用反汇编看到。只要你入口到复制操作完这段代码小于4K就可以了


我觉得这两位老兄说的很好了,昨天外出游玩了,呵呵,所以特别的累。今天来看,坛子的韦伯等牛人已经说出了真谛了。!
点赞  2010-3-1 10:31
学习,

mark。。。。。。。。。。。
点赞  2010-3-1 10:41
我终于想通了,得出一个结论。
如果指定ro-base为SDRAM的地址,比如0X30080000。并且程序大于4KB,需要拷贝到SDRAM,如果在拷贝之前用LDR PC ,=Main ,则必然要完蛋。如果用BL Main ,并且Main在小于4KB的地方,则可以调用Main,如果Main不在小于4kb的地方,则也要完蛋。
点赞  2010-3-2 00:38
补充:ro-base 与 entry 一般情况下是相等的,二般情况我还没遇到。
点赞  2010-3-2 00:40
引用: 引用 7 楼 zhang6yong 的回复:
我终于想通了,得出一个结论。
如果指定ro-base为SDRAM的地址,比如0X30080000。并且程序大于4KB,需要拷贝到SDRAM,如果在拷贝之前用LDR PC ,=Main ,则必然要完蛋。如果用BL Main ,并且Main在小于4KB的地方,则可以调用Main,如果Main不在小于4kb的地方,则也要完蛋。


哈哈哈,蛮神奇的,这个以体会bootloader蛮好用的。
点赞  2010-3-2 07:33
学习了,记得当时为了移植EBOOT到我们自己公司的硬件上,花了些时间搞这个,Nboot这部分就没区管了。
点赞  2010-3-2 10:00
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复