久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 18752|回復: 6
收起左側(cè)

STM32 ECC校驗的一些心得

[復制鏈接]
ID:76190 發(fā)表于 2015-4-5 20:48 | 顯示全部樓層 |閱讀模式
      STM32FSMC功能支持SRAMNOR FLASHNAND FLASH,是非常方便的。

當然,要STM32F103VC及以上的芯片才支持FSMC功能的。

   在此寫下一些調(diào)試使用FMMC調(diào)試NAND FLASH的心得及總結(jié),方便以后回顧,也便于大家一起交流學習。

在這里重點寫下的是調(diào)試ECC這個功能。

 使用的NAND FLASH芯片K9F2G08U0C

     芯片大小是2Gbit,也就是容量256MB。一塊64頁,一頁2K字節(jié)

     一頁2048字節(jié),其中,OOB區(qū)64字節(jié)。

     當然,要能正常使用ECC功能,NAND_FLASH的讀寫正常是前提。這里不作介紹。要ST公司提供的例子里有NAND_FLASH的讀寫例子,一般可參照其配置再結(jié)合自己實際使用的NAND_FLASH芯片及電路設計修改。

   保證了能正常讀寫頁功能,以及讀寫OOB區(qū)數(shù)據(jù)功能,即可繼續(xù)調(diào)試ECC了。

   以下這段話就是來自STM32FSMC使用手冊里關于ECC的介紹

 

   The FSMC NAND Flash controller includes two pieces oferror correction code computation

hardware, one for each NANDFlash memory block.

The ECC can be performed forpage sizes of 256, 512, 1024, 2048, 4096 or 8192 bytes,

depending on the ECCpage sizeconfigured by the user. Depending on the configured page

size, the ECC code will be 22,24, 26, 28, 30 or 32 bits.

To even improve the errorcoverage, the user can read/write the NAND Flash page with a

reduced ECC page size. This ispossible when starting and stopping the ECC computation

after the desired number ofbytes to check. In this case, the ECC code is only calculated for

the bytes written and read.

 

   這里就不講太官方的介紹了。

比如我要使用ECC功能,每512個字節(jié)產(chǎn)生一個ECC數(shù)據(jù),這樣,當這512字節(jié)里出錯有一位錯誤的時候,可以通過ECC來糾正。當然,如果錯了幾個位,就無法糾錯了。雖然當兩個位有錯,也知道,但不知道是哪兩個位出錯,也糾正不了。所以,只要關心怎么找出錯誤,通過ECC怎么糾錯。

 FSMCECC支持每256字節(jié),512字節(jié),1024,。。。8192字節(jié)產(chǎn)生一個ECC數(shù)據(jù)。

調(diào)試時使用每512字節(jié)產(chǎn)生一個ECC功能。

當寫入512個字節(jié)時,產(chǎn)生一個ECC數(shù)據(jù),然后,再讀512個字節(jié)的時候,也會產(chǎn)生一個ECC數(shù)據(jù),通過這兩個數(shù)據(jù)相異或,產(chǎn)生一個ECC校驗結(jié)果,通過這個判斷結(jié)果,就可以分析出有沒有錯,錯在哪里,是錯哪一位。當然,知道哪一位錯了,也就可以糾正了。

 

現(xiàn)在具體以實際的NAND_FLASH為例。

K9F2G08U0C這個芯片雖然是每頁2048個字節(jié),也就是4 512字節(jié)。按理說直接使用每2048字節(jié)產(chǎn)生一個ECC即可校驗,這樣也方便一些。但因為實際使用中,是把這FLASH當作U盤來使用,并使用了fat32文件系統(tǒng),將其作扇區(qū)處理了。一般扇區(qū)單位為512個字節(jié)。因此,這里就使用每512個字節(jié)產(chǎn)生一個ECC

 

FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND;

  FSMC_NANDInitStructure.FSMC_Waitfeature =FSMC_Waitfeature_Enable;

  FSMC_NANDInitStructure.FSMC_MemoryDataWidth =FSMC_MemoryDataWidth_8b;

  FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable;

 FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;

  FSMC_NANDInitStructure.FSMC_AddressLowMapping= FSMC_AddressLowMapping_Direct;

  FSMC_NANDInitStructure.FSMC_TCLRSetupTime =0x00;

  FSMC_NANDInitStructure.FSMC_TARSetupTime =0x00;

 FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;

  FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct= &p;

 

  FSMC_NANDInit(&FSMC_NANDInitStructure);

 

  /* FSMC NAND Bank Cmd Test */

  FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);

 

  初始化主要為上述幾句指令:

 FSMC_NANDInitStructure.FSMC_ECC =FSMC_ECC_Enable;

 FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;

 

  然后在讀寫NAND_FLASH,即可讀到ECC數(shù)據(jù)。

 

u32 write_ecc;

u32 read_ecc;

 for(i=0;i<512;i++)

 {

    buffer[i]=i%256;

 }

 

    FSMC_NANDECCCmd(FSMC_Bank2_NAND,ENABLE);

    FSMC_NAND_WritePage(buffer,0,512);

  while(FSMC_GetFlagStatus(FSMC_Bank2_NAND,FSMC_FLAG_FEMPT)==Bit_RESET);

   write_ecc = FSMC_GetECC(FSMC_Bank2_NAND);

   FSMC_NANDECCCmd(FSMC_Bank2_NAND,DISABLE);

//這是寫入512個字節(jié)時候讀ECC.

 

    FSMC_NANDECCCmd(FSMC_Bank2_NAND,ENABLE);

         FSMC_NAND_ReadPage(read,0,512);

   while(FSMC_GetFlagStatus(FSMC_Bank2_NAND,FSMC_FLAG_FEMPT)==Bit_RESET);

    read_ecc = FSMC_GetECC(FSMC_Bank2_NAND);

    FSMC_NANDECCCmd(FSMC_Bank2_NAND,DISABLE);

//這是讀512個時候讀取ECC

  

 要保證讀取到正確的ECC數(shù)據(jù),要在讀之前先失能下ECC功能,把ECC數(shù)據(jù)清零,再使用ECC,然后再讀或?qū)?/span>NAND_FLASH。再讀到相應的ECC。讀ECC后記得把ECC失能,以清空ECC數(shù)據(jù)。 

   這樣就可以讀到write_ecc了。當然,這個數(shù)據(jù)會讀到的是0,為什么呢,所以很多時候我們測試數(shù)據(jù),都是用比較有規(guī)律的數(shù)據(jù)去測試,下面通過幾組數(shù)據(jù),來解讀下這個ECC的數(shù)據(jù)分析 

for(i=0;i<512;i++)

  {

    buffer[i]=0x11;

  }

ECC: 0

 

 

 512個字節(jié)里,都是0x11的話,ECC數(shù)據(jù)是0。然后改變其中某個字節(jié)的某個位,再去讀ECC看。

for(i=0;i<512;i++)

  {

    buffer[i]=0x11;

  }

buffer [0]=0x10;

ECC: 0x55555555

這是改了第一個字節(jié)的第一個位。(但習慣上從0開始比較習慣,改了第0個字節(jié)第0個位)

for(i=0;i<512;i++)

  {

    buffer[i]=0x11;

  }

buffer [0]=0x13;

ECC:0x55555556

改了第1個位

 

 

for(i=0;i<2048;i++)

  {

    buffer[i]=0x11;

  }

buffer [0]=0x15;

ECC:0x55555559

改了第2個位

 

 

for(i=0;i<2048;i++)

  {

    buffer[i]=0x11;

  }

buffer [0]=0x19;

ECC:0x5555555a

 

 

 

 

for(i=0;i<512;i++)

  {

    buffer[i]=0x11;

  }

buffer [511]=0x91;

ECC:0x55aaaaaa;

這里改了第4095個位,也就是(第511個字節(jié)的最高位,也就是512個字節(jié)里的最高一個位)

 

好了,有了以上這里數(shù)據(jù),就可以開始解讀了,就算找不到例子,只要你的NAND_FLASH讀寫正常了,能把這些看懂了,也就可以使用ECC功能了。

 

下面對這幾個ECC數(shù)據(jù)進行解讀。

 

解讀前先看一下ECC結(jié)果寄存器。

   因為我們設置的是512個字節(jié)產(chǎn)生一個ECC。那么有效位是023 

也就是前面讀到的ECC數(shù)據(jù)呢,只要低24位就可以了。

當然,從這里還能看出其它數(shù)據(jù)。最高是8192字節(jié),占了32位,

4096字節(jié)占了30位。

這個規(guī)律就是從256字節(jié)開始,每增一倍字節(jié)數(shù),ECC就多占用兩個位。

按常理說,只要多一個位,就可以表示多一倍的數(shù)據(jù)了。但是要表示多一個數(shù)據(jù),需要到兩個位,那,這里就有點玄機了。

甚至不需要去理解或弄明白它使用是漢明碼,什么BCH碼,只要看明白下這里,一直可以糾錯。因為,不要管它是什么糾錯碼,就跟著這個規(guī)律去理解。

512個字節(jié)的ECC用了24位,512個字節(jié)共有512*8=4096個位。要表示到4096個數(shù),也就是剛好12位就可以了。所以,因此這里的玄機就是ECC數(shù)據(jù)里,用了2個位來表示一個位的數(shù)據(jù)。

這時,再看一下關于STM32 ECC的介紹。

When an erroroccurs during the write operation, this error is either correctable or

uncorrectabledepending on the ECC XOR operation:

Case of acorrectable error

The ECC XORoperation contains 11-bit data at 1. And each pair parity is 0x10 or

0x01.

 

忘了說,我們這些測試數(shù)據(jù)呢,是以寫入0x11為主,然后故意改錯某一個位,再讀出ECC。因為寫入全部的是0x11,因此寫入時產(chǎn)生的ECC0x0。那么再將讀出來的ECC0x0異或,得到的,也就是ECC校驗結(jié)果了。

當錯第0個位的時候,校驗結(jié)果是0x55555555。取低24位,也就是0x555555

 

對應24位就是

010101010101010101010101

當錯第1個位的時候,校驗結(jié)果是0x555556(取低24位)

對應24位就是

010101010101010101010110

當錯第2個位對應的24位是:

010101010101010101011001

當錯第3個位對應的24位是:

010101010101010101011010

…………

當錯第4095個位(也就是第511個字節(jié)的最高位) 校驗結(jié)果:0xaaaaaa

對應24位是:

101010101010101010101010

 

看到這里,大家估計很容易看出來規(guī)律了。

0個位錯誤的24位數(shù)據(jù)解碼出來12位就是:0000 00000000,也就是0x0,就是第0個位錯誤.

1個位錯誤的24位數(shù)據(jù)解碼出來12位就是:0000 00000001,也就是0x1,就是第1個位錯誤.

2個位錯誤的24位數(shù)據(jù)解碼出來12位就是:0000 00000010,也就是0x2,就是第2個位錯誤.

3個位錯誤的24位數(shù)據(jù)解碼出來12位就是:0000 00000011,也就是0x3,就是第3個錯誤.

4095個位錯誤的24位數(shù)據(jù)解碼出來12位就是:1111 11111111,也就是0xfff,就是第4095個位錯誤.

 

到了這一步,不知道有沒有明白糾正原理呢。當知道是哪一個是錯誤的了,剩下的就簡單了,就把錯誤的那一位把0變成1,或者把1變成0就行了。

可以寫成一個函數(shù),ecc_data為校驗結(jié)果。

 

intcheck_ecc(u32 ecc_data)

{

  u32 temp;

  int i;

  u8 data4;

  u32 location=0;

  temp=ecc_data&0xffffff;//只要24

 

 

  for(i=0;i<24/2;i++)

    {

     data4=(temp>>(i*2))&0x3;

     if(data4==0x01)

        {

        // 如果兩位是0x01,則判斷是0

        }

     else if(data4==0x02)

        {

         // 1 如果兩個是0x10,則判斷是1

         location|=(1<<i);

        }

     else

        {

        // 如果不是兩種其一,剛說明無法糾錯

                   // 既然無法糾錯,其它的,就暫時不關心了

         return -1;

        }

     printf("location:%d..\r\n",location);

 

    }

  return location;

 

}

 

 

當然,如果校驗結(jié)果為0x00的時候,說明讀出來的數(shù)據(jù)是對的。不需要調(diào)用這個函數(shù)了。調(diào)用這個函數(shù)時,就可以返回錯誤的位置。

到此,ECC的功能就調(diào)試的差不多了。剩下的,就是把那一位糾錯出來就好了。重要的ECC校驗結(jié)果出來了,知道是哪一位錯誤了,剩下的還不好辦了。

 

對于NAND_FLASH呢,具體就可以這樣實現(xiàn)了。

一頁是2048個字節(jié)加OOB64個字節(jié)。

OOB區(qū)一般是存放ECC數(shù)據(jù),一般如果寫到跑系統(tǒng)的是,用設計ECC layout的。

這里就簡單作個layout吧。簡單地說,就是把ECC放在哪里。

因為這里每512個字節(jié), 產(chǎn)生一個ECC,占4個字節(jié)。

1 512字節(jié)產(chǎn)生的ECC就放到OOB區(qū)里的0x10,0x11,x12,0x13這四個地址里。

2 512字節(jié)產(chǎn)生的ECC就放到OOB區(qū)里的0x14,0x15,x16,0x17這四個地址里。

3 512字節(jié)產(chǎn)生的ECC就放到OOB區(qū)里的0x18,0x19,x1a,0x1b這四個地址里。

4 512字節(jié)產(chǎn)生的ECC就放到OOB區(qū)里的0x1c,0x1d,x1e,0x1f這四個地址里。

    

     這樣,ECC layout就算是設置好了。因此只要在寫入的時候,把ECC相應地存入到OOB區(qū),然后在讀NAND_FLASH的時候,再讀新的ECC數(shù)據(jù),和之前寫入到OOB里的ECC進行異或,得到ECC校驗結(jié)果。那,ECC的調(diào)試,就算告?zhèn)段落了。

如果有錯誤之處,還請見諒。

特此寫下以便日后可以回顧,而且網(wǎng)上涉及的也比較少,寫出來也讓感興趣的人一起交流學習。


FSMC的使用手冊*(英文的),以及fsmc_nand.c的驅(qū)動測試ECC一同上傳到了我的CSDN里了,有需要可下載 STM32 ECC調(diào)試及心得.zip (385.02 KB, 下載次數(shù): 76)

回復

使用道具 舉報

ID:161913 發(fā)表于 2017-1-15 19:10 | 顯示全部樓層
需要這個東西。謝謝分享!
回復

使用道具 舉報

ID:161913 發(fā)表于 2017-1-15 19:16 | 顯示全部樓層
很有用,非常感謝樓主分享。
回復

使用道具 舉報

ID:20697 發(fā)表于 2017-10-27 10:33 | 顯示全部樓層
學習了。
有個問題,512字節(jié)寫一次,2k的page要寫4次嗎?
回復

使用道具 舉報

ID:20697 發(fā)表于 2017-10-27 10:34 | 顯示全部樓層
本帖最后由 hunancjz 于 2017-10-31 14:30 編輯

請問一下ECC如何寫到OOB?
我的理解是,data區(qū)分4次寫,得到4個ECC,再把4個ECC寫到OOB。
就是說寫一頁要進行5次寫操作。
這樣理解對嗎?
回復

使用道具 舉報

ID:256228 發(fā)表于 2017-12-1 18:24 | 顯示全部樓層
我用的也是 4096Bytes/Page 的NANDFLASH,非常感謝樓主分享解了我的困惑。
回復

使用道具 舉報

ID:396291 發(fā)表于 2018-9-10 23:45 | 顯示全部樓層
正在學習這個,謝謝樓主分享
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 黄色免费在线视频 | 国产精品成人一区二区三区 | 成人91视频 | 精品国产乱码久久久久久蜜柚 | 国产精品国产 | 国产成人影视 | 亚洲欧美日韩国产精品 | 国产成人在线播放 | 欧美日本 | 可以看av的网站 | 国产精品久久久久久中文字 | 欧美啪啪网 | 久操国产| 成年人黄色 | 久久成人精品 | 日本三级久久 | 一本色道久久综合亚洲精品小说 | 女同一区二区三区 | 成人高清视频在线观看 | 国产一区二区三区在线 | 成人激情综合网 | 青青草国产成人av片免费 | 九九在线精品 | 日韩一级二级三级 | 欧美 日韩 国产 成人 在线 | 亚洲一级二级三级 | 欧美日韩一二三区 | 亚洲日本欧美 | 青青草国产成人av片免费 | 91中文在线 | 婷婷色网 | 日韩亚洲天堂 | 久久精品av| 精品久久久久久久久久久久久久久久 | 99精品色 | 亚洲激情视频在线观看 | 一级黄色av | 夜夜操夜夜 | 日韩精品一区二区在线 | 欧美日韩国产精品 | 免费观看的黄色网址 |