|
一.簡介
本文介紹了如何調試nand flash
二. 背景
2.1.nandflash 結構分類
2.1.1 小頁
1block = 32page
1page = 512bytes(datafield) + 16bytes(Spare Field)
需要注意的是,對于flash的讀寫都是以一個page開始的,但是在讀寫之前必須進行flash的擦寫,而擦寫則是以一個block為單位的。同時必須提醒的是,512bytes理論上被分為1st half 和2sd half,每個half各占256個字節。
528個字節按順序由上而下以列為單位進行排列(1列代表一個Byte。第0行為第0 Byte ,第1行為第1 Byte,以此類推,每個行又由8個位組成,每個位表示1個Byte里面的1bit。
528Bytes按功能分為兩大部分,分別是Data Field和Spare Field,其中Spare Field占528Bytes里的16Bytes,這16Bytes是用于在讀寫操作的時候存放校驗碼用的,一般不用做普通數據的存儲區,除去這 16Bytes,剩下的512Bytes便是我們用于存放數據用的Data Field,所以一個Page上雖然有528個Bytes,但我們只按512Bytes進行容量的計算。
讀命令有兩個,分別是 Read1,Read2其中Read1用于讀取Data Field的數據,而Read2則是用于讀取Spare Field的數據。對于Nand Flash來說,讀操作的最小操作單位為Page,也就是說當我們給定了讀取的起始位置后,讀操作將從該位置開始,連續讀取到本Page的最后一個 Byte為止(可以包括Spare Field)

2.1.2 大頁
參考小頁的說明

2.2 NANDFLASH校驗
由于NAND Flash的工藝不能保證NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生產中及使用過程中會產生壞塊。為了檢測數據的可靠性,在應用NAND Flash的系統中一般都會采用一定的壞區管理策略,而管理壞區的前提是能比較可靠的進行壞區檢測。
如果操作時序和電路穩定性不存在問題的話,NAND Flash出錯的時候一般不會造成整個Block或是Page不能讀取或是全部出錯,而是整個Page(例如512Bytes)中只有一個或幾個bit出錯。
在NAND Flash處理中,一般使用一種比較專用的校驗——ECC。ECC能糾正單比特錯誤和檢測雙比特錯誤,而且計算速度很快,但對1比特以上的錯誤無法糾正,對2比特以上的錯誤不保證能檢測。
ECC一般每256字節原始數據生成3字節ECC校驗數據,這三字節共24比特分成兩部分:6比特的列校驗和16比特的行校驗,多余的兩個比特置1
當往NAND Flash的page中寫入數據的時候,每256字節我們生成一個ECC校驗和,稱之為原ECC校驗和,保存到PAGE的OOB(out-of-band)數據區中。
當從NAND Flash中讀取數據的時候,每256字節我們生成一個ECC校驗和,稱之為新ECC校驗和。
校驗的時候,根據上述ECC生成原理不難推斷:將從OOB區中讀出的原ECC校驗和新ECC校驗和按位異或,若結果為0,則表示不存在錯(或是出現了ECC無法檢測的錯誤);若3個字節異或結果中存在11個比特位為1,表示存在一個比特錯誤,且可糾正;若3個字節異或結果中只存在1個比特位為1,表示OOB區出錯;其他情況均表示出現了無法糾正的錯誤
2.3 NANDFLASH 壞塊管理
在進行數據存儲的時候,我們需要保證數據的完整性,而NAND Flash存儲器芯片由于工藝上問題,不可避免就會出現有的Block中就是某個位或某些位是塊的,就是用塊擦除命令也是無法擦除的。如果數據存儲到這個壞塊中,就無法保證該數據存儲的完整性。對于壞塊的管理首先我們要定義一個壞塊管理表:unsigned char BAD_BLOCK_TABLE [128],此數組可以存儲1024個Block狀態,即每一個字節存儲8個Block狀態。我們要存儲一批數據到NAND Flash中去某個Block時,先執行Block擦除操作,然后分析該Block的1st Page和2st Page中的每個位是否全是FFH,如果全是FFH,則在BadBlockTable數組當前Block對應的字節位給置0,否則置1。如果是1表示當前的塊是不能存儲數據的,這時需要更換下一個Block來存儲這些數據,這樣我們重復上面的動作分析再進行分析是否可以存儲數據,該塊能存儲就存儲到該塊中去。(詳見具體NANDFLASH 手冊)

2.4 DMA 傳送方式
NAND 控制器包含一個寬度為32 b,深度為4 的緩沖FIFO,用于解決高速總線與低速設備
之間數據傳輸速度的匹配問題。為提高總線的傳輸效率,以及控制器設計的便利性,NAND
FLASH 在總線上的數據傳輸采用DMA 的方式來完成。譬如在讀取FLASH 一頁數據時,數
據持續寫入控制器FIFO,FIFO 滿時發出DMA 傳輸的請求,同時暫停FLASH 的數據讀取,
控制信號nRE 拉高,直至DMA 響應請求即FIFO 不滿時,FLASH 的數據傳輸重新開始。
當選擇應用的FLASH 位寬為8,頁大小為(512+16)B 時,控制器需要發出(32+1)次4 拍字寬
度的DMA 傳輸請求來完成數據和校驗信息的讀取。
控制模塊的上作主要是將總線接口轉換的控制信號,按照NAND FLASH 的接口協議.將片
選、地址、命令、讀寫使能按照所配置的時序要求,發送到NAND FLASH 中,并且控制數
據的傳輸個數,以及DMA 請求、數據傳輸完成中斷、數據錯誤中斷等系統信號。
2.5 NANDFLASH 啟動
NANDFLASH 跟NOR FLASH有一個本質的區別就是NANDFLASH不能執行代碼,
而在SDRAM中執行程序,所以在系統的啟動過程中有步代碼從NANDFLASH中搬遷到SDRAM中的過程。隨后會在7120的實例中闡明。
二 調試T3G 7210 NANDFLASH
2.1 系統啟動
2.1.1 系統啟動流程圖
第一步:

說明:硬件的BOOTLOADER執行,執行的目的是把NANDFLASH第一個BLOCK中第一個 16kbytes 內容加載到SCRAM中去執行 相關模塊psboot
第二步:

說明:NAND Bootloader 加載到SCRAM中后執行,執行的目的根據分區表把相應分區的內容加載到SCRAM中執行 相關模塊psboot
第三步:

說明:執行Splashscreen 就是開機動畫,由于我們是模塊沒有屏幕這個模塊并沒有什么用,
可以把代碼屏蔽掉。
第四步:

說明:執行完開機動畫后,加載CODE區,開始執行代碼。
相關文件說明:
修改啟動這塊代碼我們只要關注psboot psstartup,具體修改文件如下:
psboot\modules\bootnand\srce\Rest.s
IF NAND_FLASH_512M_HDW
; 32-word ROM Boot loader parameter list
dcd 0x1234567 ; magic number causes NandFlash boot; 512M flash,
ELSE
dcd 0x1234576 ; magic number causes NandFlash boot
ENDIF
psboot\modules\bootnand\srce\ link.map
在實際的調試的過程中,發現在編譯bootnand這個模塊的時候ZI區會超RAM(請注意UNINIT 這個關鍵的屬性值),為了解決這個問題,需要去掉link.map中相應的幾個字段。
# BUFFER1 0x8000 UNINIT 0x8000
# {
# bootnand.o (buffer1)
# }
# BUFFER2 0x10000 UNINIT 0x8000
# {
# bootnand.o (buffer2)
# }
psboot\modules\bootnand\output\Makefile
BLOCK_SIZE = 16384
psstartup\modules\conf\incl\ config_bootnand.h
#define NANDFLASH_PAGE_SIZE 512
#define NANDFLASH_SPARE_SIZE 16
#define NANDFLASH_PAGES_PER_BLOCK 32
#define NANDFLASH_N_BLOCKS 4096
上面是設置 NANDFLASH的頁與塊,這也是大頁換小頁第一個需要改的。
#define NANDFLASH_READ_COMMAND_2_P 0
這個宏的定義跟讀NANDFLASH發的指令有關,大家可以在代碼中搜一下就一目了然了。
修改如下函數 這個跟NANDFLASH的地址線有關,修改時可用查看一下NANDFLASH手冊
static __inline void
platform_page_address (int page, unsigned char address [])
{
#ifdef NAND_FLASH_512M_HDW
address [0] = 0;
address [1] = (unsigned char) ((unsigned) page & 0xff);
address [2] = (unsigned char) (((unsigned) page >> 8) & 0xff);
address [3] = (unsigned char) (((unsigned) page >> 16) & 0x01);
#else
address [0] = 0;
address [1] = 0;
address [2] = (unsigned char) ((unsigned) page & 0xff);
address [3] = (unsigned char) (((unsigned) page >> 8) & 0xff);
#endif
}
到現在為止BOOTNAND應該可以正常運行了,不過要讓系統的正常運行還需要修改一些文件
下面一一道來。
Pstffs\modules\dntf\incl\dntf.hec
#ifdef NAND_FLASH_512M_HDW
#define NAND_PAGE_SIZE 512
#define NAND_SPARE_SIZE 16
#define NAND_ECC_SIZE 10 //original: 10, fxj,
#define NAND_PAGES_PER_BLOCK 32
#define NAND_BLOCK_SIZE (NAND_PAGE_SIZE * NAND_PAGES_PER_BLOCK)
#define NAND_NUM_BLOCKS 200 //original 100, fxj,
#define NAND_MIN_VALID_BLOCKS 15
#define NAND_MAX_BAD_BLOCKS (NAND_NUM_BLOCKS / 10 ) // 10% of size
#else
#define NAND_PAGE_SIZE 2048
#define NAND_SPARE_SIZE 64
#define NAND_ECC_SIZE 10
#define NAND_PAGES_PER_BLOCK 64
#define NAND_BLOCK_SIZE (NAND_PAGE_SIZE * NAND_PAGES_PER_BLOCK)
#define NAND_NUM_BLOCKS 100
#define NAND_MIN_VALID_BLOCKS 15
#define NAND_MAX_BAD_BLOCKS (NAND_NUM_BLOCKS / 10 ) // 10% of size
#endif
注意:這個宏跟NXP的mgrpaging 這個庫文件有直接關系,而我們沒有這個庫的原文件,所以這宏的修改基本來說是沒有用的,需要NXP的支持。
Pstffs\modules\tffsal\input\dntfecc.c
#ifdef NAND_FLASH_512M_HDW
/** The number of bits in ECCs generated by the NFI */
#define NFI_ECC_BITS 22
#define NFI_ECC_CHUNK_SIZE 0x100
#define NAND_FLASH_PAGE_BYTES 0x200
#else
/** The number of bits in ECCs generated by the NFI */
#define NFI_ECC_BITS 22
#define NFI_ECC_CHUNK_SIZE 0x100
#define NAND_FLASH_PAGE_BYTES 0x800
#endif
修改各OPT中的宏定義。
-DNAND_FLASH_PAGE_BYTES
-DNAND_FLASH_SPARE_BYTES
-DNAND_FLASH_BLOCK_BYTES
-DNAND_FLASH_BLOCKS
-DNAND_FLASH_FS_BASE
-DNAND_FLASH_FS_MEM_BASE
-DNAND_FLASH_FS_BLOCKS
添加相應NANDFLASH處理文件,需要填充的幾個結構:
llinit_katSDIReConfTab
llinit_katSDIInitTab
llinit_katNFIInitTab
llinit_NFICmd_Config
llinit_NFIDesConf
修改ECC的算法
compute_page_ecc
原為:for(j=0; j<8; j++) //8個256 大頁
改為:for(j=0; j<2; j++) // 2個256 小頁
到現在為止,NANDFLASH的驅動也完成,接下來就是文件系統的配置了,主要關注
vman5cfg.c 這個文件
需要注意三個宏:
#define BBM_RESERVED 88 壞塊的預留BLOCK數
MC_VOLMAN_ADD_DEVICE 添加分區
MC_VOLMAN_ADD_VOLUME 在相應分區上添加根目錄
T3G7210分為2個分區,3個跟目錄
NANDFLASH 包含 sysv app
FTL_NAND 包含 share
|
|