nand flash读写 (三) (转)

6)      NAND 的写操作

static int NF_WritePage(U32 block,U32 page,U8 *buffer)             //Flash

{

    int i;

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

    U8 *bufPt=buffer;

 

    NF_RSTECC();                                // Initialize ECC

   

    NF_nFCE_L();

    NF_CMD(0x0[q4] );                                //?????\\Read Mode 1

    NF_CMD(0x80);                               // Write 1st command,数据输入

    NF_ADDR(0);                                 // Column 0

    NF_ADDR(blockPage&0xff);       

    NF_ADDR((blockPage>>8)&0xff);               // Block & page num.

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

 

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

    {

    NF_WRDATA(*bufPt++);                    // Write one page to NFM from buffer

    } 

   

    seBuf[0]=rNFECC0;

    seBuf[1]=rNFECC1;

    seBuf[2]=rNFECC2;

    seBuf[5]=0xff;                          // Marking good block

   

    for(i=0;i<16;i++)

    {

    NF_WRDATA(seBuf[i]);                    // Write spare array(ECC and Mark)

    } 

[q5] 

    NF_CMD(0x10);                           // Write 2nd command

   

    for(i=0;i<10;i++);                      //tWB = 100ns. ??????

 

    NF_WAITRB();                            //wait tPROG 200~500us;

 

    NF_CMD(0x70);                           // Read status command  

   

    for(i=0;i<3;i++);                       //twhr=60ns

   

    if (NF_RDDATA()&0x1)                    // Page write error

    {  

        NF_nFCE_H();

    Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",block);

    return 0;

    }

    else

    {

        NF_nFCE_H();

    #if (WRITEVERIFY==1)

    //return NF_VerifyPage(block,page,pPage);  

    #else

    return 1;

    #endif

    }

}

以下讨论一下NAND 设备上所支持的文件系统,大概现在有以下几种:

A.       JFFS2(没有坏块处理,支持大容量存储的时候需要消耗大量的内存,大量的随机访问降低了NAND设备的读取效率)和YAFFS(速度快,但不支持文件的压缩和解压)

B.       支持DiskOnChip设备的TRUEFFSTrue Flash File System. TRUEFFSM-Systems公司为其产品DiskOnChip开发的文件系统,其规范并不开放。

C.       SSFDCSolid State Floppy Disk Card)论坛定义的支持SM卡的DOS-FATSM卡的DOS-FAT文件系统是由SSFDC论坛定义的,但它必须用在标准的块设备上。

对于大量用在各类存储卡上的NAND 设备而言,他们几乎都采用FAT文件系统,而在嵌入式操作系统下,还没有驱动程序可以直接让NAND设备采用文件系统,就技术角度来说,FAT文件系统不是很适合NAND设备,因为FAT文件系统的文件分区表需要不断地擦写,而NAND设备的只能有限次的擦写。

 

    在上面已经很明显的提到,NAND设备存在坏块,为和上层文件系统接口,NAND设备的驱动程序必须给文件系统提供一个可靠的存储空间,这就需要ECCError Corection Code)校验,坏块标注、地址映射等一系列的技术手段来达到可靠存储目的。

    SSFDC软件规范中,详细定义了如何利用NAND设备每个页中的冗余信息来实现上述功能。这个软件规范中,很重要的一个概念就是块的逻辑地址,它将在物理上可能不连续、不可靠的空间分配编号,为他们在逻辑空间上给系统文件提供一个连续可靠的存储空间。

3给出了SSFDC规范中逻辑地址的标注方法。在系统初始化的时候,驱动程序先将所有的块扫描一遍,读出他们所对应的逻辑地址,并把逻辑地址和虚拟地址的映射表建好。系统运行时,驱动程序通过查询映射表,找到需要访问的逻辑地址所对应的物理地址然后进行数据读写。     

 

 

 

 

 

 

                冗余字节定义

字节序号

内容

字节序号

内容

512

用户定义数据

520

256BECC校验和

513

521

514

522

515

523

块逻辑地址

516

数据状态

524

517

块状态

525

256BECC校验和

518

块逻辑地址1

526

519

527

 

4给出了块逻辑地址的存放格式,LA表示逻辑地址,P代表偶校验位。逻辑地址只有10bit,代表只有1024bit的寻址空间。而SSFDC规范将NAND设备分成了多个zone,每个zone 内有1024块,但这物理上的1024块映射到逻辑空间只有1000块,其他的24块就作为备份使用,当有坏块存在时,就可以以备份块将其替换。

4  逻辑地址格式

D7

D6

D5

D4

D3

D2

D1

D0

 

0

0

0

1

0

LA9

LA8

LA7

518   523字节

LA6

LA5

LA4

LA3

LA2

LA1

LA0

P

519   524字节

 

有了以上的软件规范,就可以对NAND设备写出较标准的ECC校验,并可以编写检测坏块、标记坏块、建立物理地址和逻辑地址的映射表的程序了。

 

static int NF_IsBadBlock(U32 block)             //检测坏块

{

    int i;

    unsigned int blockPage;

    U8 data;

   

    blockPage=(block<<5);       // For 2'nd cycle I/O[7:5]

   

    NF_nFCE_L();   

    NF_CMD(0x50);       // Spare array read command

    NF_ADDR(517&0xf);   // Read the mark of bad block in spare array(M addr="5") [q6] 

    NF_ADDR(blockPage&0xff);    // The mark of bad block is in 0 page

    NF_ADDR((blockPage>>8)&0xff);   // For block number A[24:17]

    NF_ADDR((blockPage>>16)&0xff);  // For block number A[25]

 

   for(i=0;i<10;i++);               // wait tWB(100ns) //?????

   

    NF_WAITRB();                    // Wait tR(max 12us)

   

    data=NF_RDDATA();

 

    NF_nFCE_H();   

 

    if(data!=0xff)

    {

        Uart_Printf("[block %d has been marked as a bad block(%x)]\n",block,data);

        return 1;

    }

    else

    {

        return 0;

    }

}

 

static int NF_MarkBadBlock(U32 block)                       //标记坏块

{

    int i;

    U32 blockPage=(block<<5);

 

    seBuf[0]=0xff;

    seBuf[1]=0xff;   

    seBuf[2]=0xff;   

    seBuf[5]=0x44;                              // Bad blcok mark="0"[q7] 

   

    NF_nFCE_L();

    NF_CMD(0x50);                               //????

    NF_CMD(0x80);                               // Write 1st command

   

    NF_ADDR(0x0);                               // The mark of bad block is

    NF_ADDR(blockPage&0xff);                    // marked 5th spare array

    NF_ADDR((blockPage>>8)&0xff);               // in the 1st page.

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

   

    for(i=0;i<16;i++)

    {

    NF_WRDATA(seBuf[i]);                        // Write spare array

    }

 

    NF_CMD(0x10);                               // Write 2nd command

   

    for(i=0;i<10;i++);                          //tWB = 100ns. ///???????

 

    NF_WAITRB();                                // Wait tPROG(200~500us)

 

    NF_CMD(0x70);

   

    for(i=0;i<3;i++);                           //twhr=60ns??????

   

    if (NF_RDDATA()&0x1)                        // Spare arrray write error

    {  

        NF_nFCE_H();

        Uart_Printf("[Program error is occurred but ignored]\n");

    }

    else

    {

        NF_nFCE_H();

    }

 

    Uart_Printf("[block #%d is marked as a bad block]\n",block);

    return 1;

}

 

int search_logic_block(void)                    //建立物理地址到逻

//辑地址的映射表

{

    unsigned int block,i,blockPage,logic_no,zone,zone_i;

    U8 SE[16];

    for(i=0;i                         //初始化全局变量

        lg2ph[i]=space_block[i]=0xffff;

    logic_number=0;

    space_nr=0;

 

    NF_nFCE_L();

    zone=BLOCK_NR/1024;                             //确定NAND设备中zone

//的个数

 

    for(zone_i=0;zone_i< font="" style="word-wrap: break-word;">

    {

        //搜索每个zone 内逻辑地址和物理地址的映射关系

        for(block=0;block<1024;block++)

        {

            blockPage=((block+zone_i*1024)<<block_addrerss_shift);< font="" style="word-wrap: break-word;">

        NF_WATIRB();                                //等待R/B#信号有效

       

        NF_CMD(0x50);                               // 读取每个block内部第

//0Page内冗余的16个字节

        NF_ADDR(0);                                 // Column 0

        NF_ADDR(blockPage&0xff);       

        NF_ADDR((blockPage>>8)&0xff);               // Block & page num.

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

 

        NF_WATIRB();                                //等待R/B#信号有效

        for(i=0;i<16;i++)  se[i]=NF_RDDATA();       // Write spare array

        NF_WATIRB();

 

        if(se[5]!=0xff)[q8]                              //检测是否存在坏块

            printk("\n\rphysic block %d is bad block\n\r",block);

        else if(se[7]!=se[12][q9] )

            printk("block address1:%d!=block address2 %d\n\r",se[7],se[12]);

        else if((se[6][q10] &0xf8)==0x10)

        {

            //计算该block对应的逻辑地址

            logic_no=((0x7&se[6])<<7)+(se[7]>>1)+zone_i*1000;

            if(lg2ph[logic_no]!=0xffff)             //说明有2block拥有相

//同的逻辑地址

                printk("physical block %d and block %d have the same logic number %d\n",lg2ph[logic_no],block,logic_no);

            else lg2ph[logic_no]=block;             //将该block的逻辑地址

//关系记入lg2ph

            logic_number++;                        

        }

        else if(se[7]==0xff)                        //说明该block尚未编号

        {space_block[space_nr]=block;

        space_nr++;

        }

        }

    }

    printk("there are totally %d logic blocks\n\r",logic_number);

    NF_nFCE_H();

    return logic_number;

}

这段代码的主要作用就是产生数组lg2ph[],这个数组的含义就是“块物理地址=lg2ph[逻辑地址]”。

 

 

 


 [q1]发出擦除命令

 [q2]确认并擦除

 [q3]2410处理器的功能

 [q4]为什么要有一个读取的命令???

 [q5]读取ECC并写入16字节中

 [q6]参看表3

 [q7]标记块状态  517字节

 [q8]块状态

 [q9]块逻辑地址1和块逻辑地址2

 [q10]块逻辑地址1

转自:http://blog.chinaunix.net/uid-17066213-id-2834649.html

 

 

作者:jinweidavid

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值