纠错码是一种用在不可靠的或者噪音比较大的通信信道中用来控制数据传输错误的技术。这种技术的核心思想是数据的发送方对将要发送的数据进行编码,使得编码之后的数据不仅包含了原有要发送的数据,还包含了一部分额外的冗余数据,接收方可以利用这部分冗余数据检测接收到的数据是否发生了错误,如果发生了错误,还可以利用这部分冗余数据来对部分发生错误的数据进行校正。这样就有可能避免数据的重传,这对于重传代价比较大的应用领域是非常友好的。通常情况下编码过程中引入的冗余信息越多,可以监测和校正的数据位越多,但是同时也意味着传输的有效数据位的比例越低,这个需要根据实际情况做出选择。
主要有两种类型的纠错码,以下只是基本的介绍,因为编码这玩意本身就很复杂,我也不懂,详细的请查看维基百科:
有关纠错码分类的一个简图如图1所示,图1来自于美光科技的一个文档,如图2所示。每一种纠错码也分很多种,汉明码(HammingcodeHamming\quad codeHammingcode)属于BlockcodesBlock\quad codesBlockcodes的一种。从图1也可以看出,汉明码也是线性码(linear Code)。那什么是线性码,线性码的特性有有效的线性码的码字的线性组合可以生成另外的有效的线性码码字,关于什么是码字,后面会有介绍。至于什么是线性组合,我大概百度了一下,好像是说是加法和数乘,当然这里如果是对二进制数进行操作的话,最后还要对结果进行对2的取模操作。在所有的线性码中,最后编码得到的码字的长度都大于原始要发送的数据的长度。
用数学术语来说的话,汉明码是一类binarylinearcodebinary\quad linear\quad codebinarylinearcode。对于每一个整数r,r≥2,r,r\geq2,r,r≥2,假设加到要传输的数据的冗余的大小为rrr个比特位,则要传输的数据的实际的比特个数为2r−r−12^r-r-12r−r−1,因此最后实际要传输的数据额比特位的个数为2r−12^r-12r−1。最后实际要传输的2r−12^r-12r−1个比特数据称为原始要传输的数据编码之后的码字。比如当r=3r=3r=3的时候,要传输的数据的冗余的大小为3个比特位,要传输的实际数据的比特个数为4,要传输的码字数据比特位的个数为7。编码方式根据最后生成的码字的形式可以分为systematicsystematicsystematic和non−systematicnon-systematicnon−systematic,对于systematicsystematicsystematic的码字,码字中保留有原有的实际要发送的数据,也就是原始实际要发送的数据和冗余数据在码字中有明确的分界线,没有交错,non−systematicnon-systematicnon−systematic的码字则不是,如图3所示。图3来自于这里。
对于(2r−12^r-12r−1,2r−r−12^r-r-12r−r−1,rrr)=(7,4,3)的汉明码,原始要发送的一个字符由四个比特位组成,那么一共有16种可能的字符,经过编码之后满足要求7个比特的码字也只有16种,尽管7个比特位一共有128种不同的组合,那么剩下的一共112种就是错误的码字,如果在接收方接收到了这些码字,那说明在传输过程中出现了错误。对于汉明码,所有满足要求的码字之间的最小汉明距离dmind_{min}dmin为3,汉明距离是两个码字的二进制表示的情景下,对应的位置上比特位的值不同的比特位的个数。汉明距离可以用来判断一种纠错码的错误检测和纠错能力,在知道最小汉明距离dmind_{min}dmin之后,则可以纠正的错误的最大比特数为dmin−12\frac {{d_{min}-1}}22dmin−1,可以检测的错误的最大比特数为dmin−1d_{min}-1dmin−1。其实从这里可以看出来汉明码的检测和纠错能力是比较差的,因此汉明码比较适用于错误率比较低的情景,像计算机的存储器就是这样,因此在计算机的存储器中汉明纠错码比较常见。也常用在singlelevelcellNANDflashsingle\quad level\quad cell\quad NAND\quad flashsinglelevelcellNANDflash存储器。前面说过汉明码可以最多检测到2比特的错误,但是无法区分到底是1比特错误还是2比特错误,如果将2比特错误按照1比特错误来纠正的话会造成错误的结果,为了能够区分到底是1比特错误还是2比特错误,目前又引进了一种改进的汉明码,就是在已有汉明码的基础上再多加一个冗余位,使得汉明距离达到4.这样就可以区分到底是1比特错误还是2比特错误。汉明码的发明者是Richard Hamming,他最开始的发明好像是r=3r=3r=3的汉明码,其它的好像是后人的扩充。
下面来讲一下可以校正1比特错误的汉明码的通用生成算法,首先我们看一下图4。这里图4中的第二行是经过汉明码编码之后的码字,其中di(i≥1)d_i(i\geq1)di(i≥1)表示原始要发送的原始数据位,pi(i≥1)p_i(i\geq1)pi(i≥1)表示添加的冗余数据位,这里的冗余数据位的生成其实就是基于奇偶校验位的,只不过这里采用的是偶校验(也就是要使得被校验的二进制数据位和校验位中所有为1的比特位的个数为偶数)。图4中的第1行是原始数据位经过汉明码编码之后的码字的每一个比特位的索引,从1开始。从图中可以看到,冗余数据位的存放位置为码字中索引为202^020,212^121,222^222,…,2n2^n2n,…,的比特位位置,然后其它的比特位位置就是原始要发送的数据位的位置。现在编码之后的码字中的原始数据位以及其对应的存放位置已经确定了,冗余数据位的存放位置也已经确定,现在的问题是这些冗余数据比特位的值怎么确定。其实这里图4已经比较直观的表示出来了,图4中的ParityBitCoverageParity\quad Bit\quad CoverageParityBitCoverage的区域的每一行(pn(n≥1)p_n(n\geq 1)pn(n≥1))说明了每一个冗余数据位(pn(n≥1)p_n(n\geq 1)pn(n≥1))的计算方法,每一行的红色方格表示这一行要计算的是哪一个冗余数据位,这一行的绿色方格表示这一行要计算冗余数据位是基于那些原始要发送的数据位的。比如ParityBitCoverageParity\quad Bit\quad CoverageParityBitCoverage区域的p1p_1p1行(r=3r=3r=3)表示冗余数据位p1p_1p1位的值为原始要发送的数据位D1D_1D1,D2D_2D2和D4D_4D4的奇偶校验位(这里是偶校验)。下面我们直接给出计算公式:
汉明码的编码,解码,探测以及纠错都是可以用线性代数的操作来进行的,也就是矩阵的操作,所以要详细了解汉明码的话还需要一定的数学知识背景,我现在是没有时间去详细了解了只能根据网络上特别是维基百科上面的介绍来做一个简单的说明。下面我们举一个简单的例子来说明一下,假设现在r=3r=3r=3,也就是要加入的冗余比特位的个数为3,则原始要发送的数据比特位的个数为4,最后编码之后的码字的长度为7个比特位。在汉明码的编码过程中需要用到generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G,下面是r=3r=3r=3的时候的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G,它是一个4×74\times 74×7的矩阵。
G=[1110000100110001010101101001]G=\begin{bmatrix} 1 & 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 & 1 & 0 & 0 \\ 0 & 1 & 0 & 1 & 0 & 1 & 0 \\ 1 & 1 & 0 & 1 & 0 & 0 & 1 \end{bmatrix}G=1101101110000111010000100001
假设现在有一个需要编码的二进制数据流d=[d1,d2,d3,d4]d=[d_1,d_2,d_3,d_4]d=[d1,d2,d3,d4],则编码过程如下:
d∗G=[d1d2d3d4][1110000100110001010101101001]=[d1+d2+d4d1+d3+d4d1d2+d3+d4d2d3d4]d*G=\begin{bmatrix} d_1 & d_2 & d_3 & d_4 \end{bmatrix}\begin{bmatrix} 1 & 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 & 1 & 0 & 0 \\ 0 & 1 & 0 & 1 & 0 & 1 & 0 \\ 1 & 1 & 0 & 1 & 0 & 0 & 1 \end{bmatrix}=\begin{bmatrix} d_1 + d_2+d_4 \\ d_1 + d_3+d_4 \\ d_1 \\ d_2 + d_3+d_4 \\ d_2 \\ d_3 \\ d_4 \end{bmatrix}d∗G=[d1d2d3d4]1101101110000111010000100001=d1+d2+d4d1+d3+d4d1d2+d3+d4d2d3d4
我们将上面通过矩阵运算得到的编码之后的码字和前面介绍的通用算法对比的话就可以知道这里通过矩阵的形式得到的编码的码值是满足上面描述的通用算法的。通过图4,其实generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的构建也是比较简单的,generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的每一列对应于编码之后的码字的每一个码字位。如果当前列对应于码字中的冗余数据位,则generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的该列确定原始要编码的数据流的那些数据位用来生成当前码字位的值(偶校验运算)。比如generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的第一列对应于编码之后的码字的第一位,也就是冗余数据位p1p_1p1,如果r=3r=3r=3的话,这里generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的第一列为[1,1,0,1][1,1,0,1][1,1,0,1],则表示原始要发送的数据比特流的第1,2,4个比特位用来生成码字的第一个比特位。如果当前列对应于码字中的原始要发送的数据位,则generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的该列确定原始要发送的比特数据流的哪一位作为当前的码字的该位。比如generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的第3列对应于编码之后的码字的第3位,也就是原始要发送的数据位D1D_1D1,如果r=3r=3r=3的话,这里generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G的第3列为[1,0,0,0][1,0,0,0][1,0,0,0],则表示原始要发送的数据比特流的第1个比特位D1D_1D1用来为当前的码字的该位
在汉明码的探测和纠错过程中需要用到paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H,下面是r=3r=3r=3的时候的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H,它是一个3×73\times 73×7的矩阵。这个矩阵也是很容易得到的,我们看一下图4中的BitPositionBit\quad PositionBitPosition的值为1到7的所有列中ParityBitCoverageParity\quad Bit\quad CoverageParityBitCoverage的区域(p1−>p3p_1->p_3p1−>p3),这也是一个3×73\times 73×7的区域,这个区域的每一个方块和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的每一个值一 一对应,绿色的方块对应paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H中的值为1,红色的方块也对应paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H中的值为1,只不过3×73\times 73×7的区域
的每一行的红色方格表示当前是哪一个冗余数据位,绿色区域表示当前的冗余数据位基于计算所需要的原始数据位。这个白色的方块对应paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H中的值为0。
H=[101010101100110001111]H=\begin{bmatrix} 1 & 0 & 1 & 0 &1 & 0 & 1 \\ 0 & 1 & 1 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 \end{bmatrix}H=100010110001101011111
当我们收到一个经过generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G编码之后的码字ccc之后,我们可以通过如下操作H∗cH*cH∗c来判断收到的码字是否有出现错误。
c=[d1+d2+d4d1+d3+d4d1d2+d3+d4d2d3d4]=[p1p2d1p3d2d3d4]c=\begin{bmatrix} d_1 + d_2+d_4 \\ d_1 + d_3+d_4 \\ d_1 \\ d_2 + d_3+d_4 \\ d_2 \\ d_3 \\ d_4 \end{bmatrix}=\begin{bmatrix} p_1 \\ p_2 \\ d_1 \\ p_3 \\ d_2 \\ d_3 \\ d_4 \end{bmatrix}c=d1+d2+d4d1+d3+d4d1d2+d3+d4d2d3d4=p1p2d1p3d2d3d4
H∗c=[101010101100110001111][p1p2d1p3d2d3d4]=[p1+d1+d2+d4p2+d1+d3+d4p3+d2+d3+d4]H*c=\begin{bmatrix} 1 & 0 & 1 & 0 &1 & 0 & 1 \\ 0 & 1 & 1 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 \end{bmatrix}\begin{bmatrix} p_1 \\ p_2 \\ d_1 \\ p_3 \\ d_2 \\ d_3 \\ d_4 \end{bmatrix}=\begin{bmatrix} p_1+d_1 + d_2+d_4 \\ p_2+d_1 + d_3+d_4 \\ p_3+d_2 + d_3+d_4 \end{bmatrix}H∗c=100010110001101011111p1p2d1p3d2d3d4=p1+d1+d2+d4p2+d1+d3+d4p3+d2+d3+d4
假设码字在传输过程中没有出现错误的话,因为p1p_1p1是基于d1d_1d1 ,d2d_2d2和d4d_4d4计算得到的奇偶校验位,p2p_2p2是基于d1d_1d1 ,d3d_3d3和d4d_4d4计算得到的奇偶校验位,p3p_3p3是基于d2d_2d2 ,d3d_3d3和d4d_4d4计算得到的奇偶校验位,则p1+d1+d2+d4p_1+d_1 + d_2+d_4p1+d1+d2+d4,p2+d1+d3+d4p_2+d_1 + d_3+d_4p2+d1+d3+d4和p3+d2+d3+d4p_3+d_2 + d_3+d_4p3+d2+d3+d4运算得到的值均为0(需要对计算结果进行对2取模运算),因此最后得到的是一个3×13\times13×1的0向量。从这里我们也可以看到,如果是发送的某一个数据位d1d_1d1,d2d_2d2或d3d_3d3发生翻转的话,通过接收到的码字重新计算冗余数据位会得到两个冗余数据位翻转,如果是发送的数据位d4d_4d4发生翻转的话,通过接收到的码字重新计算冗余数据位会得到三个冗余数据位翻转,如果是发送的某一个冗余位p1p_1p1,p2p_2p2或p3p_3p3发生翻转的话,通过接收到的码字重新计算冗余数据位会得到1个冗余数据位翻转
假设码字在传输过程中由某一个比特位发生了错误,即比特位的值翻转了,因此我们可以假设这个出现了一个比特翻转的码字为c′=c+eic^{'}=c+e_ic′=c+ei,这里ccc为原始没有发生比特位翻转的码字,这里eie_iei为何ccc大小相同的单位向量,eie_iei除了第i个位置上的值为1,其它位置上的值为0,也就是相当于原始码字中第iii个位置上发生了比特位翻转。这时我们将c′c^{'}c′和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H相乘之后可以得到H∗c′=H∗c+H∗ei=H∗eiH*c^{'}=H*c+H*e_i=H*e_iH∗c′=H∗c+H∗ei=H∗ei,这时我们可以发现如果码字在传输过程中由某一个比特位(第iii个)发生了错误,接收到的码字c′c^{'}c′和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H相乘之后的结果为paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的第iii行。
如果是数据位d2d_2d2发生了翻转,则H∗c′=H∗c+H∗ei=H∗ei=[1,0,1]TH*c^{'}=H*c+H*e_i=H*e_i={[1,0,1]}^{T}H∗c′=H∗c+H∗ei=H∗ei=[1,0,1]T,从上面绿色字体的描述我们可以知道数据位d2d_2d2发生翻转会造成接收到的码字重新计算的冗余位p1p_1p1和p3p_3p3发生翻转,数据位d2d_2d2在码字中的索引为5,冗余位p1p_1p1在码字中的索引为1=201=2^01=20,冗余位p3p_3p3在码字中的索引为4=224=2^24=22,而这里计算得到的这个3×13\times13×1的向量的第1和第3个元素刚好为1,第2个元素刚好为0,1×20+0×21+1×22=51×2^0+0×2^1+1×2^2=51×20+0×21+1×22=5。
如果是冗余位p3p_3p3发生了翻转,则H∗c′=H∗c+H∗ei=H∗ei=[0,0,1]TH*c^{'}=H*c+H*e_i=H*e_i={[0,0,1]}^{T}H∗c′=H∗c+H∗ei=H∗ei=[0,0,1]T,从上面绿色字体的描述我们可以知道冗余位p3p_3p3发生翻转仅仅会造成接收到的码字重新计算的冗余位p3p_3p3发生翻转,冗余位p3p_3p3在码字中的索引为4,而这里计算得到的这个3×13\times13×1的向量的第1和第2个元素刚好为0,第3个元素刚好为1,0×20+0×21+1×22=40×2^0+0×2^1+1×2^2=40×20+0×21+1×22=4。
以上两种情况不是巧合,这正是汉明码的巧妙之处,就是我们可以根据H∗c′=H∗c+H∗ei=H∗ei=[a,b,c]TH*c^{'}=H*c+H*e_i=H*e_i=[a,b,c]^TH∗c′=H∗c+H∗ei=H∗ei=[a,b,c]T的结果是否为0向量来判断经过汉明码编码的码字在发送过程中是否发生了一个比特位的错误。如果为0则没有发生错误。如果不为0则发生了一个比特位的翻转错误。如果H∗c′=H∗c+H∗ei=H∗ei=[a,b,c]TH*c^{'}=H*c+H*e_i=H*e_i=[a,b,c]^TH∗c′=H∗c+H∗ei=H∗ei=[a,b,c]T的结果向量中只有一个数据位为1则是某个冗余数据位发生了翻转错误,如果H∗c′=H∗c+H∗ei=H∗ei=[a,b,c]TH*c^{'}=H*c+H*e_i=H*e_i=[a,b,c]^TH∗c′=H∗c+H∗ei=H∗ei=[a,b,c]T的结果向量中有多于一个数据位为1则是某个数据位发生了翻转错误。发错误的比特位在码字中的索引为a×20+b×21+c×22a×2^0+b×2^1+c×2^2a×20+b×21+c×22,假设此时r=3r=3r=3,rrr为其它值的情况类似。这里既然已经知道了具体是哪个数据位发生了翻转,那么纠错就很简单了,把对应额哪个发生翻转的位翻转回来就可以了。
那其实解码也是很简单的,根据图4中数据位的存放位置,把对应的数据位取出来就可以了。
可以看到用这种方式编码得到的汉明码属于non−systematicnon-systematicnon−systematic,那如果要得到systematicsystematicsystematic类型的应该怎么做。r=3r=3r=3的时候non−systematicnon-systematicnon−systematic类型的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G为。我们可以知道这个矩阵的每一列对应的码字中的元素为[p1,p2,d1,p3,d2,d3,d4][p_1,p_2,d_1,p_3,d_2,d_3,d_4][p1,p2,d1,p3,d2,d3,d4]。
G=[1110000100110001010101101001]G=\begin{bmatrix} 1 & 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 & 1 & 0 & 0 \\ 0 & 1 & 0 & 1 & 0 & 1 & 0 \\ 1 & 1 & 0 & 1 & 0 & 0 & 1 \end{bmatrix}G=1101101110000111010000100001
假设我们现将以前码字中的元素的位置调整一下,假设将以前的码字[p1,p2,d1,p3,d2,d3,d4][p_1,p_2,d_1,p_3,d_2,d_3,d_4][p1,p2,d1,p3,d2,d3,d4]中的元素的位置调整为[d1,d2,d3,d4,p1,p2,p3][d_1,d_2,d_3,d_4,p_1,p_2,p_3][d1,d2,d3,d4,p1,p2,p3],相应的也将generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G中的对应列的位置做调整,则调整后的码字对应的编码矩阵generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G为:
G=[1000110010010100100110001111]G=\begin{bmatrix} 1 & 0 & 0 & 0 & 1 & 1 & 0 \\ 0 & 1 & 0 & 0 & 1 & 0 & 1 \\ 0 & 0 & 1 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 \end{bmatrix}G=1000010000100001110110110111
那么经过该编码矩阵generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G编码后的码字就属于是systematicsystematicsystematic类型的。
根据前面的描述我们知道,在汉明码的探测和纠错过程中需要用到paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H,那么基于现在的systematicsystematicsystematic类型的的编码,又该如何得到对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H。我们知道前面的non−systematicnon-systematicnon−systematic类型的的编码的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H是基于图4得到的,那其实这里我们也可以基于这样的方式来得到systematicsystematicsystematic类型的的编码的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H,只不过这里要对图4做一点小小的改变,如图5所示。
在图5中的上半部分是图4一样的,下半部分是按照前面同样的方式调整了码字中的元素的位置之后对应于图4的图。接下来按照前面的non−systematicnon-systematicnon−systematic类型的编码生成paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的方式生成的systematicsystematicsystematic类型的编码的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H为:
H=[110110010110100111001]H=\begin{bmatrix} 1 & 1 & 0 & 1 &1 & 0 & 0 \\ 1 & 0 & 1 & 1 & 0 & 1 & 0\\ 0 & 1 & 1 & 1 & 0 & 0 & 1 \end{bmatrix}H=110101011111100010001
其实non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H也可以和non−systematicnon-systematicnon−systematic类型的编码的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G一样,通过对non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的列做调整来得到systematicsystematicsystematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H。
我们知道non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H是通过图4得到的,那么这个non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H究竟代表什么意思?
其实我们最开始在描述汉明码的通用算法的时候已经说明了。图4中的ParityBitCoverageParity\quad Bit\quad CoverageParityBitCoverage的区域的每一行(pn(n≥1)p_n(n\geq 1)pn(n≥1))说明了每一个冗余数据位(pn(n≥1)p_n(n\geq 1)pn(n≥1))的计算方法,每一行的红色方格表示这一行要计算的是哪一个冗余数据位,这一行的绿色方格表示这一行要计算冗余数据位是基于那些原始要发送的数据位的。比如ParityBitCoverageParity\quad Bit\quad CoverageParityBitCoverage区域的p1p_1p1行(r=3r=3r=3)表示冗余数据位p1p_1p1位的值为原始要发送的数据位D1D_1D1,D2D_2D2和D4D_4D4的奇偶校验位(这里是偶校验)。那么这里从图4中也可以看出来paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的每一列也对应于编码的码字中的每一个数据位,比如下面是non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H,我们也可以说这个矩阵的每一列分别对应的码字中的数据为为[p1,p2,d1,p3,d2,d3,d4][p_1,p_2,d_1,p_3,d_2,d_3,d_4][p1,p2,d1,p3,d2,d3,d4],那这种对应到底是什么关系呢?比如这里的第3列对应了数据位d1d_1d1,而non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的第三列的第一行和第二行不为0,第三行为0,0对应了图4中ParityBitCoverageParity\quad Bit\quad CoverageParityBitCoverage区域的白色方块,1对应了图4中ParityBitCoverageParity\quad Bit\quad CoverageParityBitCoverage区域的白色方块。其实这里的对应关系就是paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的每一行分别表示了每一个冗余数据位,比如第一行代表第一个冗余数据位p1p_1p1,每一列就表示该数据位会用于那些冗余数据位的计算。比如下面的non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的第三列的第一行和第二行不为0,第三行为0,则表示数据位d1d_1d1会参与冗余数据位p1p_1p1和p2p_2p2的计算,但是不会参与冗余数据位p3p_3p3的计算。如果paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的某一列只有一个不为0的数据,则该列代表码字中的某个冗余数据位。因此可以通过对non−systematicnon-systematicnon−systematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的列做调整来得到systematicsystematicsystematic类型的编码对应的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H。
H=[101010101100110001111]H=\begin{bmatrix} 1 & 0 & 1 & 0 &1 & 0 & 1 \\ 0 & 1 & 1 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 \end{bmatrix}H=100010110001101011111
到这里systematicsystematicsystematic类型编码的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H都已经得到了,那systematicsystematicsystematic类型编码的数据编码,校验,纠错以及解码和non−systematicnon-systematicnon−systematic类型编码一样,这里就不再累述了。
前面说过汉明码可以最多检测到2比特的错误,但是无法区分到底是1比特错误还是2比特错误,如果将2比特错误按照1比特错误来纠正的话会造成错误的结果,为了能够区分到底是1比特错误还是2比特错误,目前又引进了一种改进的汉明码,就是在已有汉明码的基础上再多加一个冗余位,使得汉明距离达到4.这样就可以区分到底是1比特错误还是2比特错误。下面我们来简单介绍一下这种改进的汉明码。
下面我们直接给出r=3r=3r=3的时候这种改进的汉明码的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H,这里是non−systematicnon-systematicnon−systematic类型的。改进的汉明码的码字为[p1,p2,d1,p3,d2,d3,d4,p4][p_1,p_2,d_1,p_3,d_2,d_3,d_4,p_4][p1,p2,d1,p3,d2,d3,d4,p4]
G=[11100001100110010101010111010010]G=\begin{bmatrix} 1 & 1 & 1 & 0 & 0 & 0 & 0 & 1\\ 1 & 0 & 0 & 1 & 1 & 0 & 0 & 1\\ 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1\\ 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 \end{bmatrix}G=11011011100001110100001000011110
H=[10101010011001100001111011111111]H=\begin{bmatrix} 1 & 0 & 1 & 0 &1 & 0 & 1 & 0\\ 0 & 1 & 1 & 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0\\ 1 & 1 & 1 & 1 &1 & 1 & 1& 1 \end{bmatrix}H=10010101110100111011011111110001
这里最明显的变化是generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H都变成了4×84\times84×8矩阵,而不是以前的3×73\times73×7矩阵。因此额外添加的冗余数据位为原始要发送的数据位(假设原始要发送的数据位有n个:d1d_1d1,d2d_2d2,…,dn−1d_{n-1}dn−1,dnd_ndn)d1d_1d1,d2d_2d2,…,dn−1d_{n-1}dn−1计算得到的偶校验值,这里r=3r=3r=3的时候额外添加的冗余数据位p4p_4p4为原始要发送的数据位d1d_1d1,d2d_2d2,d3d_{3}d3计算得到的偶校验值。还有就是改进的汉明码的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H的最后一行会将接收到的码字的所有位都拿来进行奇偶校验。
这里的改进的汉明码的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H都是non−systematicnon-systematicnon−systematic类型的,当然这里我们也可以和前面一样通过简单的矩阵中的列的互换来转换成systematicsystematicsystematic类型的,如下所示:
G=[10001101010010110010011100011110]G=\begin{bmatrix} 1 & 0 & 0 & 0 & 1 & 1 & 0 & 1\\ 0 & 1 & 0 & 0 & 1 & 0 & 1 & 1\\ 0 & 0 & 1 & 0 & 0 & 1 & 1 & 1\\ 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0 \end{bmatrix}G=10000100001000011101101101111110
H=[11011000101101000111001011111111]H=\begin{bmatrix} 1 & 1 & 0 & 1 &1 & 0 & 0 & 0\\ 1 & 0 & 1 & 1 & 0 & 1 & 0& 0\\ 0 & 1 & 1 & 1 & 0 & 0 & 1 & 0\\ 1 & 1 & 1 & 1 &1 & 1 & 1& 1 \end{bmatrix}H=11011011011111111001010100110001
没有改进的汉明码的non−systematicnon-systematicnon−systematic类型的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H如下所示:
G=[1000110010010100100110001111]G=\begin{bmatrix} 1 & 0 & 0 & 0 & 1 & 1 & 0 \\ 0 & 1 & 0 & 0 & 1 & 0 & 1 \\ 0 & 0 & 1 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 \end{bmatrix}G=1000010000100001110110110111
H=[110110010110100111001]H=\begin{bmatrix} 1 & 1 & 0 & 1 &1 & 0 & 0 \\ 1 & 0 & 1 & 1 & 0 & 1 & 0\\ 0 & 1 & 1 & 1 & 0 & 0 & 1 \end{bmatrix}H=110101011111100010001
我们可以看到没有改进的汉明码的non−systematicnon-systematicnon−systematic类型的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G可以写为[Ik,P][I_k,P][Ik,P],其中IkI_kIk为行和列都有kkk个元素的单位矩阵,PPP为k×(n−k)k\times(n-k)k×(n−k)的矩阵,这里n为编码后的码字中的位的个数,k为原始要发送的数据位的个数。那么改进的汉明码的non−systematicnon-systematicnon−systematic类型的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H为[−PT,In−k][-P^T,I_{n-k}][−PT,In−k]=[PT,In−k][P^T,I_{n-k}][PT,In−k]。还有这里generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H满足G∗HTG*H^TG∗HT为0矩阵(这里non−systematicnon-systematicnon−systematic类型和systematicsystematicsystematic类型都满足,普通型肯定满足,改进型我这里有待确认,但是我认为是可以的)。
这里就是汉明码的巧妙,也是数学的巧妙,没想到转换为矩阵的操作之后可以有这样的效果。但是前面也说过了,我目前没有这方面的积累以及足够的时间,因此这里涉及到数学方面的我就不讲了,自己感兴趣的可以自己去查询相关的资料。
我们可以看到经过交换改进的汉明码的non−systematicnon-systematicnon−systematic类型的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G而得到的改进的汉明码的systematicsystematicsystematic类型的generatormatrix,Ggenerator\quad matrix, Ggeneratormatrix,G满足[Ik,P][I_k,P][Ik,P],但是经过交换改进的汉明码的non−systematicnon-systematicnon−systematic类型的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H而得到的改进的汉明码的systematicsystematicsystematic类型的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H不满足[PT,In−k][P^T,I_{n-k}][PT,In−k],因为这里的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H最后一行的所有元素都为1,但是这里可以通过的线性运算(数乘和加法)来将改进的汉明码的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H转换为符合[PT,In−k][P^T,I_{n-k}][PT,In−k]的systematicsystematicsystematic类型。但是这里又是数学运算的问题了,因此这里涉及到数学方面的我就不讲了,自己感兴趣的可以自己去查询相关的资料。至于这里改进的汉明码能不能满足[Ik,P][I_k,P][Ik,P]到[PT,In−k][P^T,I_{n-k}][PT,In−k]的对应关系我就不是太清楚了,但是我认为是满足的,只是有待查资料确认。
至于改进的汉明码的的编码解码就没什么好说的了。至于探测和纠错,我们看一下下面改进的汉明码的non−systematicnon-systematicnon−systematic类型的paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H和接收到的码字的乘法的结果。
H∗c=[10101010011001100001111011111111][p1p2d1p3d2d3d4p4]=[p1+d1+d2+d4p2+d1+d3+d4p3+d2+d3+d4p1+p2+p3+p4+d1+d2+d3+d4]H*c=\begin{bmatrix} 1 & 0 & 1 & 0 &1 & 0 & 1 & 0\\ 0 & 1 & 1 & 0 & 0 & 1 & 1 & 0\\ 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0\\ 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \end{bmatrix}\begin{bmatrix} p_1 \\ p_2 \\ d_1 \\ p_3 \\ d_2 \\ d_3 \\ d_4\\ p_4 \end{bmatrix}=\begin{bmatrix} p_1+d_1 + d_2+d_4 \\ p_2+d_1 + d_3+d_4 \\ p_3+d_2 + d_3+d_4 \\ p_1+p_2+p_3+p_4+d_1 + d_2+d_3+d_4 \end{bmatrix}H∗c=10010101110100111011011111110001p1p2d1p3d2d3d4p4=p1+d1+d2+d4p2+d1+d3+d4p3+d2+d3+d4p1+p2+p3+p4+d1+d2+d3+d4
结果的前三个没什么好说的,和没有改进的汉明码一样,如果码字在传输过程中没有出错的话,这三个值肯定都是0。如果码字在传输过程中没有出错的话,最后一个值p1+p2+p3+p4+d1+d2+d3+d4p_1+p_2+p_3+p_4+d_1 + d_2+d_3+d_4p1+p2+p3+p4+d1+d2+d3+d4肯定也是0。这是因为:
因此p1+p2+p3+p4+d1+d2+d3+d4p_1+p_2+p_3+p_4+d_1 + d_2+d_3+d_4p1+p2+p3+p4+d1+d2+d3+d4=4∗d1+4∗d2+4∗d3+4∗d4=04*d_1 + 4*d_2+4*d_3+4*d_4=04∗d1+4∗d2+4∗d3+4∗d4=0(偶校验运算)。前面我们说过汉明码可以最多检测到2比特的错误,但是无法区分到底是1比特错误还是2比特错误,如果将2比特错误按照1比特错误来纠正的话会造成错误的结果。但是改进的汉明码可以区分到底是1比特错误还是2比特错误。下面我直接给结论,至于原理需要一定的数学背景,我也不会,我也没时间,大家有空的话自己去查一下相关的资料。
我这里的结论来自于图6的文档,文档在这里。
图6这里描述到,如果对于改进的汉明码,如果接收到的码字和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H乘积为:
[sp]\begin{bmatrix} s \\ p \end{bmatrix}[sp]
其中sss对应于没有改进的汉明码,接收到的码字和paritycheckmatrix,Hparity\quad check\quad matrix, Hparitycheckmatrix,H乘积,如果r=3r=3r=3的话,这里的sss中有3个元素。ppp对应于改进的汉明码中接收到的码字中的所有元素的偶校验位。结论为:
下面我将会对NANDFLASHNAND\quad FLASHNANDFLASH厂商的文档(如图7,图8和图9所示)中描述的所谓的汉明码ECCECCECC算法做一个简单的介绍,一般的通用MCUMCUMCU上面的FSMC,FlexiblestaticmemorycontrollerFSMC,Flexible\quad static\quad memory\quad controllerFSMC,Flexiblestaticmemorycontroller模块,也就是外部存储器控制器接口的NANDFLASHNAND\quad FLASHNANDFLASH接口的硬件ECCECCECC算法好像也是采用的这种算法。一般该汉明码ECCECCECC算法在256个字节数据上的冗余ECCECCECC数据位为22比特,在512个字节数据上的冗余ECCECCECC数据位为24比特。下面的介绍先基于图7中的文档
图10 是512个字节的数据块的24位冗余ECCECCECC数据的算法。这24位的冗余ECCECCECC数据可以分为两部分:行冗余数据:16位,p8,p8′,p16,p16′,...,p2048,p2048′p_8,p_{8^{'}},p_{16},p_{{16}^{'}},...,p_{2048},p_{{2048}^{'}}p8,p8′,p16,p16′,...,p2048,p2048′和列冗余数据:6位,p1,p1′,p2,p2′,p4,p4′p_1,p_{1^{'}},p_2,p_{2^{'}},p_4,p_{4^{'}}p1,p1′,p2,p2′,p4,p4′。其中⊕\oplus⊕表示异或运算。下面是当ECCECCECC冗余数据计算模块读入512个字节的数据块的第一个字节数据的时候列冗余数据的计算方法。
当读入512个字节的数据块的后续字节数据的时候列冗余数据的计算方法如下,也就是冗余数据位本身现在也要参与运算:
ECCECCECC冗余数据的行冗余数据的计算就要特殊一点,但是相对也简单一点。当读入512个字节的数据块的每一个字节数据的时候,该字节的素有位都会参与行冗余数据位的计算,不像列冗余数据位计算的时候那样会对读入的字节数据的部分位来进行计算。但是比较特别是对于读入的这512(索引,indexindexindex,为0到511)个字节的数据:
如果index&(0x0001)≠0index\ \&\ (0x0001)\neq0index & (0x0001)=0,那么该字节的所有比特位异或的结果得到p8p_8p8,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p8p_8p8的话,那么p8p_8p8本身也得参与计算得到p8p_8p8。也就是:
如果index&(0x0001)=0index\ \&\ (0x0001)=0index & (0x0001)=0,那么该字节的所有比特位异或的结果得到p8′p_{8^{'}}p8′,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p8′p_{8^{'}}p8′的话,那么p8′p_{8^{'}}p8′本身也得参与计算得到p8′p_{8^{'}}p8′。
如果index&(0x0002)≠0index\ \&\ (0x0002)\neq0index & (0x0002)=0,那么该字节的所有比特位异或的结果得到p16p_{16}p16,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p16p_{16}p16的话,那么p16p_{16}p16本身也得参与计算得到p16p_{16}p16。
如果index&(0x0002)=0index\ \&\ (0x0002)=0index & (0x0002)=0,那么该字节的所有比特位异或的结果得到p16′p_{{16}^{'}}p16′,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p16′p_{{16}^{'}}p16′的话,那么p16′p_{{16}^{'}}p16′本身也得参与计算得到p16′p_{{16}^{'}}p16′。
如果index&(0x0004)≠0index\ \&\ (0x0004)\neq0index & (0x0004)=0,那么该字节的所有比特位异或的结果得到p32p_{32}p32,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p32p_{32}p32的话,那么p32p_{32}p32本身也得参与计算得到p32p_{32}p32。也就是:
如果index&(0x0004)=0index\ \&\ (0x0004)=0index & (0x0004)=0,那么该字节的所有比特位异或的结果得到p32′p_{{32}^{'}}p32′,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p32′p_{{32}^{'}}p32′的话,那么p32′p_{{32}^{'}}p32′本身也得参与计算得到p32′p_{{32}^{'}}p32′。
如果index&(0x0008)≠0index\ \&\ (0x0008)\neq0index & (0x0008)=0,那么该字节的所有比特位异或的结果得到p64p_{64}p64,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p64p_{64}p64的话,那么p64p_{64}p64本身也得参与计算得到p64p_{64}p64。也就是:
如果index&(0x0008)=0index\ \&\ (0x0008)=0index & (0x0008)=0,那么该字节的所有比特位异或的结果得到p64′p_{{64}^{'}}p64′,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p64′p_{{64}^{'}}p64′的话,那么p64′p_{{64}^{'}}p64′本身也得参与计算得到p64′p_{{64}^{'}}p64′。
如果index&(0x0010)≠0index\ \&\ (0x0010)\neq0index & (0x0010)=0,那么该字节的所有比特位异或的结果得到p128p_{128}p128,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p128p_{128}p128的话,那么p128p_{128}p128本身也得参与计算得到p128p_{128}p128。也就是:
如果index&(0x0010)=0index\ \&\ (0x0010)=0index & (0x0010)=0,那么该字节的所有比特位异或的结果得到p128′p_{{128}^{'}}p128′,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p128′p_{{128}^{'}}p128′的话,那么p128′p_{{128}^{'}}p128′本身也得参与计算得到p128′p_{{128}^{'}}p128′。
如果index&(0x0020)≠0index\ \&\ (0x0020)\neq0index & (0x0020)=0,那么该字节的所有比特位异或的结果得到p256p_{256}p256,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p256p_{256}p256的话,那么p256p_{256}p256本身也得参与计算得到p256p_{256}p256。也就是:
如果index&(0x0020)=0index\ \&\ (0x0020)=0index & (0x0020)=0,那么该字节的所有比特位异或的结果得到p256′p_{{256}^{'}}p256′,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p256′p_{{256}^{'}}p256′的话,那么p256′p_{{256}^{'}}p256′本身也得参与计算得到p256′p_{{256}^{'}}p256′。
如果index&(0x0040)≠0index\ \&\ (0x0040)\neq0index & (0x0040)=0,那么该字节的所有比特位异或的结果得到p512p_{512}p512,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p512p_{512}p512的话,那么p512p_{512}p512本身也得参与计算得到p512p_{512}p512。也就是:
如果index&(0x0040)=0index\ \&\ (0x0040)=0index & (0x0040)=0,那么该字节的所有比特位异或的结果得到p512′p_{{512}^{'}}p512′,如果这里先前已经有512个字节的数据中的某一个数据用来计算得到p512′p_{{512}^{'}}p512′的话,那么p512′p_{{512}^{'}}p512′本身也得参与计算得到p512′p_{{512}^{'}}p512′。
如果index&(0x0080)≠0index\ \&\ (0x0080)\neq0index & (0x0080)=0,那么该字节的所有比特位异或的结果得到p1024p_{1024}p1024,如果这里先前已经有1024个字节的数据中的某一个数据用来计算得到p1024p_{1024}p1024的话,那么p1024p_{1024}p1024本身也得参与计算得到p1024p_{1024}p1024。也就是:
如果index&(0x0080)=0index\ \&\ (0x0080)=0index & (0x0080)=0,那么该字节的所有比特位异或的结果得到p1024′p_{{1024}^{'}}p1024′,如果这里先前已经有1024个字节的数据中的某一个数据用来计算得到p1024′p_{{1024}^{'}}p1024′的话,那么p1024′p_{{1024}^{'}}p1024′本身也得参与计算得到p1024′p_{{1024}^{'}}p1024′。
如果index&(0x0100)≠0index\ \&\ (0x0100)\neq0index & (0x0100)=0,那么该字节的所有比特位异或的结果得到p2048p_{2048}p2048,如果这里先前已经有2048个字节的数据中的某一个数据用来计算得到p2048p_{2048}p2048的话,那么p2048p_{2048}p2048本身也得参与计算得到p2048p_{2048}p2048。也就是:
如果index&(0x0100)=0index\ \&\ (0x0100)=0index & (0x0100)=0,那么该字节的所有比特位异或的结果得到p2048′p_{{2048}^{'}}p2048′,如果这里先前已经有2048个字节的数据中的某一个数据用来计算得到p2048′p_{{2048}^{'}}p2048′的话,那么p2048′p_{{2048}^{'}}p2048′本身也得参与计算得到p2048′p_{{2048}^{'}}p2048′。
所有ECCECCECC冗余数据计算完成之后的排布图11所示:
NANDFLASHNAND\quad FLASHNANDFLASH相比起NORFLASHNOR\quad FLASHNORFLASH的一点区别是,NANDFLASHNAND\quad FLASHNANDFLASH的每一页存储空间都有对应的sparesparespare区域,如图12所示。这里是在网上随便找的一款NANDFLASHNAND\quad FLASHNANDFLASH的数据手册里面对该NANDFLASHNAND\quad FLASHNANDFLASH的存储空间的图示,从图中我们可以看到该NANDFLASHNAND\quad FLASHNANDFLASH的每一页的大小为4096字节,每一页的sparesparespare区域的大小为224字节。如果访问NANDFLASHNAND\quad FLASHNANDFLASH的通用MCUMCUMCU的FSMCFSMCFSMC模块有使能ECCECCECC功能的话,那么每次向NANDFLASHNAND\quad FLASHNANDFLASH写入一定的数据后(一般是512字节)FSMCFSMCFSMC模块会计算写入的数据(发送的命令不会参与运算)的冗余ECCECCECC数据,如果是按照前面的算法计算的话就应该是24比特位。用户可以将该计算的冗余ECCECCECC数据放在该页对应的sparesparespare区域。下次去读这一块数据的时候,FSMCFSMCFSMC模块也会计算读出数据(发送的命令不会参与运算)的冗余ECCECCECC数据,这样通过对比读出的时候计算出的冗余ECCECCECC数据和保存在sparesparespare区域的上次写入的时候计算的冗余ECCECCECC数据就可以判断是否发生了错误。
假设这里读写的数据块的大小为512字节,则按照上面的算法计算得到的冗余ECCECCECC数据的大小为24个比特位。将读出的时候计算出的冗余ECCECCECC数据和保存在sparesparespare区域的上次写入的时候计算的冗余ECCECCECC数据进行异或运算:
下一篇:设计模式-02