增加从Nand 启动的代码:


 FS2410板有跳线,跳线短路时从NAND启动,否则从NOR启动。根据FS2410 BIOS源码,我修改了start.s加入了可以从两种FLASH中启动u-boot的
 代码。原理在于:在重定位之前先读BWSCON寄存器,判断OM0位是0(有跳线,NAND启动)还是1(无跳线,NOR启动),采取不同的重定位代码
 分别从nand或nor中拷贝u-boot镜像到RAM中。这里面也有问题,比如从Nand启动后,nor flash的初始化代码和与它相关的命令都是不能使用的。
 这里我采用比较简单的方法,定义一个全局变量标志_boot_flash保存当前启动FLASH标志,_boot_flash=0则表明是NOR启动,否则是从NAND。
 在每个与nor flash 相关的命令执行函数一开始就判断这个变量,如果为1立即返回。flash_init()也必须放在这个if(!_boot_flash)条件中。
 这里方法比较笨,主要是为了能在跳线处于任意状态时都能启动u-boot。
 修改后的start.s如下。
 .......
  //修改1
  .globl _boot_flash 
  _boot_flash:   //定义全局标志变量,0:NOR FLASH启动,1:NAND FLASH启动。
  .word 0x00000000   
 .........

  ///修改2:

  ldr r0,=BWSCON
  ldr r0,[r0]
  ands r0,r0,#6
  beq nand_boot   //OM0=0,有跳线,从Nand启动。nand_boot在后面定义。
  ............
  
  //修改4,这里在全局变量_boot_flash中设置当前启动flash设备是NOR还是NAND
  //这里已经完成搬运到RAM的工作,即将跳转到RAM中_start_armboot函数中执行。
  adr r1,_boot_flash //取_boot_flash的当前地址,这时还在NOR FLASH或者NAND 4KB缓冲中。
  ldr r2,_TEXT_BASE
  add r1,r1,r2   //得到_boot_flash重定位后的地址,这个地址在RAM中。
  ldr r0,=BWSCON
  ldr r0,[r0]
  ands r0,r0,#6   //
  mov r2,#0x00000001
  streq r2,[r1]   //如果当前是从NAND启动,置_boot_flash为1
  
  ldr pc, _start_armboot
 
 _start_armboot: .word start_armboot
 
 ........
 
 //////// 修改4,从NAND拷贝U-boot镜像(最大128KB),这段代码由fs2410 BIOS修改得来。
 nand_boot:
   mov r5, #NFCONF
   ldr r0, =(1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7)
   str r0, [r5]
   
   bl ReadNandID
   mov r6, #0
   ldr r0, =0xec73
   cmp r5, r0
   beq x1
   ldr r0, =0xec75
   cmp r5, r0
   beq x1
   mov r6, #1
  x1: 
   bl ReadNandStatus
   
   mov r8, #0        //r8是PAGE数变量
   ldr r9, _TEXT_BASE   //r9指向u-boot在RAM中的起始地址。
  x2: 
   ands r0, r8, #0x1f
   bne  x3       //此处意思在于页数是32的整数倍的时候才进行一次坏块检查  1 block=32 pages,否则直接读取页面。
   mov  r0, r8
   bl  CheckBadBlk   //检查坏块返回值非0表明当前块不是坏块。
   cmp  r0, #0
   addne r8, r8, #32   //如果当前块坏了,跳过读取操作。 1 block=32 pages
   bne  x4
  x3: 
   mov r0, r8
   mov r1, r9
   bl ReadNandPage  //读取一页(512B)
   add r9, r9, #512
   add r8, r8, #1
  x4: 
   cmp r8, #256    //一共读取256*512=128KB。
   bcc x2
   
   mov r5, #NFCONF   //DsNandFlash
   ldr r0, [r5]
   and r0, r0, #~0x8000
   str r0, [r5]
   
   adr lr,stack_setup //注意这里直接跳转到stack_setup中执行
   mov pc,lr
  ///
  /*************************************************
  *
  *Nand basic functions:
  *************************************************
  */

  //读取Nand的ID号,返回值在r5中
  ReadNandID:
   mov     r7,#NFCONF 
   ldr      r0,[r7,#0]  //NFChipEn();
   bic      r0,r0,#0x800
   str      r0,[r7,#0] 
   mov      r0,#0x90  //WrNFCmd(RdIDCMD);
   strb     r0,[r7,#4] 
   mov      r4,#0   //WrNFAddr(0);
   strb     r4,[r7,#8] 
  y1:           //while(NFIsBusy());
   ldr      r0,[r7,#0x10] 
   tst      r0,#1
   beq      y1
   ldrb     r0,[r7,#0xc] //id  = RdNFDat()<<8;
   mov      r0,r0,lsl #8 
   ldrb     r1,[r7,#0xc] //id |= RdNFDat();
   orr      r5,r1,r0 
   ldr      r0,[r7,#0]  //NFChipDs();
   orr      r0,r0,#0x800
   str      r0,[r7,#0] 
   mov   pc,lr
  
  //读取Nand状态,返回值在r1,此处没有用到返回值。
  
  ReadNandStatus:
   mov   r7,#NFCONF
   ldr      r0,[r7,#0]   //NFChipEn();
   bic      r0,r0,#0x800
   str      r0,[r7,#0]
   mov      r0,#0x70     //WrNFCmd(QUERYCMD);
   strb     r0,[r7,#4] 
   ldrb     r1,[r7,#0xc]  //r1 = RdNFDat();
   ldr      r0,[r7,#0]   //NFChipDs();
   orr      r0,r0,#0x800
   str      r0,[r7,#0]
   mov   pc,lr
  
  //等待Nand内部操作完毕
  WaitNandBusy:
   mov      r0,#0x70  //WrNFCmd(QUERYCMD);
   mov      r1,#NFCONF
   strb     r0,[r1,#4]
  z1:                //while(!(RdNFDat()&0x40)); 
   ldrb     r0,[r1,#0xc]
   tst      r0,#0x40
   beq     z1
   mov      r0,#0   //WrNFCmd(READCMD0);
   strb     r0,[r1,#4]
   mov      pc,lr
  
  //检查坏block:
  CheckBadBlk:
   mov     r7, lr
   mov     r5, #NFCONF
   
   bic     r0, r0, #0x1f   //addr &= ~0x1f;
   ldr      r1,[r5,#0]  //NFChipEn()
   bic      r1,r1,#0x800
   str      r1,[r5,#0] 
  
   mov      r1,#0x50    //WrNFCmd(READCMD2)
   strb     r1,[r5,#4] 
   mov    r1, #6
   strb     r1,[r5,#8]  //WrNFAddr(6)
   strb     r0,[r5,#8]  //WrNFAddr(addr)
   mov      r1,r0,lsr #8 //WrNFAddr(addr>>8)
   strb     r1,[r5,#8] 
   cmp      r6,#0     //if(NandAddr)  
   movne    r0,r0,lsr #16 //WrNFAddr(addr>>16)
   strneb   r0,[r5,#8]
   
   bl  WaitNandBusy //WaitNFBusy()
  
   ldrb r0, [r5,#0xc] //RdNFDat()
   sub  r0, r0, #0xff
   
   mov      r1,#0   //WrNFCmd(READCMD0)
   strb     r1,[r5,#4] 
   
   ldr      r1,[r5,#0]  //NFChipDs()
   orr      r1,r1,#0x800
   str      r1,[r5,#0]
   
   mov  pc, r7
  
  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)
   strb     r0,[r5,#8]  //WrNFAddr(addr)
   mov      r1,r0,lsr #8 //WrNFAddr(addr>>8)
   strb     r1,[r5,#8] 
   cmp      r6,#0   //if(NandAddr)  
   movne    r0,r0,lsr #16 //WrNFAddr(addr>>16)
   strneb   r0,[r5,#8]
   
   ldr      r0,[r5,#0]  //InitEcc()
   orr      r0,r0,#0x1000
   str      r0,[r5,#0] 
   
   bl       WaitNandBusy //WaitNFBusy()
   
   mov      r0,#0   //for(i=0; i<512; i++)
  r1:
   ldrb     r1,[r5,#0xc] //buf[i] = RdNFDat()
   strb     r1,[r4,r0]
   add      r0,r0,#1
   bic      r0,r0,#0x10000
   cmp      r0,#0x200
   bcc      r1
   
   ldr      r0,[r5,#0]  //NFChipDs()
   orr      r0,r0,#0x800
   str      r0,[r5,#0]
    
   mov   pc,r7
  
关于nand命令,我尝试打开CFG_CMD_NAND选项,并定义
    #define CFG_MAX_NAND_DEVICE 1
   #define MAX_NAND_CHIPS 1
   #define CFG_NAND_BASE 0x4e000000
   添加boar_nand_init()定义(空实现)。但是连接时出现问题,原因是u-boot使用的是软浮点,而我的交叉编译arm-linux-gcc是硬件浮点。
   看过一些解决方法,比较麻烦,还没有解决这个问题,希望好心的高手指点。不过我比较纳闷,u-boot在nand部分哪里会用到浮点运算呢?
   

你可能感兴趣的:(增加从Nand 启动的代码:)