首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

嵌入式系统中的FLASH(6)

嵌入式系统中的FLASH(6)

/************************ECC校验***************************/
   ecc0=rNFECC0;                              //利用2410自带的硬件ECC校验
    ecc1=rNFECC1;
    ecc2=rNFECC2;
[q3]
     for(i=0;i
    {
        se=NF_RDDATA();                         // Read spare array
                                                    //读页内冗余的16B
    }
       NF_nFCE_H();   
    if(ecc0==se[0] && ecc1==se[1] && ecc2==se[2])   //未知使用哪一种软件规范?
    {                                               //比较数据结果是否正确
    Uart_Printf("[ECC OK:%x,%x,%x]\n",se[0],se[1],se[2]);
        return 1;
    }
    else
    {
    Uart_Printf("[ECC ERROR(RD):read:%x,%x,%x, reg:%x,%x,%x]\n",
        se[0],se[1],se[2],ecc0,ecc1,ecc2);
        return 0;
    }      
}
6)      NAND 的写操作
static int NF_WritePage(U32 block,U32 page,U8 *buffer)             //写Flash
{
    int i;
    U32 blockPage=(block
    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
    {
    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
    {
    NF_WRDATA(seBuf);                    // Write spare array(ECC and Mark)
    }
[q5]

    NF_CMD(0x10);                           // Write 2nd command
   
    for(i=0;i                     //tWB = 100ns. ////??????
    NF_WAITRB();                            //wait tPROG 200~500us;
    NF_CMD(0x70);                           // Read status command   
   
    for(i=0;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设备的TRUEFFS(True Flash File System). TRUEFFS是M-Systems公司为其产品DiskOnChip开发的文件系统,其规范并不开放。
C.       由SSFDC(Solid State Floppy Disk Card)论坛定义的支持SM卡的DOS-FAT。SM卡的DOS-FAT文件系统是由SSFDC论坛定义的,但它必须用在标准的块设备上。
对于大量用在各类存储卡上的NAND 设备而言,他们几乎都采用FAT文件系统,而在嵌入式操作系统下,还没有驱动程序可以直接让NAND设备采用文件系统,就技术角度来说,FAT文件系统不是很适合NAND设备,因为FAT文件系统的文件分区表需要不断地擦写,而NAND设备的只能有限次的擦写。
    在上面已经很明显的提到,NAND设备存在坏块,为和上层文件系统接口,NAND设备的驱动程序必须给文件系统提供一个可靠的存储空间,这就需要ECC(Error Corection Code)校验,坏块标注、地址映射等一系列的技术手段来达到可靠存储目的。
    SSFDC软件规范中,详细定义了如何利用NAND设备每个页中的冗余信息来实现上述功能。这个软件规范中,很重要的一个概念就是块的逻辑地址,它将在物理上可能不连续、不可靠的空间分配编号,为他们在逻辑空间上给系统文件提供一个连续可靠的存储空间。
表3给出了SSFDC规范中逻辑地址的标注方法。在系统初始化的时候,驱动程序先将所有的块扫描一遍,读出他们所对应的逻辑地址,并把逻辑地址和虚拟地址的映射表建好。系统运行时,驱动程序通过查询映射表,找到需要访问的逻辑地址所对应的物理地址然后进行数据读写。      
               表3 冗余字节定义
字节序号
内容
字节序号
内容
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校验,并可以编写检测坏块、标记坏块、建立物理地址和逻辑地址的映射表的程序了。
继承事业,薪火相传
返回列表