NandFlash?ECC校驗原理與實現(xiàn)
時間:2021-08-19 16:23:55
手機看文章
掃描二維碼
隨時隨地手機看文章
[導(dǎo)讀]關(guān)注星標公眾號,不錯過精彩內(nèi)容來源|nhczp編排|strongerHuang大家應(yīng)該都在用U盤,而U盤中的存儲芯片就是NandFlash,你買的64G的U盤,實際并沒有64G,其中一個原因就是存在壞塊。因為工藝和其他方面的原因,不能保證NandFlash不存在壞塊,因此就需要“...
關(guān)注 星標公眾號,不錯過精彩內(nèi)容來源 | nhczp編排 | strongerHuang
大家應(yīng)該都在用U盤,而U盤中的存儲芯片就是NandFlash,你買的64G的U盤,實際并沒有64G,其中一個原因就是存在壞塊。
因為工藝和其他方面的原因,不能保證NandFlash不存在壞塊,因此就需要“挑選出壞塊”。
本文就為大家講述一下用于NandFlash的ECC校驗原理與實現(xiàn)。
ECC簡介由于NAND Flash的工藝不能保證NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生產(chǎn)中及使用過程中會產(chǎn)生壞塊。為了檢測數(shù)據(jù)的可靠性,在應(yīng)用NAND Flash的系統(tǒng)中一般都會采用一定的壞區(qū)管理策略,而管理壞區(qū)的前提是能比較可靠的進行壞區(qū)檢測。
如果操作時序和電路穩(wěn)定性不存在問題的話,NAND Flash出錯的時候一般不會造成整個Block或是Page不能讀取或是全部出錯,而是整個Page(例如512Bytes)中只有一個或幾個bit出錯。
對數(shù)據(jù)的校驗常用的有奇偶校驗、CRC校驗等,而在NAND Flash處理中,一般使用一種比較專用的校驗——ECC。ECC能糾正單比特錯誤和檢測雙比特錯誤,而且計算速度很快,但對1比特以上的錯誤無法糾正,對2比特以上的錯誤不保證能檢測。
ECC原理ECC一般每256字節(jié)原始數(shù)據(jù)生成3字節(jié)ECC校驗數(shù)據(jù),這三字節(jié)共24比特分成兩部分:6比特的列校驗和16比特的行校驗,多余的兩個比特置1,如下圖所示:
ECC的列校驗和生成規(guī)則如下圖所示:
用數(shù)學(xué)表達式表示為:
ECC的行校驗和生成規(guī)則如下圖所示:
用數(shù)學(xué)表達式表示為:
當往NAND Flash的page中寫入數(shù)據(jù)的時候,每256字節(jié)我們生成一個ECC校驗和,稱之為原ECC校驗和,保存到PAGE的OOB(out-of-band)數(shù)據(jù)區(qū)中。
當從NAND Flash中讀取數(shù)據(jù)的時候,每256字節(jié)我們生成一個ECC校驗和,稱之為新ECC校驗和。
校驗的時候,根據(jù)上述ECC生成原理不難推斷:將從OOB區(qū)中讀出的原ECC校驗和新ECC校驗和按位異或,若結(jié)果為0,則表示不存在錯(或是出現(xiàn)了ECC無法檢測的錯誤);若3個字節(jié)異或結(jié)果中存在11個比特位為1,表示存在一個比特錯誤,且可糾正;若3個字節(jié)異或結(jié)果中只存在1個比特位為1,表示OOB區(qū)出錯;其他情況均表示出現(xiàn)了無法糾正的錯誤。
ECC算法的實現(xiàn)這里附上算法代碼:
大家應(yīng)該都在用U盤,而U盤中的存儲芯片就是NandFlash,你買的64G的U盤,實際并沒有64G,其中一個原因就是存在壞塊。
因為工藝和其他方面的原因,不能保證NandFlash不存在壞塊,因此就需要“挑選出壞塊”。
本文就為大家講述一下用于NandFlash的ECC校驗原理與實現(xiàn)。
ECC簡介由于NAND Flash的工藝不能保證NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生產(chǎn)中及使用過程中會產(chǎn)生壞塊。為了檢測數(shù)據(jù)的可靠性,在應(yīng)用NAND Flash的系統(tǒng)中一般都會采用一定的壞區(qū)管理策略,而管理壞區(qū)的前提是能比較可靠的進行壞區(qū)檢測。
如果操作時序和電路穩(wěn)定性不存在問題的話,NAND Flash出錯的時候一般不會造成整個Block或是Page不能讀取或是全部出錯,而是整個Page(例如512Bytes)中只有一個或幾個bit出錯。
對數(shù)據(jù)的校驗常用的有奇偶校驗、CRC校驗等,而在NAND Flash處理中,一般使用一種比較專用的校驗——ECC。ECC能糾正單比特錯誤和檢測雙比特錯誤,而且計算速度很快,但對1比特以上的錯誤無法糾正,對2比特以上的錯誤不保證能檢測。
ECC原理ECC一般每256字節(jié)原始數(shù)據(jù)生成3字節(jié)ECC校驗數(shù)據(jù),這三字節(jié)共24比特分成兩部分:6比特的列校驗和16比特的行校驗,多余的兩個比特置1,如下圖所示:
ECC的列校驗和生成規(guī)則如下圖所示:
用數(shù)學(xué)表達式表示為:
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的行校驗和生成規(guī)則如下圖所示:
用數(shù)學(xué)表達式表示為:
P8 = bit7( )bit6( )bit5( )bit4( )bit3( )bit2( )bit1( )bit0( )P8
備注:這里( )表示“位異或”操作當往NAND Flash的page中寫入數(shù)據(jù)的時候,每256字節(jié)我們生成一個ECC校驗和,稱之為原ECC校驗和,保存到PAGE的OOB(out-of-band)數(shù)據(jù)區(qū)中。
當從NAND Flash中讀取數(shù)據(jù)的時候,每256字節(jié)我們生成一個ECC校驗和,稱之為新ECC校驗和。
校驗的時候,根據(jù)上述ECC生成原理不難推斷:將從OOB區(qū)中讀出的原ECC校驗和新ECC校驗和按位異或,若結(jié)果為0,則表示不存在錯(或是出現(xiàn)了ECC無法檢測的錯誤);若3個字節(jié)異或結(jié)果中存在11個比特位為1,表示存在一個比特錯誤,且可糾正;若3個字節(jié)異或結(jié)果中只存在1個比特位為1,表示OOB區(qū)出錯;其他情況均表示出現(xiàn)了無法糾正的錯誤。
ECC算法的實現(xiàn)這里附上算法代碼:
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 = 0;
/* Calculate first ECC byte */
for (i = 0; i < 4; i )
{
if (reg3