NAND FLASH 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 parity static 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 = ; /* Calculate first ECC byte */ ; i < ; i++) { if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ tmp1 |= b; b >>= ; if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ tmp1 |= b; b >>= ; a >>= ; } /* Calculate second ECC byte */ b = 0x80; ; i < ; i++) { if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ tmp2 |= b; b >>= ; if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ tmp2 |= b; b >>= ; a >>= ; } /* Store two of the ECC bytes */ ecc_code[] = tmp1; ecc_code[] = tmp2; } // Calculate 3 byte ECC code for 256 byte block void nand_calculate_ecc (const u_char *dat, u_char *ecc_code) { u_char idx, reg1, reg2, reg3; int j; /* Initialize variables */ reg1 = reg2 = reg3 = ; ecc_code[] = ecc_code[] = ecc_code[] = ; /* Build up column parity */ ; j < ; 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[] = ~ecc_code[]; ecc_code[] = ~ecc_code[]; ecc_code[] = ((~reg1) << ) | 0x03; } // Detect and correct a 1 bit error for 256 byte block int 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[] ^ read_ecc[]; d2 = calc_ecc[] ^ read_ecc[]; d3 = calc_ecc[] ^ read_ecc[]; ) { /* No errors */ ; } else { a = (d1 ^ (d1 >> )) & 0x55; b = (d2 ^ (d2 >> )) & 0x55; c = (d3 ^ (d3 >> )) & 0x54; /* Found and will correct single bit error in the data */ if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { c = 0x80; add = ; a = 0x80; ; i<; i++) { if (d1 & c) add |= a; c >>= ; a >>= ; } c = 0x80; ; i<; i++) { if (d2 & c) add |= a; c >>= ; a >>= ; } bit = ; b = 0x04; c = 0x80; ; i<; i++) { if (d3 & c) bit |= b; c >>= ; b >>= ; } b = 0x01; a = dat[add]; a ^= (b << bit); dat[add] = a; ; } else { i = ; while (d1) { if (d1 & 0x01) ++i; d1 >>= ; } while (d2) { if (d2 & 0x01) ++i; d2 >>= ; } while (d3) { if (d3 & 0x01) ++i; d3 >>= ; } ) { /* ECC Code Error Correction */ read_ecc[] = calc_ecc[]; read_ecc[] = calc_ecc[]; read_ecc[] = calc_ecc[]; ; } else { /* Uncorrectable Error */ ; } } } /* Should never happen */ ; }
NAND FLASH ECC校验原理与实现的更多相关文章
- ECC校验原理以及在Nand Flash中的应用
本篇文章主要介绍ECC基本原理以及在Nand Flash中的应用,本文记录自己对ECC校验原理的理解和学习. ECC介绍 ECC,全称为Error Correcting Code, ...
- Nand Flash 控制器工作原理
对 Nand Flash 存储芯片进行操作, 必须通过 Nand Flash 控制器的专用寄存器才能完成.所以,不能对 Nand Flash 进行总线操作.而 Nand Flash 的写操作也必须块方 ...
- Nand flash 芯片工作原理
Nand flash 芯片型号为 Samsung K9F1208U0B,数据存储容量为 64MB,采用块页式存储管理.8 个 I/O 引脚充当数据.地址.命令的复用端口. 芯片内部存储布局及存储操作特 ...
- NAND FLASH 原理
NAND FLASH 原理 http://www.360doc.com/content/12/0522/21/21412_212888167.shtml 闪存保存数据的原理: 与DRAM以电容作为存储 ...
- nand flash详解及驱动编写
https://www.crifan.com/files/doc/docbook/linux_nand_driver/release/html/linux_nand_driver.html#nand_ ...
- 如何编写linux下nand flash驱动-4
2. 软件方面 如果想要在Linux下编写Nand Flash驱动,那么就先要搞清楚Linux下,关于此部分的整个框架.弄明白,系统是如何管理你的nand flash的,以及,系统都帮你做 ...
- DM365视频处理流程/DM368 NAND Flash启动揭秘
出自http://blog.csdn.net/maopig/article/details/7029930 DM365的视频处理涉及到三个相关处理器,分别是视频采集芯片.ARM处理器和视频图像协处理器 ...
- Nand flash 三种类型SLC,MLC,TLC【转】
转自:https://blog.csdn.net/fc34235/article/details/79584758 转载自:http://diy.pconline.com.cn/750/7501340 ...
- DM368 NAND Flash启动
概要: 本文介绍了DM368 NAND Flash启动的原理,并且以DM368 IPNC参考设计软件为例,介绍软件是如何配合硬件实现启动的. 芯片上电后是如何启动实现应用功能的?这是许多工程师在看到 ...
随机推荐
- iis7.0/8.0rewrite规则
首先在网站 web.config 配置文件的 configuration 节点中加入如下代码: <system.webServer> <rewrite> <rules&g ...
- css background-position (图片裁取)
语法:background-position : length || length background-position : position || position 取值:length : 百分 ...
- Activiti5 待审 待批任务 TaskQuery查询 条件查询 like查询
TaskQuery查询API 有两种方法可以从引擎中查询数据:查询API和原生查询.查询API提供了完全类型安全的API. 你可以为自己的查询条件添加很多条件 (所以条件都以AND组合)和精确的排序条 ...
- flush privileges是什么意思?
flush privileges 命令本质上的作用是将当前user和privilige表中的用户信息/权限设置从mysql库(MySQL数据库的内置库)中提取到内存里.MySQL用户数据和权限有修改后 ...
- J2SE知识点摘记(十)
1. 多线程的同步 2. 同步代码块 即程序中不能有多个线程同时在这两句代码之间执行.(必须两句代码执行完,其他线程才可以公用执行) 同步代码块定义语法如下 ... syn ...
- svn 同步到web目录
windows hook 下 @echo offSET REPOS=%1SET REV=%2SET DIR=%REPOS%/hooksSET PATH=%PATH%;SET WORKING=D:/w ...
- VC中利用多线程技术实现线程之间的通信
当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...
- 用showModalDialog写的简单弹出框传参与反参
vReturnValue = window.showModalDialog(sURL [, vArguments] [,sFeatures]) sURL -- 必选参数,类型:字符串.用来指定对话框要 ...
- Java反射-简单应用
为了程序更好的维护和扩展,在面向对象思维的世界里,首先是面向接口编程,然后我们应该把做什么和怎么做进行分离. 以下我将用一个开晚会的样例来演示一下,终于达到的效果是:工厂+反射+配置文件实现程序的灵活 ...
- 分析cocos2d-x在Android上的编译过程(1):cocco2d-x是怎样生成的Android的文件夹结构
当新建完一个cocos2d-x的项目后.进入到项目中的proj.android中,会看到例如以下的文件夹结构 在VS先把它编译,然后导入到Eclipse中,导入完后会看到多了几个文件 watermar ...