STM32的FSMC功能支持SRAM,NOR FLASH,NAND FLASH,是非常方便的。 當然,要STM32F103VC及以上的芯片才支持FSMC功能的。 在此寫下一些調試使用FMMC調試NAND FLASH的心得及總結,方便以后回顧,也便于大家一起交流學習。 在這里重點寫下的是調試ECC這個功能。 使用的NAND FLASH芯片是K9F2G08U0C 芯片大小是2Gbit,也就是容量256MB。一塊64頁,一頁2K字節 一頁2048字節,其中,OOB區64字節。 當然,要能正常使用ECC功能,NAND_FLASH的讀寫正常是前提。這里不作介紹。要ST公司提供的例子里有NAND_FLASH的讀寫例子,一般可參照其配置再結合自己實際使用的NAND_FLASH芯片及電路設計修改。 保證了能正常讀寫頁功能,以及讀寫OOB區數據功能,即可繼續調試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個字節產生一個ECC數據,這樣,當這512字節里出錯有一位錯誤的時候,可以通過ECC來糾正。當然,如果錯了幾個位,就無法糾錯了。雖然當兩個位有錯,也知道,但不知道是哪兩個位出錯,也糾正不了。所以,只要關心怎么找出錯誤,通過ECC怎么糾錯。 FSMC的ECC支持每256字節,512字節,1024,。。。8192字節產生一個ECC數據。 調試時使用每512字節產生一個ECC功能。 當寫入512個字節時,產生一個ECC數據,然后,再讀512個字節的時候,也會產生一個ECC數據,通過這兩個數據相異或,產生一個ECC校驗結果,通過這個判斷結果,就可以分析出有沒有錯,錯在哪里,是錯哪一位。當然,知道哪一位錯了,也就可以糾正了。 現在具體以實際的NAND_FLASH為例。 K9F2G08U0C這個芯片雖然是每頁2048個字節,也就是4 個512字節。按理說直接使用每2048字節產生一個ECC即可校驗,這樣也方便一些。但因為實際使用中,是把這FLASH當作U盤來使用,并使用了fat32文件系統,將其作扇區處理了。一般扇區單位為512個字節。因此,這里就使用每512個字節產生一個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數據。 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個字節時候讀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數據,要在讀之前先失能下ECC功能,把ECC數據清零,再使用ECC,然后再讀或寫NAND_FLASH。再讀到相應的ECC。讀ECC后記得把ECC失能,以清空ECC數據。 這樣就可以讀到write_ecc了。當然,這個數據會讀到的是0,為什么呢,所以很多時候我們測試數據,都是用比較有規律的數據去測試,下面通過幾組數據,來解讀下這個ECC的數據分析 for(i=0;i<512;i++) { buffer[i]=0x11; } ECC: 0 512個字節里,都是0x11的話,ECC數據是0。然后改變其中某個字節的某個位,再去讀ECC看。 for(i=0;i<512;i++) { buffer[i]=0x11; } buffer [0]=0x10; ECC: 0x55555555 這是改了第一個字節的第一個位。(但習慣上從0開始比較習慣,改了第0個字節第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個字節的最高位,也就是512個字節里的最高一個位) 好了,有了以上這里數據,就可以開始解讀了,就算找不到例子,只要你的NAND_FLASH讀寫正常了,能把這些看懂了,也就可以使用ECC功能了。 下面對這幾個ECC數據進行解讀。 解讀前先看一下ECC結果寄存器。
因為我們設置的是512個字節產生一個ECC。那么有效位是0到23。 也就是前面讀到的ECC數據呢,只要低24位就可以了。 當然,從這里還能看出其它數據。最高是8192字節,占了32位, 4096字節占了30位。 這個規律就是從256字節開始,每增一倍字節數,ECC就多占用兩個位。 按常理說,只要多一個位,就可以表示多一倍的數據了。但是要表示多一個數據,需要到兩個位,那,這里就有點玄機了。 甚至不需要去理解或弄明白它使用是漢明碼,什么BCH碼,只要看明白下這里,一直可以糾錯。因為,不要管它是什么糾錯碼,就跟著這個規律去理解。 512個字節的ECC用了24位,512個字節共有512*8=4096個位。要表示到4096個數,也就是剛好12位就可以了。所以,因此這里的玄機就是ECC數據里,用了2個位來表示一個位的數據。 這時,再看一下關于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. 忘了說,我們這些測試數據呢,是以寫入0x11為主,然后故意改錯某一個位,再讀出ECC。因為寫入全部的是0x11,因此寫入時產生的ECC是0x0。那么再將讀出來的ECC與0x0異或,得到的,也就是ECC校驗結果了。 當錯第0個位的時候,校驗結果是0x55555555。取低24位,也就是0x555555。 對應24位就是 010101010101010101010101 當錯第1個位的時候,校驗結果是0x555556(取低24位) 對應24位就是 010101010101010101010110 當錯第2個位對應的24位是: 010101010101010101011001 當錯第3個位對應的24位是: 010101010101010101011010 ………… 當錯第4095個位(也就是第511個字節的最高位) 校驗結果:0xaaaaaa。 對應24位是: 101010101010101010101010 看到這里,大家估計很容易看出來規律了。 第0個位錯誤的24位數據解碼出來12位就是:0000 00000000,也就是0x0,就是第0個位錯誤. 第1個位錯誤的24位數據解碼出來12位就是:0000 00000001,也就是0x1,就是第1個位錯誤. 第2個位錯誤的24位數據解碼出來12位就是:0000 00000010,也就是0x2,就是第2個位錯誤. 第3個位錯誤的24位數據解碼出來12位就是:0000 00000011,也就是0x3,就是第3個錯誤. 第4095個位錯誤的24位數據解碼出來12位就是:1111 11111111,也就是0xfff,就是第4095個位錯誤. 到了這一步,不知道有沒有明白糾正原理呢。當知道是哪一個是錯誤的了,剩下的就簡單了,就把錯誤的那一位把0變成1,或者把1變成0就行了。 可以寫成一個函數,ecc_data為校驗結果。 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; } 當然,如果校驗結果為0x00的時候,說明讀出來的數據是對的。不需要調用這個函數了。調用這個函數時,就可以返回錯誤的位置。 到此,ECC的功能就調試的差不多了。剩下的,就是把那一位糾錯出來就好了。重要的ECC校驗結果出來了,知道是哪一位錯誤了,剩下的還不好辦了。 對于NAND_FLASH呢,具體就可以這樣實現了。 一頁是2048個字節加OOB的64個字節。 OOB區一般是存放ECC數據,一般如果寫到跑系統的是,用設計ECC layout的。 這里就簡單作個layout吧。簡單地說,就是把ECC放在哪里。 因為這里每512個字節, 產生一個ECC,占4個字節。 第1 個512字節產生的ECC就放到OOB區里的0x10,0x11,x12,0x13這四個地址里。 第2 個512字節產生的ECC就放到OOB區里的0x14,0x15,x16,0x17這四個地址里。 第3 個512字節產生的ECC就放到OOB區里的0x18,0x19,x1a,0x1b這四個地址里。 第4 個512字節產生的ECC就放到OOB區里的0x1c,0x1d,x1e,0x1f這四個地址里。 這樣,ECC layout就算是設置好了。因此只要在寫入的時候,把ECC相應地存入到OOB區,然后在讀NAND_FLASH的時候,再讀新的ECC數據,和之前寫入到OOB里的ECC進行異或,得到ECC校驗結果。那,ECC的調試,就算告個段落了。 如果有錯誤之處,還請見諒。 特此寫下以便日后可以回顧,而且網上涉及的也比較少,寫出來也讓感興趣的人一起交流學習。 FSMC的使用手冊*(英文的),以及fsmc_nand.c的驅動測試ECC一同上傳到了我的CSDN里了,有需要可下載
STM32 ECC調試及心得.zip
(385.02 KB, 下載次數: 76)
2015-4-5 20:48 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|