目前市場(chǎng)上閃存芯片主要有兩類,,即NAND Flash(Not And Flash ROM)和NOR Flash(Not Or Flash ROM),。前者具有容量大、讀寫速度快,、芯片面積小,、單元密度高、擦除速度快,、成本低等特點(diǎn),,更適合于大批量數(shù)據(jù)存儲(chǔ)的嵌入式" title="嵌入式">嵌入式系統(tǒng)。如今Windows仍是桌面系統(tǒng)的主流,,對(duì)FAT文件系統(tǒng)" title="文件系統(tǒng)">文件系統(tǒng)提供了天然的支持,。然而就技術(shù)而言,F(xiàn)AT文件系統(tǒng)并不適合Flash,,因?yàn)镕lash設(shè)備并不是塊設(shè)備[1],,為了不破壞兼容性,并在NAND型閃存中應(yīng)用FAT文件系統(tǒng),,國(guó)際上提出了閃存轉(zhuǎn)譯層FTL(Flash Translation Layer)的解決方案,。
1 NAND Flash嵌入式存儲(chǔ)系統(tǒng)結(jié)構(gòu)
基于NAND Flash的存儲(chǔ)系統(tǒng)的設(shè)計(jì)首先要解決壞塊問題。由于NAND Flash自身存在固有壞塊并在擦除和編程中又隨機(jī)產(chǎn)生壞塊,,因此為了提高設(shè)備的可靠性應(yīng)該將這兩種操作分散在閃存不同的塊中,,以避免對(duì)某塊的過度操作。
一般的基于NAND Flash嵌入式存儲(chǔ)系統(tǒng)驅(qū)動(dòng)結(jié)構(gòu)分為三個(gè)層次:最底層是硬件操作接口,,負(fù)責(zé)將主控芯片與Flash的控制管腳相連,,這方面的固件" title="固件">固件主要實(shí)現(xiàn)對(duì)NAND Flash的物理操作;中間層是閃存轉(zhuǎn)譯層NFTL(NAND FTL),,是封裝在Flash驅(qū)動(dòng)中的軟件模塊,,其作用是將Flash模擬成與磁盤相類似的塊設(shè)備,使對(duì)上層操作系統(tǒng)而言,,NAND Flash就像普通磁盤一樣被訪問,。這一層主要是封裝一些特殊的復(fù)雜管理控制功能;最上面的層就是文件管理層,,功能類似于普通磁盤上的通用文件系統(tǒng),,向上層提供標(biāo)準(zhǔn)的文件操作接口,。基于NAND Flash的嵌入式系統(tǒng)存儲(chǔ)結(jié)構(gòu)原理圖如圖1所示,。
根據(jù)以上兩個(gè)方面,,既要在驅(qū)動(dòng)中實(shí)現(xiàn)壞塊管理,又要進(jìn)行塊模擬,,所以可用的方法有兩種[2]:一是在上層文件系統(tǒng)中解決壞塊問題,,驅(qū)動(dòng)層只實(shí)現(xiàn)本身的功能,文件系統(tǒng)為驅(qū)動(dòng)層提供不變的接口,,為上層應(yīng)用程序提供可靠透明的服務(wù),。這種方法較簡(jiǎn)單,開發(fā)周期比較短,,但只對(duì)特定應(yīng)用的嵌入式系統(tǒng)有很強(qiáng)的適應(yīng)性,;第二種方法是在驅(qū)動(dòng)層的NFTL中解決壞塊問題,將不可靠的NAND Flash虛擬成可靠的存儲(chǔ)設(shè)備,,為上層文件系統(tǒng)提供可靠透明服務(wù),,這種方法較第一種更復(fù)雜,但是此法具有較強(qiáng)的可移植性并能徹底斷絕與文件系統(tǒng)的聯(lián)系,,其他文件系統(tǒng)也同樣適用,。
本文是以Samsung的NAND Flash K9F2808U0C作為存儲(chǔ)芯片,設(shè)計(jì)了一種在NFTL上實(shí)現(xiàn)壞塊管理并且實(shí)現(xiàn)連續(xù)數(shù)據(jù)讀取的方法,。
2 設(shè)計(jì)思想
2.1 閃存空間劃分
K9F2808U0C是16 MB×8 bit的NAND Flash,,共有1 024個(gè)Block,1 Block=16 KB,,32 Page/Block,,1 Page=528 B=(512 B+16 B),其中16 B為備用區(qū),,主要存放NAND Flash出廠壞塊標(biāo)記,、ECC校驗(yàn)碼以及用戶自定義區(qū)。K9F2808U0C地址空間是24 bit,,分三個(gè)周期依次送入NAND Flash的地址鎖存器,。本文使用的地址均為字節(jié)地址,數(shù)據(jù)類型為DWORD(4 B),。
將K9F2808U0C的存儲(chǔ)空間劃分為四個(gè)區(qū):壞塊映射表存放區(qū),、交換塊區(qū)、壞塊映射區(qū)和實(shí)際數(shù)據(jù)存放區(qū),。文件系統(tǒng)管理的空間就是實(shí)際的數(shù)據(jù)存放空間,,如圖2所示。
2.2 各分區(qū)宏定義
#define FLASH_BLOCK_SIZE 0x40000 //16 KB/Block
#define FLASH_PAGE_SIZE 0x200 //512 B/Page
#define FLASH_SECTOR_SIZE 0x200
//1Page=1Sector(only K9F2808U0C)
#define FLASH_BLOCKS_TABLE 3//壞塊映射表存放塊數(shù)
#define FLASH_SWAP_BLOCKS 5 //交換區(qū)的塊數(shù)
#define FLASH_BAD_BLOCKS_REMAP 50
//壞簇重映區(qū)的塊數(shù)
#define FLASH_MAX_ADDR 0xFFFFFF
//Flash最大字節(jié)地址
各分區(qū)首地址計(jì)算公式:
FLASH_BLOCK_TABLE_ADDR=FLASH_MAX_ADDR+
1-3*FLASH_BLOCK_SIZE);
FLASH_SWAP_BLOCK_ADDR=(FLASH_BLOCK_
TABLE_ADDR-5*FLASH_BLOCK_SIZE);
FLASH_BAD_BLOCK_REMAP_ADDR=(FLASH_SWAP_
BLOCK_ADDR-50*FLASH_BLOCK_SIZE);
FLASH_MAX_SECTOR_ADDR=(FLASH_MAX_ADDR-
3*FLASH_BLOCK_TABLE_ADDR-5*FLASH_SWAP_
BLOCK_ADDR-50*FLASH_BAD_BLOCK_REMAP_ADDR),;
文件系統(tǒng)管理的最大字節(jié)地址,。
任意地址Addr:
所在塊地址:Addr&(~(FLASH_BLOCK_SIZE-1));
塊內(nèi)偏移地址:Addr&(FLASH_BLOCK_SIZE-1);
塊中的頁:(Addr&(FLASH_BLOCK_SIZE-1))/FLASH_
PAGE_SIZE;
2.3 分區(qū)功能設(shè)計(jì)
壞塊映射區(qū)存放復(fù)制3份的壞塊信息BBI(Bad Block Information)表,。復(fù)制3份是預(yù)防系統(tǒng)突然斷電,,造成BBI表數(shù)據(jù)丟失。選擇最后3個(gè)塊,,主要是出于固件設(shè)計(jì),。當(dāng)Flash首次上電,固件程序通過讀取Flash ID,,獲得設(shè)備的容量等信息,,然后從Flash的最后一塊中尋找BBI表,,如果最后一塊沒有發(fā)現(xiàn)BBI表,,則認(rèn)為此塊為壞塊,繼續(xù)前移尋找,,依此類推,,直到在預(yù)留的3個(gè)塊中找到,并將其數(shù)據(jù)讀入到在主控芯片為其開設(shè)的RAM中,。如果還找不到,,則固件認(rèn)為該片F(xiàn)lash沒有BBI表。
交換塊區(qū)是對(duì)NAND Flash進(jìn)行擦除或?qū)懖僮鲿r(shí)用來臨時(shí)存放數(shù)據(jù),,共分配5個(gè)塊,。選取5塊是出于可靠性設(shè)計(jì)。用一個(gè)數(shù)組FlashSwapBlockStatus[FLASH_SWAP_BLOCKS]記錄交換塊狀態(tài):有效還是已經(jīng)損壞,。初始化時(shí),,固件認(rèn)為所有的交換塊都是有效塊,在隨后對(duì)其進(jìn)行擦除或?qū)懖僮鲿r(shí),,通過讀Flash狀態(tài)寄存器判斷該交換塊的真實(shí)狀態(tài),,并記錄在數(shù)組中。交換塊的管理圍繞固件請(qǐng)求返回當(dāng)前可用交換塊地址或當(dāng)前正在使用的交換塊地址,,并判斷標(biāo)記當(dāng)前使用的交換塊狀態(tài)為壞,。
壞塊映射區(qū)是當(dāng)主機(jī)向數(shù)據(jù)區(qū)寫數(shù)據(jù)時(shí),檢測(cè)到當(dāng)前塊(數(shù)據(jù)區(qū))為壞塊時(shí),,將數(shù)據(jù)寫到壞塊映射區(qū)中的相應(yīng)好塊中,,并且將這兩個(gè)塊的塊地址記錄到BBI表中,以后主機(jī)若要對(duì)當(dāng)前塊(數(shù)據(jù)區(qū))訪問時(shí),,只需讀BBI表就可以找到相應(yīng)映射塊,,從而代替壞塊的訪問。這樣就使文件系統(tǒng)所見邏輯塊地址LBA(Logical Block Address)變成連續(xù)的,但實(shí)際上物理塊地址PBA(Physical Block Address)可能并不連續(xù),。上述方法就是壞塊管理的精髓,。出于保守設(shè)計(jì)本文共選50塊作為重映塊。用數(shù)組FlashRemapBlockStatus[FLASH_BAD_BLOCKS_REMAP]標(biāo)識(shí)壞塊映射區(qū)的狀態(tài):未使用,、已使用還是已經(jīng)損壞,。初始化時(shí)認(rèn)為壞塊映射區(qū)中所有塊都是好塊。
目前市場(chǎng)上閃存芯片主要有兩類,,即NAND Flash(Not And Flash ROM)和NOR Flash(Not Or Flash ROM),。前者具有容量大、讀寫速度快,、芯片面積小,、單元密度高、擦除速度快,、成本低等特點(diǎn),,更適合于大批量數(shù)據(jù)存儲(chǔ)的嵌入式系統(tǒng)。如今Windows仍是桌面系統(tǒng)的主流,,對(duì)FAT文件系統(tǒng)提供了天然的支持,。然而就技術(shù)而言,F(xiàn)AT文件系統(tǒng)并不適合Flash,,因?yàn)镕lash設(shè)備并不是塊設(shè)備[1],,為了不破壞兼容性,并在NAND型閃存中應(yīng)用FAT文件系統(tǒng),,國(guó)際上提出了閃存轉(zhuǎn)譯層FTL(Flash Translation Layer)的解決方案,。
1 NAND Flash嵌入式存儲(chǔ)系統(tǒng)結(jié)構(gòu)
基于NAND Flash的存儲(chǔ)系統(tǒng)的設(shè)計(jì)首先要解決壞塊問題。由于NAND Flash自身存在固有壞塊并在擦除和編程中又隨機(jī)產(chǎn)生壞塊,,因此為了提高設(shè)備的可靠性應(yīng)該將這兩種操作分散在閃存不同的塊中,,以避免對(duì)某塊的過度操作。
一般的基于NAND Flash嵌入式存儲(chǔ)系統(tǒng)驅(qū)動(dòng)結(jié)構(gòu)分為三個(gè)層次:最底層是硬件操作接口,,負(fù)責(zé)將主控芯片與Flash的控制管腳相連,,這方面的固件主要實(shí)現(xiàn)對(duì)NAND Flash的物理操作;中間層是閃存轉(zhuǎn)譯層NFTL(NAND FTL),,是封裝在Flash驅(qū)動(dòng)中的軟件模塊,,其作用是將Flash模擬成與磁盤相類似的塊設(shè)備,使對(duì)上層操作系統(tǒng)而言,,NAND Flash就像普通磁盤一樣被訪問,。這一層主要是封裝一些特殊的復(fù)雜管理控制功能;最上面的層就是文件管理層,,功能類似于普通磁盤上的通用文件系統(tǒng),,向上層提供標(biāo)準(zhǔn)的文件操作接口,。基于NAND Flash的嵌入式系統(tǒng)存儲(chǔ)結(jié)構(gòu)原理圖如圖1所示,。
根據(jù)以上兩個(gè)方面,,既要在驅(qū)動(dòng)中實(shí)現(xiàn)壞塊管理,又要進(jìn)行塊模擬,,所以可用的方法有兩種[2]:一是在上層文件系統(tǒng)中解決壞塊問題,,驅(qū)動(dòng)層只實(shí)現(xiàn)本身的功能,文件系統(tǒng)為驅(qū)動(dòng)層提供不變的接口,,為上層應(yīng)用程序提供可靠透明的服務(wù),。這種方法較簡(jiǎn)單,開發(fā)周期比較短,,但只對(duì)特定應(yīng)用的嵌入式系統(tǒng)有很強(qiáng)的適應(yīng)性,;第二種方法是在驅(qū)動(dòng)層的NFTL中解決壞塊問題,將不可靠的NAND Flash虛擬成可靠的存儲(chǔ)設(shè)備,,為上層文件系統(tǒng)提供可靠透明服務(wù),,這種方法較第一種更復(fù)雜,但是此法具有較強(qiáng)的可移植性并能徹底斷絕與文件系統(tǒng)的聯(lián)系,,其他文件系統(tǒng)也同樣適用,。
本文是以Samsung的NAND Flash K9F2808U0C作為存儲(chǔ)芯片,,設(shè)計(jì)了一種在NFTL上實(shí)現(xiàn)壞塊管理并且實(shí)現(xiàn)連續(xù)數(shù)據(jù)讀取的方法,。
2 設(shè)計(jì)思想
2.1 閃存空間劃分
K9F2808U0C是16 MB×8 bit的NAND Flash,共有1 024個(gè)Block,,1 Block=16 KB,,32 Page/Block,1 Page=528 B=(512 B+16 B),,其中16 B為備用區(qū),,主要存放NAND Flash出廠壞塊標(biāo)記、ECC校驗(yàn)碼以及用戶自定義區(qū),。K9F2808U0C地址空間是24 bit,,分三個(gè)周期依次送入NAND Flash的地址鎖存器。本文使用的地址均為字節(jié)地址,,數(shù)據(jù)類型為DWORD(4 B),。
將K9F2808U0C的存儲(chǔ)空間劃分為四個(gè)區(qū):壞塊映射表存放區(qū)、交換塊區(qū),、壞塊映射區(qū)和實(shí)際數(shù)據(jù)存放區(qū),。文件系統(tǒng)管理的空間就是實(shí)際的數(shù)據(jù)存放空間,如圖2所示,。
2.2 各分區(qū)宏定義
#define FLASH_BLOCK_SIZE 0x40000 //16 KB/Block
#define FLASH_PAGE_SIZE 0x200 //512 B/Page
#define FLASH_SECTOR_SIZE 0x200
//1Page=1Sector(only K9F2808U0C)
#define FLASH_BLOCKS_TABLE 3//壞塊映射表存放塊數(shù)
#define FLASH_SWAP_BLOCKS 5 //交換區(qū)的塊數(shù)
#define FLASH_BAD_BLOCKS_REMAP 50
//壞簇重映區(qū)的塊數(shù)
#define FLASH_MAX_ADDR 0xFFFFFF
//Flash最大字節(jié)地址
各分區(qū)首地址計(jì)算公式:
FLASH_BLOCK_TABLE_ADDR=FLASH_MAX_ADDR+
1-3*FLASH_BLOCK_SIZE),;
FLASH_SWAP_BLOCK_ADDR=(FLASH_BLOCK_
TABLE_ADDR-5*FLASH_BLOCK_SIZE);
FLASH_BAD_BLOCK_REMAP_ADDR=(FLASH_SWAP_
BLOCK_ADDR-50*FLASH_BLOCK_SIZE);
FLASH_MAX_SECTOR_ADDR=(FLASH_MAX_ADDR-
3*FLASH_BLOCK_TABLE_ADDR-5*FLASH_SWAP_
BLOCK_ADDR-50*FLASH_BAD_BLOCK_REMAP_ADDR),;
文件系統(tǒng)管理的最大字節(jié)地址。
任意地址Addr:
所在塊地址:Addr&(~(FLASH_BLOCK_SIZE-1));
塊內(nèi)偏移地址:Addr&(FLASH_BLOCK_SIZE-1);
塊中的頁:(Addr&(FLASH_BLOCK_SIZE-1))/FLASH_
PAGE_SIZE,;
2.3 分區(qū)功能設(shè)計(jì)
壞塊映射區(qū)存放復(fù)制3份的壞塊信息BBI(Bad Block Information)表,。復(fù)制3份是預(yù)防系統(tǒng)突然斷電,造成BBI表數(shù)據(jù)丟失,。選擇最后3個(gè)塊,,主要是出于固件設(shè)計(jì)。當(dāng)Flash首次上電,,固件程序通過讀取Flash ID,,獲得設(shè)備的容量等信息,然后從Flash的最后一塊中尋找BBI表,,如果最后一塊沒有發(fā)現(xiàn)BBI表,,則認(rèn)為此塊為壞塊,繼續(xù)前移尋找,,依此類推,,直到在預(yù)留的3個(gè)塊中找到,并將其數(shù)據(jù)讀入到在主控芯片為其開設(shè)的RAM中,。如果還找不到,,則固件認(rèn)為該片F(xiàn)lash沒有BBI表。
交換塊區(qū)是對(duì)NAND Flash進(jìn)行擦除或?qū)懖僮鲿r(shí)用來臨時(shí)存放數(shù)據(jù),,共分配5個(gè)塊,。選取5塊是出于可靠性設(shè)計(jì)。用一個(gè)數(shù)組FlashSwapBlockStatus[FLASH_SWAP_BLOCKS]記錄交換塊狀態(tài):有效還是已經(jīng)損壞,。初始化時(shí),,固件認(rèn)為所有的交換塊都是有效塊,在隨后對(duì)其進(jìn)行擦除或?qū)懖僮鲿r(shí),,通過讀Flash狀態(tài)寄存器判斷該交換塊的真實(shí)狀態(tài),,并記錄在數(shù)組中。交換塊的管理圍繞固件請(qǐng)求返回當(dāng)前可用交換塊地址或當(dāng)前正在使用的交換塊地址,,并判斷標(biāo)記當(dāng)前使用的交換塊狀態(tài)為壞,。
壞塊映射區(qū)是當(dāng)主機(jī)向數(shù)據(jù)區(qū)寫數(shù)據(jù)時(shí),檢測(cè)到當(dāng)前塊(數(shù)據(jù)區(qū))為壞塊時(shí),,將數(shù)據(jù)寫到壞塊映射區(qū)中的相應(yīng)好塊中,,并且將這兩個(gè)塊的塊地址記錄到BBI表中,以后主機(jī)若要對(duì)當(dāng)前塊(數(shù)據(jù)區(qū))訪問時(shí),,只需讀BBI表就可以找到相應(yīng)映射塊,,從而代替壞塊的訪問。這樣就使文件系統(tǒng)所見邏輯塊地址LBA(Logical Block Address)變成連續(xù)的,,但實(shí)際上物理塊地址PBA(Physical Block Address)可能并不連續(xù),。上述方法就是壞塊管理的精髓,。出于保守設(shè)計(jì)本文共選50塊作為重映塊。用數(shù)組FlashRemapBlockStatus[FLASH_BAD_BLOCKS_REMAP]標(biāo)識(shí)壞塊映射區(qū)的狀態(tài):未使用,、已使用還是已經(jīng)損壞,。初始化時(shí)認(rèn)為壞塊映射區(qū)中所有塊都是好塊。