从各种资料上看,不管是硬件ECC还是软件ECC,他们都或者是通过flash controler上的ecc模块或程序中的软件ecc模块来对每一页中data area中的数据进行ecc校验,校验值都来自于或存放到spare area中去。

不管是硬件还是软件,ecc的校验都是伴随着pgae read或page wirte来的,也就是在读写一页的过程中必须要实现的一个动作。在读写一页时,对于ecc的能力我们一般可以这样描述:该ecc模块一次可以校验aaa个字节,一个大小为bbb字节的页,则一共需要校验ccc=bbb/aaa次,每次产生的ecc校验字节数为ddd,则每页校验后在spare area区的第xxx字节位置开始,共存放ccc*ddd个字节的ecc校验值。

现在列一下我所看到的soc上nandflash控制器中所支持的硬件ecc特性:

1、hisi3518a:

(1)支持ecc校验使能和关闭,支持ecc纠错使能和关闭;

(2)支持1bit/512bytes,4bit/512bytes,24bit/1024bytes的校验能力;

(3)支持ecc校验错误完成等中断上报;

举例:1bit/512bytes

上面比如所说的预留区,我想应该是文件系统比如jffs2,ubifs等在文件系统管理上所要用到的地方。

2、dm365:

再列一下我所看到的软件ecc所支持的特性:

1、uboot-2010.6:

2、

==============================

(底下部分为转载)

在上一篇关于“支持NandFlash读写”的文章中,我们很好地完成了u-boot对NandFlash的读写,但这个读写进行的是软件ECC,即用软件编程的方法实现ECC。我们知道S3C2440的NandFlash控制器是支持硬件ECC的,因此在这里我们就来讲解如何实现硬件ECC。

NandFlash的每一页分为main区和spare区,S3C2440的NandFlash控制器支持这两个区的硬件ECC,但为了兼容u-boot-2011.06,我们只实现main区的硬件ECC。

为了实现硬件ECC,首先需要在include/configs/zhaocj2440.h文件内定义宏CONFIG_S3C2440_NAND_HWECC,这样在drivers/mtd/nand/s3c2440_nand.c文件内就定义了硬件ECC所需要的三个函数:s3c2440_nand_enable_hwecc函数、s3c2440_nand_calculate_ecc函数和s3c2440_nand_correct_data函数,而且在board_nand_init函数内,又把这三个函数分别赋给了相对应的结构体的三个成员,这样在进行NandFlash读写时,就会调用这三个函数,从而实现了硬件ECC。s3c2440_nand_enable_hwecc函数负责使能硬件ECC,s3c2440_nand_calculate_ecc函数负责计算ECC(当然这种计算是由硬件来完成的),s3c2440_nand_correct_data函数负责进行ECC的校验(同样地,这种校验也是由硬件自动完成的)。

为了理解u-boot是如何进行硬件ECC的,我们先来简要地分析一下相关的函数。NandFlash是以页为最小单位进行读写操作的,支持硬件ECC的读操作最终是由nand_read_page_hwecc函数(在drivers/mtd/nand目录下)来完成的,支持硬件ECC的写操作最终是由nand_write_page_hwecc函数(在drivers/mtd/nand目录下)来完成的。nand_read_page_hwecc函数的流程为先读取main区数据,同时通过调用s3c2440_nand_calculate_ecc函数来得到硬件ECC;再读取spare区数据;然后提取出储存在spare区内的main区ECC;最后通过调用s3c2440_nand_correct_data函数来对刚刚读取的main区数据进行校验。nand_write_page_hwecc函数的流程比较简单,它先写入main区数据,同时通过调用s3c2440_nand_calculate_ecc函数来得到硬件ECC;然后就是把硬件ECC写入到spare区内。

无论是nand_write_page_hwecc 函数,还是nand_write_page_hwecc 函数,内部都有一个这样的for循环体:

for(i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {

……  ……

}

其中三个主要变量的定义为:

eccsize= chip->ecc.size;

eccbytes= chip->ecc.bytes;

eccsteps= chip->ecc.steps;

下面我们就来介绍一下这个循环的作用:

不同的CPU的NandFlash控制器一次所能完成的硬件ECC的字节数是不一样的,例如有些CPU一次只能完成512字节的硬件ECC,但如果开发板上的NandFlash每页有2048个字节,那该怎么办呢?这时就要用到一个循环体,通过循环多次来得到一页的硬件ECC。例如上面这种情况,就要循环4次(2048÷512=4),才能得到这个页内数据完整的硬件ECC。另外每一次硬件ECC,不同的CPU所生成的ECC字节数也是不同的,有的是3个字节,有的是4个字节。

那么,上面那三个变量的含义就分别为:

ecc.size:每一次硬件ECC所检验的字节个数

ecc.bytes:每一次硬件ECC所生成的字节个数

ecc.steps:每一页需要进行硬件ECC的次数

对于S3C2440来说,一次硬件ECC可以检验2048个字节,并且生成4个字节的ECC,因此ecc.size应该为2048,ecc.bytes应该为4。而ecc.steps是通过计算得到的,即系统上电后能够获知NandFlash的每页的大小,用这个值除以ecc.size就等于ecc.steps。所以对于这三个参数,只需事先定义好前两个参数即可。而这两个参数是在drivers/mtd/nand/s3c2440_nand.c文件中的board_nand_init函数内被定义赋值的,即:

nand->ecc.size = 2048;

nand->ecc.bytes = 4;

u-boot-2011.06对S3C2440的NandFlash控制器的寄存器定义得不完整,而且有错误,因此我们还需要对此进行修改。删除arch/arm/include/asm/arch-s3c24x0/s3c24x0.h文件内的第167行至第178行内容,添加进下面的内容:

struct s3c2440_nand {

u32  nfconf;

u32  nfcont;

u32  nfcmd;

u32  nfaddr;

u32  nfdata;

u32  nfmeccd0;

u32  nfmeccd1;

u32  nfseccd;

u32  nfstat;

u32  nfestat0;

u32  nfestat1;

u32  nfmecc0;

u32  nfmecc1;

u32  nfsecc;

u32  nfsblk;

u32  nfeblk;

};

最后,我们对s3c2440_nand_enable_hwecc函数、s3c2440_nand_calculate_ecc函数和s3c2440_nand_correct_data函数进行修改。

void s3c2440_nand_enable_hwecc(structmtd_info *mtd, int mode)

{

struct  s3c2440_nand *nand = s3c2440_get_base_nand();

debugX(1,"s3c2440_nand_enable_hwecc(%p,%d)\n", mtd, mode);

writel(readl(&nand->nfcont)| S3C2440_NFCONT_INITECC& ~S3C2440_NFCONT_MECCL,&nand->nfcont);

}

该函数的任务就是初始化ECC(即复位ECC),并解锁main区ECC。

static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, constu_char *dat,

u_char *ecc_code)

{

struct  s3c2440_nand *nand = s3c2440_get_base_nand();

u32  mecc0;

writel(readl(&nand->nfcont)| S3C2440_NFCONT_MECCL,&nand->nfcont);

mecc0= readl(&nand->nfmecc0);

ecc_code[0]= mecc0 & 0xff;

ecc_code[1] = (mecc0 >> 8) &0xff;

ecc_code[2] = (mecc0 >> 16) &0xff;

ecc_code[3] =(mecc0 >> 24) & 0xff;

debugX(1,"s3c2440_nand_calculate_hwecc(%p,):0x%02x 0x%02x 0x%02x 0x%02x\n",

mtd , ecc_code[0], ecc_code[1], ecc_code[2], ecc_code[3]);

return 0;

}

该函数首先锁定main区ECC,然后读取寄存器NFMECC0,该寄存器存放着由硬件生成的main区ECC,最后把4个1字节的ECC存放到ecc_code数组内。

static int s3c2440_nand_correct_data(struct mtd_info *mtd, u_char*dat,

u_char *read_ecc, u_char *calc_ecc)

{

struct  s3c2440_nand *nand = s3c2440_get_base_nand();

u32  meccdata0, meccdata1, estat0, err_byte_addr;

int  ret = -1;

u8  repaired;

meccdata0= (read_ecc[1] << 16) | read_ecc[0];

meccdata1= (read_ecc[3] << 16) | read_ecc[2];

writel(meccdata0,&nand->nfmeccd0);

writel(meccdata1,&nand->nfmeccd1);

/*Read ecc status */

estat0= readl(&nand->nfestat0);

switch(estat0 & 0x3) {

case  0: /* No error */

ret= 0;

break;

case  1:

/*

* 1 bit error (Correctable)

* (nfestat0 >> 7) & 0x7ff    :error byte number

* (nfestat0 >> 4) & 0x7      :error bit number

*/

err_byte_addr= (estat0 >> 7) & 0x7ff;

repaired= dat[err_byte_addr] ^ (1 << ((estat0 >> 4) & 0x7));

printf("S3C NAND: 1 bit error detected at byte%ld. "

"Correcting from 0x%02x to0x%02x...OK\n",

err_byte_addr, dat[err_byte_addr],repaired);

dat[err_byte_addr]= repaired;

ret= 1;

break;

case  2: /* Multiple error */

case  3: /* ECC area error */

printf("S3C NAND: ECC uncorrectable errordetected. "

"Not correctable.\n");

ret= -1;

break;

}

return   ret;

}

该函数首先把read_ecc数组内的ECC存入寄存器NFMECCD0 和寄存器 NFMECCD1中,这样系统就会自动校验数据,并把状态放入寄存器NFESTAT0中,然后读取该寄存器的后4位,当为0时表示校验正确;当为1时表示发生了1位错误(该类错误可以校正),我们把它校正过来;当为2和3时表示发生其他类型的错误,这类错误是无法校正的。

通过以上内容的修改,我们就实现了NandFlash的硬件ECC。

ECC足以保证所读数据的正确性,并在有些情况下还可以修正错误,但它不能保证所写数据的正确性。为了保证所写数据的正确性,u-boot还可以通过在include/configs/zhaocj2440.h文件内定义宏CONFIG_MTD_NAND_VERIFY_WRITE来实现把所写的数据再读取一遍,然后与被写入的数据之间进行比较来判断所写数据的正确性,这一过程是在drivers/mtd/nand/nand_base.c文件的nand_write_page函数内调用实现

硬件ecc和软件ecc相关推荐

  1. [Nand Flash]软件ECC

    /* --------------------------------------------------------------- 作    者:温子祺 联系方式:wenziqi@hotmail.c ...

  2. 单片机加密の硬件加密和软件加密

    单片机的加密和解密是指在单片机的应用程序中对某些数据进行加密和解密操作,以保护数据的安全性和隐私性.单片机的加密和解密方式主要有硬件加密和软件加密两种方法. 一.硬件加密: 硬件加密是通过硬件电路实现 ...

  3. 硬件 RAID 与软件 RAID 之间的区别

    独立磁盘冗余阵列 (RAID) 是一种将多个物理驱动器组合到一个单元中的虚拟磁盘技术.这是一种通过使用多个驱动器来提高存储介质的性能和可靠性的方法.驱动器配置为在磁盘之间划分数据以分配负载,或者复制数 ...

  4. 硬件专业化和软件映射的敏捷框架

    硬件专业化和软件映射的敏捷框架 概述 随着摩尔定律接近尾声,设计专用硬件及将应用程序映射到专用硬件的软件,都是很有前途的解决方案.硬件设计决定了峰值性能,软件也很重要,决定了实际性能.硬件/软件(HW ...

  5. 《 嵌入式系统设计与实践》一一3.6 测试硬件(和软件)

    3.6 测试硬件(和软件) 虽然我强烈建议准备好工具箱.数字万用表和示波器,但是,如果大家没有准备好独自拥有这些,那么将这些留给硬件工程师也在情理之中.作为一个软件工程师,更重要的是将用于测试硬件的软 ...

  6. 硬件磁盘阵列还是软件磁盘阵列

    市面上有所谓硬件磁盘阵列与软件磁盘阵列之分,因为软件磁盘阵列是使用一块SCSI 卡与磁盘连接,一般用户误以为是硬件磁盘阵列.以上所述主要是针对硬件磁盘阵列, 其与软件磁盘阵列有几个最大的区别: 一个完 ...

  7. LB服务:硬件如何被软件取代(上)

    大业务上云,难免要用到LB.可是,您是否了解LB的来龙去脉?本文浅谈一下LB,从硬件走到软件,他们经历了什么转变. 几年前,刚接触网络的时候,就听过一个称呼:四层交换. 四层交换,顾名思义,就是基于传 ...

  8. 认识队列技术中的硬件队列和软件队列及如何改变硬件队列长度

    认识队列技术中的硬件队列和软件队列及如何改变硬件队列长度 队列技术      路由器或者交换机的数据发送,必须依赖于队列(queue),这是一个什么样的概念呢?首先从生活中打个比喻:有很多人在公交车站 ...

  9. 硬件防火墙和软件防火墙的比较

    硬件防火墙和软件防火墙是两种不同的网络安全设备,它们的主要区别在于工作原理和使用场景.本文将分别介绍硬件防火墙和软件防火墙的特点.优缺点以及如何进行配置. 一.硬件防火墙的特点和优缺点 硬件防火墙是一 ...

最新文章

  1. NCHW与NHWC格式
  2. 2018年全球AI突破性技术TOP10
  3. mysql客户端( Navicat)远程登录操作问题 1142-create command denied to user×××
  4. python all()函数 (判断可迭代对象中是否全为True)
  5. 用两个文件a.txt;b.txt.使用linux命令,复制,a.txt文档倒数第十行的记录to b.txt文档
  6. 张俊红21岁的年度总结
  7. 国外网站设计欣赏:30个优秀的国外咖啡网站设计
  8. android刷新时的圆形动画_【Android】圆形揭露动画
  9. cocos2d-x的Android工程开启c++0x特性
  10. Mysql的去重distinct
  11. Java基础编程题——水仙花数
  12. Spark学习:Win10中编译Spark源码
  13. linux ls按着文件数字大小排列
  14. unity-编辑器协程
  15. verilog-pcie
  16. 智能物联网网关有哪些必备功能
  17. 量化投资:用Python实现金融数据的获取与整理
  18. 守恒定律、连续性方程和玻印亭矢量
  19. 直播软件与微信小程序的测试点
  20. 谷歌浏览器出现应用程序无法启动,因为应用程序的并行配置不正确....(亲测完美解决)

热门文章

  1. android百度人脸采集免费,Android 调用百度人脸采集
  2. oracle量子,量子计算
  3. 最小二乘,最大似然,最大后验,查准率与查全率
  4. 机器学习中的数学——距离定义(九):测地距离(Geodesic Distance)
  5. 大二物竞金牌转北大计算机,靠竞赛进入清北的学生,都能选哪些专业?| 2019竞赛优惠专业分析...
  6. 隐马尔科夫(HMM)的Matlab实现
  7. 修改gif图片文件大小
  8. 智原深耕网通应用 布建完整ASIC解决方案
  9. C语言入门----输出语句
  10. 自制的MATLAB拼图游戏GUI界面版详解(上篇)