Windows下u-boot-2011.03在Mini2440移植詳解(5)

增加Nand Flash ECC的支持

又參考了網址http://blog.csdn.net/fulinus/article/details/8737129

修改相關文件:

1.      u-boot-2011.03\drivers\mtd\nand\s3c2440_nand.c

2.      u-boot-2011.03\include\configs\mini2440.h

 

一開始一直不能確定的是:nand->ecc.size 和nand->ecc.bytes到底是多少?板子上帶的Nand Flash是:K9F1208U0B:64MB,8位。1頁包含512字節的main數據區和16字節的spare數據區。main區用於存儲數據,spare區用於存儲其它附加信息。S3C2440一次可以產生4個字節的ECC,對於K9F1208U0B,頁大小是512字節的nand flash,只要讀取1頁(512字節)就產生4個字節的main區ECC。對於頁是2048字節的nand flash,同樣也是讀取1頁(2048字節)就產生4字節的ECC。參考網址,將nand->ecc.size=512,nand->ecc.bytes=4。

@2014-04-26:關於產生ECC字節數之前的誤解:

S3C2440到底讀/寫一頁數據上產生多少個字節的mainECC和多少個字節的spareECC,是和Nand Flash的位數關聯的。如果Nand Flash8位的,那麼一頁產生4字節的MainECC(NFMECC0寄存器裏)2個字節的spareECC(NFSECC寄存器的低16),如果Nand Flash16位的,那麼一頁產生8個字節的MainECC(NFMECC0NFMECC1寄存器裏)4個字節的spareECC(NFSECC寄存器裏)。但是目前我們並沒有是spare區的ECC碼。

如下圖(摘自S3C2440A datasheet)



關於怎麼產生ECC

在S3C2440數據手冊第6章有這麼一段。


產生ECC校驗碼的過程爲:在讀取或寫入哪個區的數據之前,先解鎖該區的ECC,以便產生該區的ECC。在讀取或寫入數據之後,再鎖定該區的ECC,這樣系統就會把產生的ECC碼保存到相應的寄存器中。

以主數據區域爲例:解鎖ECC,將NFCONT中第5位MainECCLock置0。鎖定ECC,將NFCONT中第5位MainECCLock置1。

當讀或寫數據時,自動產生的ECC校驗在寄存器NFMECC0/1中。

ECC校驗可以糾正1個比特的錯誤和檢測2個比特的錯誤。

關於出現1位錯誤根據下圖校正


1.      先計算哪個數據出錯:(NFESTAT0>>7) & 0x7ff;

2.      再計算哪個位出錯:(NFESTAT0>>4) & 0x7;

3.      校正:我們知道,1位出錯,要麼是0變1,要麼是1變0。用1與這位異或即可。

Repaired = Data[(NFESTAT0>>7)& 0x7ff] ^ (1<<((NFESTAT0>>4) & 0x7));

測試:

調試運行後的串口輸出如下圖:


讀參數時報了一個-74的錯誤,應該就是ECC校驗不過的原因。具體還沒有去查。下面還有一個warning。在串口中輸入saveenv,然後再次調試運行,如下圖。這時候沒有報上圖的錯誤了。


查看參數0x80000的nand flash值,發現oob的前4個字節已經與之前的不同了。其中0x80000是在mini2440.h文件內定義的nand flash 參數起始地址。nand dump命令並不會去進行數據的ECC校驗檢測,只是讀取數據,這區別與下面的nand read命令


當執行:nand read 0x31100000 0x80000 0x200時,程序會調用到這裏,在文件drivers/mtd/nand/nand_base.c,函數nand_read_page_hwecc。如下圖:


根據上圖可做函數簡要說明:

staticint s3c2440_nand_calculate_ecc(structmtd_info *mtd, const u_char *dat,

                                  u_char *ecc_code)

當讀或寫完一頁後,調用該函數,讀取NFMECC0寄存器,就可以將該頁main區的ECC校驗碼取出。參考源碼

其中,u_char *ecc_code就是存取讀取的ECC校驗碼

staticint s3c2440_nand_correct_data(structmtd_info *mtd, u_char *dat,

                                 u_char *read_ecc, u_char *calc_ecc)

該函數用來比較read_ecc和calc_ecc的校驗是否相等的。

其中,read_ecc是在spare區讀出來的ECC校驗值。

      calc_ecc是讀完1頁後自動產生的ECC校驗值。針對main區的ECC校驗碼,此值同樣存在於NFMECC0寄存器內。

但是在該函數中並沒有直接去比較read_ecc和calc_ecc,而是將read_ecc的值寫入NFMECCD0和NFMECCD1,用硬件去比較,然後讀取寄存器NFSTAT的值來判斷。

其實直接比較read_ecc和calc_ecc,也是可以的,有的移植就是直接比較的。


本部分代碼下載地址:360雲盤http://yunpan.360.cn/,在《Uboot相關代碼》文件夾裏的《u-boot-2011.03_SRAM調試.zip》文件。

《u-boot-2011.03源碼無修改.tar.bz2》是從官網下的無修改代碼


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章