ARM2440 NBOOT的实现(2具体实现)!

nboot就是复制与跳转!

所以复制其实就是NBOOT全部了。
1.      复制就是从nandflash的烧写在block0的NBOOT.NB0复制到SDRAM指定地址。
所以首先就要知道NANDFLASH的读写方式。我们来结合代码来分析!
NANDFLASH读函数:
int NF_ReadPage(U32 block,U32 page,U8 *buffer)
{
       int i;
       unsigned int blockPage;
       U32 Mecc, Secc;
       U8 *bufPt=buffer;
                    
        blockPage=(block<<5)+page;//block*32
       NF_CE_L();
       NF_CLEAR_RB();
 
   
    NF_CMD(CMD_READ);
    NF_ADDR(0x00);
    NF_ADDR(blockPage&0xff);
    NF_ADDR((blockPage>>8)&0xff);
    NF_ADDR((blockPage>>16)&0xff);
      
     
   NF_DETECT_RB();
    for(i=0;i<512;i++)
    {
          *bufPt++=NF_RDDATA();
         
    }
   
 NF_CE_H();
   
}
 
 
 
NAND FLASH相关链接:

ARM2440ANAND FLASH 引脚:

 

从上面这个时序就可以看出,当设置地址时第八位是不需要传进去的。

官方的文档是这样的:

 

因为armflash的支持,所以相应的

Cle,we,ale,re,arm会自动设置,不用我们自己设,(轻松啊!!!)

还是因为armflash的支持,所以只要对寄存器直接操作就行,相关时序,arm会帮你完成!

#define NF_CMD(cmd)     {rNFCMD  = (cmd); }

#define NF_ADDR(addr)      {rNFADDR = (addr); } 

 

 

(1)NF_CE_L();

#define NF_nFCE_L()        {rNFCONT &= ~(1<<1); }

片选使能,使ce变为低电平。

 

(2)NF_CLEAR_RB();

#define NF_CLEAR_RB()      {rNFSTAT |= (1<<2); }

RB位写1来清除RB位使之为低电平表示现在busy,位读操作的ready作准备。

(3) NF_CMD(CMD_READ);

#define CMD_READ                    0x00 

1st half Page:进行读操作,设置A[8]

(4)NF_ADDR(0x00);

设置column设置A[0:7],从0地址开始读

(5) NF_ADDR(blockPage&0xff);

设置A[9:16],其中A[9:13]设置page地址,A[14:16]block地址

(6)NF_ADDR((blockPage>>8)&0xff);

设置A[17:24]block地址

(7)NF_ADDR((blockPage>>16)&0xff);

设置A[25]block地址

 

(8) NF_DETECT_RB();

#define NF_DETECT_RB() {while(!(rNFSTAT&(1<<2)));}

设置完地址后,根据时序图,要等待RB位由低电平变为高电平,表示数据就绪可以读取了。这也是为什么我们之前做NF_CLEAR_RB();的原因。

 

(9) for(i=0;i<512;i++)

    {

          *bufPt++=NF_RDDATA();

         

         

}

因为我们是也读取,所以制定好相应的地址,flash就会从那个地址开始读数据,直到这一页读完。因为我们是从column0地址开始读的,所以会返回一个完整的页的数据512bytes。所以这个函数的功能就是这样,把读出来的数据放到bufPt指针指向的内存中。

(10) NF_CE_H();

一切完成之后拉高CE电平,释放flash的控制。

到此,大功告成了!

 

最后就是让PC跳到bufPt指定内存执行就可以了。

所以main函数可以这样写

volatile unsigned char *downPt;

#define  OS_START_ADDR_OFFSET 0x38000//(0x02040000)         // 0x3020_0000

#define DOWNLOAD_ADDRESS (_RAM_STARTADDRESS+OS_START_ADDR_OFFSET)

void Main(void)

{

DWORD       err; //, t0 = 0;

int i;

register page, block, blockcopy_count;

MMU_EnableICache();

Uart_Init();

   Uart0_SendString("/n+-----------------------+/n");

   Uart0_SendString("WinCE NAND Boot v1.001 2009/n");

   Uart0_SendString("+-------------------------+/n");

 

    rGPCDAT &=0;

    rGPCDAT|=1;

rGPADAT|=(1<<16); //

       rGPACON=rGPACON&~(0x1<<16); // nGCS[5] -> OUTPUT

 

    downPt=(unsigned char *)DOWNLOAD_ADDRESS;

   

      

      

      

    NF_Init();

    NF_Reset();

    NF_ReadID();

 

  

 

    //err = ReadImageFromNand(dwEntry,0);

    for(block=2;block<8;block++)

    for(page=0;page<32;page++)

    {

          NF_ReadPage(block,page,(U8 *)downPt);

          downPt+=512;

    }

   //NF_ReadPage(7,8,(U8 *)downPt);

   ///*

   JumpAddr=DOWNLOAD_ADDRESS;//(unsigned char *)

  

          Launch(JumpAddr);

    

    Uart0_SendString("/nBoot ERROR:");

    Uart0_SendDWORD(err, TRUE);

    while (1);

  

 

}

 

所以当我们在转换地址时,需要把第八位单独以命令的方式设置。

#define CMD_READ                    0x00        //  Read

#define CMD_READ1                   0x01        //  Read1

NF_CMD(CMD_READ);                             //read the 1st half Page

NF_CMD(CMD_READ1);                           read the 2nd half Page

 

2.1.3

A0~A25的含义:

A[7:0]就是所谓的512BYTEScolumn address。其实column addressA[8:0],只不过A[8]必须由NF_CMD(CMD_READ);  NF_CMD(CMD_READ1);来设置,比如你要读地址为256的数据,第八位的1就要用命令来传。这样A[7:0]加上命令设置就可以完成对512bytePAGE的设置,一共9位!

A[13:9] 32page的地址刚好5位表示0~31.

A[25:14] 4096block的地址。

 

 

所以在blockPage=(block<<5)+page;中指设置了blockpage的地址,column的地址会在后面设置。

因为和column无关,所以blockpage是用来设置A[9:25]的。

block<<5:左移5位,是为了设置A[25:14]

Page是用来设置A[9:13]

 

设置好地址,我们就可以根据时序来进行操作了!

 

2.2

下面是读的时序:

 

因为arm2440a是支持NAND FLASH的所以ARM已经定义好了引脚。

Flash中的789161718是控制脚,直接和arm相连,44~4132~29是数据脚所以是8位的。

2、具体分析:

 

(1)blockPage=(block<<5)+page;

上面这句代码是对对地址进行转换,根据指定的块和页转换成相应的地址。

 

2.1.1K9F1208U0A为例:

总的来说,flash是由block组成的,blockpage组成,pagecolumn组成,column就是寻址的最小单位。

 

一共4096block

1 block=16kbyte
512Mbit=64Mbyte

1block=32page,
1page=528byte=512byte(Main Area)+16byte(Spare Area)
用户数据保存在main area中。

NAND FLASH主要以页(page)为单位进行读写,以块(block)为单位进行擦除。FLASH页的大小和块的大小因不同类型块结构而不同,块结构有两种:小块和大块,小块NAND FLASH包含32个页,每页512+16字节;大块NAND FLASH包含64页,每页2048+64字。(因为我用的是K9F1208U0A是小块,所以下面以小块为例)

 

 

 

其中,512Byte(或1024B)用于存放数据,16 Byte64B)用于存放其他信息(包括:块好坏的标记、块的逻辑地址、页内数据的ECC校验和等)。NAND设备的随机读取得效率很低,一般以页为单位进行读操作。系统在每次读一页后会计算其校验和,并和存储在页内的冗余的16B内的校验和做比较,以此来判断读出的数据是否正确。

大块和小块NAND FLASH都有与页大小相同的页寄存器,用于数据缓存。当读数据时,先从NAND FLASH内存单元把数据读到页寄存器,外部通过访问NAND FLASH I/O端口获得页寄存器中数据(地址自动累加);当写数据时,外部通过NAND FLASH I/O端口输入的数据首先缓存在页寄存器,写命令发出后才写入到内存单元中。

 

2.1.2又因为page又分为1st half Page2nd half Page。所以1st half Page得寻址范围从0~2552nd half Page寻址范围从256~511.从他们的二进制数字可以看出

1st half Page 00000000b ~11111111b

2nd half Page000000001b~111111111b

第八位是用来区分1st half Page2nd half Page的。

所以nand FLASH 就专门设置了一个设置第八位的命令,而不允许用地址的方式去设置,

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值