NandFlash ECC校验原理与实现
关注+星标公众号,不错过精彩内容
来源 | nhczp
编排 | strongerHuang
大家应该都在用U盘,而U盘中的存储芯片就是NandFlash,你买的64G的U盘,实际并没有64G,其中一个原因就是存在坏块。
因为工艺和其他方面的原因,不能保证NandFlash不存在坏块,因此就需要“挑选出坏块”。
本文就为大家讲述一下用于NandFlash的ECC校验原理与实现。
ECC简介
由于NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生产中及使用过程中会产生坏块。为了检测数据的可靠性,在应用NAND Flash的系统中一般都会采用一定的坏区管理策略,而管理坏区的前提是能比较可靠的进行坏区检测。
如果操作时序和电路稳定性不存在问题的话,NAND Flash出错的时候一般不会造成整个Block或是Page不能读取或是全部出错,而是整个Page(例如512Bytes)中只有一个或几个bit出错。
对数据的校验常用的有奇偶校验、CRC校验等,而在NAND Flash处理中,一般使用一种比较专用的校验——ECC。ECC能纠正单比特错误和检测双比特错误,而且计算速度很快,但对1比特以上的错误无法纠正,对2比特以上的错误不保证能检测。
ECC原理
ECC一般每256字节原始数据生成3字节ECC校验数据,这三字节共24比特分成两部分:6比特的列校验和16比特的行校验,多余的两个比特置1,如下图所示:
ECC的列校验和生成规则如下图所示:
用数学表达式表示为:
P4=D7(+)D6(+)D5(+)D4 P4`=D3(+)D2(+)D1(+)D0
P2=D7(+)D6(+)D3(+)D2 P2`=D5(+)D4(+)D1(+)D0
P1=D7(+)D5(+)D3(+)D1 P1`=D6(+)D4(+)D2(+)D0
备注:这里(+)表示“位异或”操作
ECC的行校验和生成规则如下图所示:
用数学表达式表示为:
P8 = bit7(+)bit6(+)bit5(+)bit4(+)bit3(+)bit2(+)bit1(+)bit0(+)P8
备注:这里(+)表示“位异或”操作
当往NAND Flash的page中写入数据的时候,每256字节我们生成一个ECC校验和,称之为原ECC校验和,保存到PAGE的OOB(out-of-band)数据区中。
当从NAND Flash中读取数据的时候,每256字节我们生成一个ECC校验和,称之为新ECC校验和。
校验的时候,根据上述ECC生成原理不难推断:将从OOB区中读出的原ECC校验和新ECC校验和按位异或,若结果为0,则表示不存在错(或是出现了ECC无法检测的错误);若3个字节异或结果中存在11个比特位为1,表示存在一个比特错误,且可纠正;若3个字节异或结果中只存在1个比特位为1,表示OOB区出错;其他情况均表示出现了无法纠正的错误。
ECC算法的实现
这里附上算法代码:
static const u_char nand_ecc_precalc_table[] ={0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00};// Creates non-inverted ECC code from line paritystatic void nand_trans_result(u_char reg2, u_char reg3,u_char *ecc_code){u_char a, b, i, tmp1, tmp2;/* Initialize variables */a = b = 0x80;tmp1 = tmp2 = 0;/* Calculate first ECC byte */for (i = 0; i < 4; i++){if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */tmp1 |= b;b >>= 1;if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */tmp1 |= b;b >>= 1;a >>= 1;}/* Calculate second ECC byte */b = 0x80;for (i = 0; i < 4; i++){if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */tmp2 |= b;b >>= 1;if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */tmp2 |= b;b >>= 1;a >>= 1;}/* Store two of the ECC bytes */ecc_code[0] = tmp1;ecc_code[1] = tmp2;}// Calculate 3 byte ECC code for 256 byte blockvoid nand_calculate_ecc (const u_char *dat, u_char *ecc_code){u_char idx, reg1, reg2, reg3;int j;/* Initialize variables */reg1 = reg2 = reg3 = 0;ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;/* Build up column parity */for(j = 0; j < 256; j++){/* Get CP0 - CP5 from table */idx = nand_ecc_precalc_table[dat[j]];reg1 ^= (idx & 0x3f);/* All bit XOR = 1 ? */if (idx & 0x40) {reg3 ^= (u_char) j;reg2 ^= ~((u_char) j);}}/* Create non-inverted ECC code from line parity */nand_trans_result(reg2, reg3, ecc_code);/* Calculate final ECC code */ecc_code[0] = ~ecc_code[0];ecc_code[1] = ~ecc_code[1];ecc_code[2] = ((~reg1) << 2) | 0x03;}// Detect and correct a 1 bit error for 256 byte blockint nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc){u_char a, b, c, d1, d2, d3, add, bit, i;/* Do error detection */d1 = calc_ecc[0] ^ read_ecc[0];d2 = calc_ecc[1] ^ read_ecc[1];d3 = calc_ecc[2] ^ read_ecc[2];if ((d1 | d2 | d3) == 0){/* No errors */return 0;}else{a = (d1 ^ (d1 >> 1)) & 0x55;b = (d2 ^ (d2 >> 1)) & 0x55;c = (d3 ^ (d3 >> 1)) & 0x54;/* Found and will correct single bit error in the data */if ((a == 0x55) && (b == 0x55) && (c == 0x54)){c = 0x80;add = 0;a = 0x80;for (i=0; i<4; i++){if (d1 & c)add |= a;c >>= 2;a >>= 1;}c = 0x80;for (i=0; i<4; i++){if (d2 & c)add |= a;c >>= 2;a >>= 1;}bit = 0;b = 0x04;c = 0x80;for (i=0; i<3; i++){if (d3 & c)bit |= b;c >>= 2;b >>= 1;}b = 0x01;a = dat[add];a ^= (b << bit);dat[add] = a;return 1;}else{i = 0;while (d1){if (d1 & 0x01)++i;d1 >>= 1;}while (d2){if (d2 & 0x01)++i;d2 >>= 1;}while (d3){if (d3 & 0x01)++i;d3 >>= 1;}if (i == 1){/* ECC Code Error Correction */read_ecc[0] = calc_ecc[0];read_ecc[1] = calc_ecc[1];read_ecc[2] = calc_ecc[2];return 2;}else{/* Uncorrectable Error */return -1;}}}/* Should never happen */return -1;}
参考文档:
http://blogimg.chinaunix.net/blog/upfile2/080702112233.pdf
免责声明:本文素材来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。
------------ END ------------
后台回复『软件算法』『科普知识』相关文章。
欢迎关注我的公众号,回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。
欢迎关注我的视频号:
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。
NandFlash ECC校验原理与实现相关推荐
- NAND FLASH ECC校验原理与实现
NAND FLASH ECC校验原理与实现 2008-01-25 14:57:27 转自:http://blog.csdn.net/nhczp/archive/2007/07/20/1700031.a ...
- linux ecc校验原理,Nand ECC校验和纠错原理及ECC代码分析
校验码生成算法的C语言实现 在Linux内核中ECC校验算法所在的文件为drivers/mtd/nand/nand_ecc.c,其实现有新.旧两种,在2.6.27及更早的内核中使用的程序,从2.6.2 ...
- Hadoop数据完整性与CheckSum校验原理
一.HDFS数据完整性 用户肯定都希望系统在存储和处理数据时,数据不会有任何丢失或损坏.但是,受网络不稳定.硬件损坏等因素,IO操作过程中难免会出现数据丢失或脏数据,难免会出现数据丢失或脏数据,数据传 ...
- ECC校验有什么作用
ECC校验有什么作用 先看看另外几种校验算法 奇偶校验(Parity Check) CRC校验(Cyclic Redundancy Check) MD5校验(Message-Digest Algori ...
- ECC校验——汉明码(Hamming Code)
本文参考板块与链接: https://en.wikipedia.org/wiki/Hamming_code #wiki英文版 https://zh.wikipedia.org/wiki/%E6%B1% ...
- 32位crc校验码程序_CRC码计算及校验原理的最通俗诠释
CRC校验原理 CRC校验原理看起来比较复杂,好难懂,因为大多数书上基本上是以二进制的多项式形式来说明的.其实很简单的问题,其根本思想就是先在要发送的帧后面附加一个数(这个就是用来校验的校验码,但要注 ...
- CRC校验原理及STM32 IAP在线升级程序
CRC校验原理: 什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据 ...
- 最详细易懂的CRC-16校验原理(附源程序)
from:http://www.openhw.org/chudonganjin/blog/12-08/230184_515e6.html 最详细易懂的CRC-16校验原理(附源程序) 1.循环校验码( ...
- Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle...
Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle 1. 主键1 2. uniq index2 3. ...
最新文章
- 熬10天夜,肝出了这个PDF版“软件安装手册”(附下载)
- 脚本运行java_shell脚本运行java程序jar
- html页面手机端console,GitHub - MobileHTML5/vConsole: 一个针对手机网页的前端 console 调试面板。...
- qchart 坐标轴设置_实战PyQt5: 156-QChart图表之更换图表主题
- C语言函数最多有有多少个参数,C中子函数最多有几个形参
- 5、android使用意图传递数据之全局变量传递
- 小程序json字符串取值问题,怎么取出来的是undefined,eval函数不能用?
- mySQL教程 第7章 存储过程和函数
- Matlab中的eig函数和Opecv中eigen()函数的区别
- OLAP和OLTP的区别(基础知识) 【转】
- 制作全功能系统维护U盘 PE Linux BT3 DOS
- php留言板上传图片,thinkphp3.2.3留言板带管理没有后台ajax上传图片功能
- JVC DSP调音软件
- Python编程语言入门视频教程,人生苦短,我用Python!
- S32K的flash组件使用(操作FLASH)
- 通俗易懂的Spatial Transformer Networks(STN)(一)
- js 计算个人所得税
- 支付宝sdk集成,报系统繁忙 请稍后再试(ALI64)
- [ZROJ-955]折纸 Solution
- AMD GPU驱动,ROCM,Pytorch安装教程(A卡6700xt)