深入浅出NandFlash里的ECC校验算法原理与实现(1)

网上关于NandFlash的ECC校验文章很多,但没有一个深得我心。
(本文只分析256字节下ECC生成,其他同理)

LINUX内核中关于NandFlash的ECC校验算法,只能纠正一个bit的错误。实现过程就是在存入数据时计算ECC校验,在读出数据时再次计算ECC校验,如果两次计算结果不同,则数据在存储过程中肯定发生了变化,通常是存储某个bit的电气元件电平发生了翻转。在实际过程中,我们会通过两次计算结果对比来找到是哪一个bit发生了变化,然后更正它即可。所以重点在于怎么找到这个发生了变化的bit。

其实ECC校验我觉得主要用了两个点:异或和二分法。
异或的结果就是相同为0,不同为1,理解这个概念很重要。
然后就是二分法,逐步缩小范围

牢记以上两点即可完全理解ECC校验方式。

我们先举一个简单的例子:现在我向NandFlash里存了8个字节的数据,它们全部为0。如下图:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第1张图片
后我把数据读出来,发现其中一个bit发生了翻转。如下图:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第2张图片
我们读出来的时候并不知道存入的数据到底是多少,那ECC又是如何通过两次计算来确定是哪个bit发生了变化?
实际操作如下:
在存入数据时,计算8个字节bit0-bit3所有位的异或结果得到一个位(32个位异或的结果),再计算bit4-bit7所有位的异或结果又得到一个位(同样32个位)
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第3张图片
在读取的时候我再次计算这个两个位:

深入浅出NandFlash里的ECC校验算法原理与实现(1)_第4张图片
这样,通过两次计算结果中两个位比较,可以确定是bit0-bit3中出现了错误,还是bit4-bit7中出现了错误。这是第一次二分,用两个位筛选掉了一半的位。同理,我们可以在bit0-bit3中再次二分,可以确定是bit0-bit1中出现了错误还是bit2-bit3中出现了错误。也就是我在写入和读出时再加4个bit。如下图:
写入:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第5张图片
读出:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第6张图片
此时,我们把错误位定位到了bit2-bit3中间。再继续,我们可以再加8个位去再次二分,最后得到错误的位就在bit2这个位。这么乍一听好像没有问题,其实不然。我们在实际写入和读取时,并不知道到底是哪一位是错误的,所以我们每一列bit都要计算,而并不是先计算bit0-bit3和bit4-bit7,在判断是bit0-bit3存在错误后再计算bit0-bit1和bit2-bit3,而是我们要计算出2+4+8 = 14个部分bit的异或结果:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第7张图片
这样就出现了尴尬,如果我们是在每次判断后再计算,那我们需要计算2+2+2 = 6次,如下图:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第8张图片

但是实际情况是我们在存入数据的时候不知道哪一列会出现错误,所以我们需要一次性把14个bit都计算出来,而实际如果我们每次判断后再计算的话,第一步就可以筛选掉7个没用的bit:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第9张图片
而且细心的人会发现,我们干嘛不直接只计算最下面那一列的8个bit不就好了吗?
所以,ECC它的二分法用的很巧妙。第一次,还和之前一样我们先计算bit0-bit3和bit4-bit7的异或结果,得到两个bit可以用来第一次二分。第二次,我们不再计算bit0-bit1,bit2-bit3,bit4-bit5,bit6-bit7这四个部分,而是进一步合并,我们计算bit0-bit1与bit4-bit5所有位的异或结果,再计算bit2-bit3与bit6-bit7所有位的异或结果。如下图:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第10张图片
最后我们只用2个位就可以做第二次二分法。即无论第一次二分法得到的结果是左边四列存在错误还是右边四列存在错误,都可以通过第二次二分法得到是四列中的左边两列存在错误还是右边两列存在错误!
为什么我们多了一步异或就可以判断?比如我们上面举的例子,是bit2出现错误,那在第一次筛选后已经能确定是bit0-bit3中出现错误,那bit4-bit7肯定是没有错误的,所以即使它们与bit2-bit3异或,并不会影响最终的结果,如果bit2、bit3、bit6、bit7中出现错误,肯定是bit2和bit3中某一列出现了错误!
相同的,我们可以再用2个bit做最后一次二分,如下图:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第11张图片
在上次二分后,我们已经可以确定是哪两列出现了错误,所以最后这次二分我们可以判断具体是两列中哪一列出现了错误。就这样我们用了6个bit来确定哪一列出现了错误,同理我们也可以用这个方法确定是哪一行出现了错误,这样行列都确定了,就可以定位到哪个bit出现了错误。

同理我们扩大到256个字节计算ecc,如下图:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第12张图片
可以看到为了定位哪一列我们用了6个bit:CP0-CP5
为了定位哪一行我们用了16个bit:LP0-LP15
256行为什么是16个bit呢?
从上图可以看到对于8列的情况,CP0和CP1一共8个,即23=8;CP3和CP2一共4个,即22=4;CP4和CP5一共2个,即21=2。也就是对于8个元素来说,一共需要3行,每行占用两个位,也就是3*2=6。同理我们可以算出,对于256个元素来说,28=256,则需要8行,每行占用2个位,即8*2=16。对于拥有2n个元素的集合来说,我们需要m行,第一行的元素个数等于2n,最后一行的元素个数等于21,所以一共需要n-1+1行,每行占用两个位,一共2n个位。
总共22个bit需要占用3个byte,而多余出来两个bit,然后我们把这些bit按照固定的顺序排列:
深入浅出NandFlash里的ECC校验算法原理与实现(1)_第13张图片
所以256字节最后得到3个字节的ECC校验。

下一章介绍代码实现。

部分图片来自于:
Nand Flash 的ECC算法

下一章更精彩:
深入浅出NandFlash里的ECC校验算法原理与实现(2)

你可能感兴趣的:(ecc,nand,c语言,stm32,编程语言)