WinCE NAND flash - FAL
http://blog.csdn.net/renpine/article/details/4572347
http://msdn.microsoft.com/en-US/library/ee482032(v=winembedded.60).aspx
WinCE NAND flash - FAL
From ESSLabWiki
1.?Introduction
Flash與一般常見的Disk不同,其特性是無(wú)法重複對(duì)同一塊記憶體位置去做Write的動(dòng)作,必須要Erase那塊記憶體位置才可以做Write的動(dòng)作。因此一般的File System,如FAT16、FAT32、NFTS…,無(wú)法直接在Flash Memory上使用;若是想要沿用這些File System,則必須透過(guò)一層Translation Layer來(lái)將Logical Block Address對(duì)應(yīng)到實(shí)體的Flash Memory的位置,並透過(guò)一些機(jī)制能讓系統(tǒng)能把Flash Memory當(dāng)作一般的硬碟一樣處理,在Win CE的平臺(tái)上,我們稱這層為FTL(Flash Translation Layer)。
FTL最原始的應(yīng)用,為使用於NOR Flash,然而目前的市場(chǎng)價(jià)格,大容量的NOR Flash的成本,遠(yuǎn)高於同樣容量的NAND flash ,因此有NFTL(NAND Flash Translation Layer)的產(chǎn)生,NFTL主要想法與FTL相似,主要差別在於是用在NAND Flash上。
Figure 1. Architecture
本文件將介紹WinCE6.0在與Flash相關(guān)的Data structure、RAM上的Data structure,以及Win CE如何在Flash作Garbage Collection、Wear-Leveling,最後說(shuō)明如何在Win CE的基本系統(tǒng)上,註冊(cè)一個(gè)Flash Device。
2.?System Architecture
下圖為Windows CE 平臺(tái)中,Flash Memory驅(qū)動(dòng)的系統(tǒng)架構(gòu)
Figure 2. Flash Architecture
先對(duì)本篇的重點(diǎn):FAL及FMD做基本定義的說(shuō)明如下:
FMD(FLASH Media Driver)可針對(duì)特定廠商的Flash作Driven、Read、Write、Erase等動(dòng)作,實(shí)際去對(duì)Flash做讀寫的操作。
FAL(FLASH Abstraction Layer):File System對(duì)Flash讀寫,必須透過(guò)此層操作。而此層則再根據(jù)FMD所提供的Interface再對(duì)Flash做讀寫。
參考Figure 1再來(lái)看此圖的行為;File System為了對(duì)Flash操作,必須透過(guò)FAL對(duì)FMD(Driver)做操作。因此面對(duì)各家Flash來(lái)說(shuō),只需修改FMD即可,而不用再行修改 FAL的Interface即可對(duì)Flash做Read、Write、Erase等基本的操作。因此可得到一個(gè)結(jié)論,若是有一個(gè)產(chǎn)品裡的Flash換成了另一廠商的,因Flash對(duì)FAL的interface是一致的,那麼只要抽換FMD則其它的程式都不用再修改即可使用。
那麼FMD對(duì)FAL所提供的interface及其作用後面會(huì)再詳細(xì)說(shuō)明,此處便不再贅述。
FAL存在兩個(gè)Table(DLUT、Secondary Table)以提供Translation的動(dòng)作,其中也存在兩條List一個(gè)存Free Sector,一個(gè)存Dirty Block來(lái)分別提供Free Sector以及可幫助Garbage Collection的作用,詳細(xì)的流程及使用後續(xù)會(huì)再行說(shuō)明。
3.?Terminology
以下說(shuō)明一些在本篇會(huì)出現(xiàn)的基本名詞及其定義
在Flash中可能會(huì)有多個(gè)Region,在實(shí)體上會(huì)如下圖:
Figure 3. Region at Flash
而Region中會(huì)存有多個(gè)Block,其示意圖如下:
Figure 4. Block at Region
而Block中也有多個(gè)Sector,其示意圖如下:
Figure 5. Sector at Block
但這裡要注意的是,Win CE是採(cǎi)用Sector Mapping的方式,因此取Block動(dòng)作時(shí),必須依所給的Sector Address算出它是屬於那一個(gè)Block。
這裡再說(shuō)明它在各Term的情況:
對(duì)Region而言,它只紀(jì)錄了它有多少個(gè)Block,且一個(gè)Block有多少個(gè)Sector。
對(duì)Block而言,它的起始位置就是第一個(gè)Sector(以Figure 5來(lái)看,就是Sector 1)。但是這裡要說(shuō)明一下Block裡面是如何去算它第一個(gè)Sector的位置。假設(shè)一個(gè)Block中有10個(gè)Sector,那麼下一個(gè)Block的第一個(gè)Sector就是Sector 11。
對(duì)File System而言,所看到的Sector Address都是Logical Address;當(dāng)File System想取一個(gè)在Flash上的資料,必須要給FAL那個(gè)資料的Logical Address,而FAL要去取所需的資料,需根據(jù)Logical Address解析是位於Mapping Table的位置,再依據(jù)Table中的位置取出Physical Address,再交由FMD去取出在Flash上的Data;FAL再將取得的Data交給送出Request的System。這中間更詳細(xì)的細(xì)節(jié),後面章節(jié)會(huì)再解釋。
4.?Address Translation
一個(gè)Logical Address要如何快速找到Physical Address,靠的就是Mapping Table。有了這個(gè)就可以很方便且快速的找到所需的Address(Sector)。本段要介紹如何Create Mapping Table以及如何Mapping。
4.1 In-RAM Data Structures
PUCHAR m_pDynamicLUT[MASTER_TABLE_SIZE]; DWORD m_cbPhysicalAddr;
BOOL m_bIsNumSectorsPerSecTableLog2;
DWORD m_dwNumSectorsPerSecTable;
DWORD m_dwSecondaryTableSize;
DWORD m_dwStartLogSector;
DWORD m_dwNumLogSectors;
DWORD m_dwStartPhysSector;
DWORD m_dwNumPhysSectors;
這裡主要的動(dòng)作是在處理及維護(hù) DLUT Table和Secondary Table;其用途是為了快速的從Logical Address來(lái)找到Physical Address;是做Translation一個(gè)重要的Table。
m_pDynamicLUT[MASTER_TABLE_SIZE]:
這裡MASTER_TABLE_SIZE是256。因此可知一開始便給定Table的大小。這個(gè)Variable是Dynamic Look-Up Table (DLUT),也就是Mapping Table。
m_bIsNumSectorsPerSecTableLog2:
判斷Sector的個(gè)數(shù)在Secondary Table中是否是power of 2,會(huì)影響計(jì)算Table Size以及Secondary ID。若它是2的倍數(shù),可直接Shift取值,節(jié)省做除法取值的時(shí)間
m_dwNumSectorsPerSecTable:
在Secondary table中可紀(jì)錄多少個(gè)Sector
m_dwSecondaryTableSize:
Secondary Table的Size。根據(jù)有多少個(gè)Logical Sector及Physical Address的長(zhǎng)度來(lái)決定Size的大小
m_dwStartLogSector:
這個(gè)Logical Block的起始Sector的位置
m_dwNumLogSectors:
Logical Sector的個(gè)數(shù)
m_dwStartPhysSector:
這個(gè)Physical Block的起始Sector的位置
m_dwNumPhysSectors:
Physical Block的Sector的個(gè)數(shù)
4.2 On-Flash Data Structures
typedef struct _FlashInfoEx
{
DWORD cbSize;
FLASH_TYPE flashType;
DWORD dwNumBlocks;
DWORD dwDataBytesPerSector;
DWORD dwNumRegions;
FlashRegion region[1];
}FlashInfoEx, *PFlashInfoEx;
typedef struct _FlashInfo
{
FLASH_TYPE flashType;
DWORD dwNumBlocks;
DWORD dwBytesPerBlock;
WORD wSectorsPerBlock;
WORD wDataBytesPerSector;
}FlashInfo, *PFlashInfo;
flashType:在init之後這裡要取得Flash Type看是NOR亦或NAND。
dwNumBlocks:看這Flash中有多少個(gè)Block
dwBytesPerBlock:一個(gè)Block有多少Bytes
wSectorsPerBlock:一個(gè)Block有多少個(gè)Sector
wDataBytesPerSector:一個(gè)Sector有多少個(gè)Bytes
這裡是取得Flash的基本Info,之後再去算這個(gè)Flash內(nèi)有多少Block。而FlashInfoEx與FlashInfo的差別是Region的部分,由於看的NAND flash的部分只用一個(gè)Region,所以,下面都以一個(gè)Region做介紹。
Block有以下幾種Status, 根據(jù)不同的status來(lái)決定Sector會(huì)被放在那一個(gè)List裡。
BLOCK_STATUS_UNKNOWN:其它無(wú)法判斷的情況
BLOCK_STATUS_BAD:這個(gè)Block是Bad Block。
BLOCK_STATUS_READONLY:這個(gè)Block是Read Only。
BLOCK_STATUS_RESERVED:這個(gè)Block被Reserved。
另外,在取Block Status時(shí),FAL是用Block ID跟FMD取Block Status,而FMD是在得到這個(gè)Block ID之後,去算出此Block在Flash中的第一個(gè)Sector是第幾個(gè)Sector,再去取出它的Status給FAL。
以下圖為例,若是一個(gè)Block有10個(gè)Sector,那麼Block 2的第一個(gè)Sector就是Sector 11。因此,FMD便是取Sector 11的Status交還給FAL。
Figure 6. Get Block Status
4.3 How to Create Mapping Table
這裡介紹在Win CE所使用的Mapping Table。它是去Scan Flash上Info,先取出Region、Flash Type。一個(gè)Region內(nèi)有多個(gè)Block,每一個(gè)Region都有各自一個(gè)獨(dú)立的Table ,Region裡有多個(gè)Block。
Region的data Structure如下
typedef struct _FlashRegion
{
REGION_TYPE regionType;
DWORD dwStartPhysBlock;
DWORD dwNumPhysBlocks;
DWORD dwNumLogicalBlocks;
DWORD dwSectorsPerBlock;
DWORD dwBytesPerBlock;
DWORD dwCompactBlocks;
}FlashRegion, *PFlashRegion;
dwStartPhysBlock:在這個(gè)Region中Physical Block的index值,這裡的初始值是0。也就是說(shuō)若是這個(gè)Flash中有兩個(gè)Region,而每個(gè)Region中有10個(gè)Block,則第一個(gè) Region的Start Physical Block為0,第二個(gè)Region的Start Physical Block為10。
dwNumPhysBlocks:有多少個(gè)Block在這個(gè)Region裡
dwSectorsPerBlock:Block中有多少個(gè)Sector
dwCompactBlocks:在Compactor裡定義其值為2,之後在Compaction會(huì)看到
這裡是做Sector Mapping。因此Table是依一個(gè)個(gè)Sector去建成的。先取Block,再取Block中的所有Sector的Info(這裡取出的只有 Spare area的資料);依據(jù)這個(gè)Sector status再?zèng)Q定它是放入一般的List (在這裡亦有分Free, Read only) 或是Dirty list。其它有info的sector則是去做Mapping Table的動(dòng)作。其中要注意的是,由於Write是以Sector為單位在寫,所以存Free List是以Sector為單位在存,而Erase是以Block為單位,所以Dirty List是以Block為單位在存。
建Table的psuedo-code如下,
for (each Block)
{
for (each Sector)
{
Read Sector Info (spare area)
if (Sector is free)
{
add into m_list(Free)
}
if (Sector is dirty)
{
add into dirty_list
}
if (Sector is mapped)
{
if (Block is Read_Only && Sector is first sector on Block)
{
add into m_list(Read_only);
for (each Sector)
mapping the Table : L2P
break;
}
mapping the Table : L2P
}
} //for (each Sector)
}// for (each Block)
接下來(lái)說(shuō)明Mapping Table的流程:
DLUT(Dynamic Look Up Table)指的是Master Table,有256個(gè)entry,一個(gè)entry對(duì)映一個(gè)Secondary Table。沒有用到的Sector(Free Sector)不會(huì)在Table中去建立,採(cǎi)取On Demand的方式。
一個(gè)有資料的Sector會(huì)存有之前在系統(tǒng)中所代表其位置的Sector Logical Address,若是要找Secondary Tables並未建立,系統(tǒng)才會(huì)去建其Table,並根據(jù)Logical Address算出它在Secondary Table中的位置,再將其Physical Address存入至Table中。
Figure 7. DLUT and Secondary Table
下圖是詳細(xì)的建立Table的過(guò)程:
1. 根據(jù)給的Logical Sector先去算出Secondary Table ID(此圖假設(shè)算出來(lái)的ID = 1),再查詢是否已有Secondary Table,若該table不存在,系統(tǒng)會(huì)在此時(shí)Allocate一個(gè)新的Secondary Table。
2. 就先前讀出的Sector’s Spare Area的資料來(lái)建Secondary Table。再來(lái)便是計(jì)算在Secondary Table中的位置
3. 取出後再把Physical Sector Address存到這個(gè)位置中:
Figure 8. Create Logical to Physical Sector Address
4.4 Read
它做的流程可參考Figure 4來(lái)解釋,。根據(jù)Sector’s Logical Address算出在DLUT是第幾個(gè)entry,再依據(jù)Entry就可以取得相對(duì)應(yīng)的Secondary Table,再利用Logical Address做計(jì)算取出在這個(gè)Secondary Table中的位置,之後便可取得Physical Address。而FMD就可根據(jù)這個(gè)Address來(lái)取出位於Flash的資料。
4.5 Write
在Write之前必須在Free list中取一個(gè)可用的Sector,若是Sector不足,便會(huì)啟動(dòng)Compaction機(jī)制,以取到足夠的Sector,以便完成 Write。
在Write之前先將Sector Info Mark成處理中,再去寫Sector info;寫完info確定該Sector可以寫入,再將Sector Info 標(biāo)示為處理完,與Data一起寫入。最後更新Mapping Table以及Logical Address對(duì)映的Physical Address。
而之前舊的資料,將其update Sector info設(shè)定為Dirty;此外會(huì)算出此Sector位於哪一個(gè)Block,並將該Block Dirty的Sector個(gè)數(shù)加1。這邊要請(qǐng)讀者注意的是,它是SLC的動(dòng)作,它可以允許一次這個(gè)動(dòng)作,而MLC是不允許此值直接變更寫回。
5.?Garbage Collection (Compaction)
Garbage Collection,在WinCE中的命名是Compaction。簡(jiǎn)單的說(shuō),其目的是回收被無(wú)效資料所佔(zhàn)據(jù)的空間,且一次可回收愈多愈好。
5.1 What’s Garbage Collection?
由於Flash無(wú)法在更新資料時(shí)寫回相同的位置(除非先將該位置Erase),所以採(cǎi)Outplace的方式寫回資料。Outplace是將更新的資料寫入在不同的頁(yè)面中,來(lái)避免每次更新資料就必須進(jìn)行抹除的動(dòng)作的Overhead。
那麼原來(lái)不能直接寫回而變成無(wú)用舊資料的Sector,便需要有policy去將它釋放成為可用的Sector,這個(gè)policy便是Garbage Collection
5.2 Garbage Collection Policy
在這個(gè)FAL中會(huì)存在兩條List,分別去紀(jì)錄Free Sector及Dirty Block。這兩條List所紀(jì)錄的大小不一樣是由於寫是Sector為單位去寫,而Erase是以Block為單位在做。
上面所提到的直接選Dirty Block,便是直接去取Dirty List裡Dirty Sector最多的一個(gè)Block來(lái)當(dāng)做Victim Block。而Random選Block的方式,是取第一個(gè)Physical Block做Base,用1~32做Random去除Physical Block的數(shù)量取餘數(shù);Base加上餘數(shù)之後的值為Block ID,這個(gè)Block即為Victim Block。
Compaction的時(shí)機(jī)是當(dāng)Free Sector不足時(shí)做,且會(huì)做到這個(gè)Compaction完成才離開,這裡稱它是Synchronous Compaction。例如:一個(gè)Block有20個(gè)Sector,那麼Free Sector最少要有40個(gè)才夠。另一個(gè)情況是,當(dāng)你要寫的Data的Sector個(gè)數(shù)若是比目前Free Sector個(gè)數(shù)多時(shí),它也會(huì)強(qiáng)制執(zhí)行Compaction直到有足夠的Free Sector,得以完成Write Data的任務(wù)才會(huì)結(jié)束。
另一個(gè)時(shí)機(jī)是當(dāng)Flash目前的Dirty Sector數(shù)目Free Sector多(但此情況還是Free Sector的個(gè)數(shù)比限制的下限個(gè)數(shù)多),但是它的Priority低,是Background Compaction這裡稱它是Asynchronous Compaction,不會(huì)強(qiáng)制必須要Compaction結(jié)束才會(huì)離開。
6.?Wear-Leveling
6.1 What is Wear-Leveling?
因?yàn)镕lash的每個(gè)Block有Erase次數(shù)的限制,當(dāng)某個(gè)Block Erase次數(shù)過(guò)多,可能會(huì)造成該Block存取速度變慢,嚴(yán)重時(shí)甚至?xí)斐稍揃lock毀損。因此為了避免同一區(qū)塊過(guò)度存取而造成毀損,且能夠平均每個(gè) Block Erase的的次數(shù),此機(jī)制稱為Wear-Leveling。
6.2 How WL is done in FAL
這裡Critical是指當(dāng)Free Sector不足時(shí)的情況,所以會(huì)直接取Dirty List裡的Block去做Compact。其它情況下就使用Random的方式,下面就直接介紹這兩種policy。
1. Critical = True
從Dirty List裡取一個(gè)Dirty Sector最多的Block來(lái)Earse
Bool value 不更改。
2. Critical = False
是用Random的方式,用Static Bool value做交替的條件,Bool value的初始值為False。
若第一次是Random方式選(Bool Value = True),且更改Bool value
則第二次從Dirty List裡選(Bool Value = False),亦更改Bool value
此外,若是Random選出來(lái)的Block是Free或是Invalid就從Dirty List裡選。
Random使用範(fàn)例如下:
Sequence(S)
1
2
3
4
5
Execute
Dirtiest
Random
Dirtiest
Random
Dirtiest
Free Block
N
N
N
Y
N
Re-Execute
Dirtiest
S 1:第一次是Bool value = False,所以從Dirty List裡取,且更改Bool value為True
S 2:第二次是Bool value = True,所以取Random,且更改Bool value為False
S 3:第三次是Bool value = False,從Dirty List裡取,且更改Bool value為True
S 4:第四次是Bool value = True,所以取Random,且更改Bool value為False。但取出的Block為Free Block所以改取Dirty List。
S 5:第五次是Bool value = False,從Dirty List裡取,且更改Bool value為True
綜合使用範(fàn)例如下:
C = Critical, D = Dirty Block, R = Random Block,
B = bRandom-表示T下一次要選Random或是從Dirty List裡取Victim
(請(qǐng)看Critical = False的範(fàn)例及說(shuō)明)
若C的順序如下:
TFFTFFF B = F (init)
則選的Block的流程如下:
Critical
Choose Block
B (Change)
C = T
D
B = F(no change)
C = F
D
B = T
C = F
R→若選出Block is Free
則再?gòu)腄選
B = F
C = T
D
B = F (no change)
C = F
D
B = T
C = F
R
B = F
C = F
D
B = T
7.?FMD/FAL interface
7.1 FMD給FAL的函式介面
typedef struct _FMDInterface
{
DWORD cbSize;
PFN_INIT pInit;
PFN_DEINIT pDeInit;
PFN_GETINFO pGetInfo;
PFN_GETBLOCKSTATUS pGetBlockStatus;
PFN_SETBLOCKSTATUS pSetBlockStatus;
PFN_READSECTOR pReadSector;
PFN_WRITESECTOR pWriteSector;
PFN_ERASEBLOCK pEraseBlock;
PFN_POWERUP pPowerUp;
PFN_POWERDOWN pPowerDown;
PFN_GETPHYSSECTORADDR pGetPhysSectorAddr;
PFN_OEMIOCONTROL pOEMIoControl;
} FMDInterface, *PFMDInterface;
以上FMD Function其本來(lái)是以FMD_做Prefix,以pGetBlockStatus為例,其在FMD.cpp的naming是 FMD_GetBlockStauts;但為了某些使用技巧,因此將其包裝成Structure使其得以用Function Point的方式使用,以下說(shuō)Function的用途:
pInit:
當(dāng)Flash Device要initial時(shí)對(duì)Device做初始化的動(dòng)作。找到其支援的chip加以進(jìn)行初始化,以及返回一個(gè)FMD handle。
pDeInit:
取得FMD handle以釋放一些用到的資源,關(guān)掉chip controller。
pGetInfo:
該函數(shù)用於取得Flash的資訊。其中pFlashInfo是一個(gè)包含F(xiàn)lash資訊的結(jié)構(gòu)。
pFlashInfo->flashType:Flash的類型。
pFlashInfo->wDataBytesPerSector:一個(gè)Sector多少個(gè)Bytes。
pFlashInfo->dwNumBlocks:Flash中總共有多少個(gè)Block。
pFlashInfo->wSectorsPerBlock:每個(gè)Block中包含多少個(gè)Sector。
pFlashInfo->dwBytesPerBlock:每個(gè)Block中包含多少個(gè)Bytes。
pGetBlockStatus:
為取得某一個(gè)block的狀態(tài)。參數(shù)為Block Address。由於Flash中可能有Bad Block,所以首先會(huì)檢查目前是否為Bad Block,是取得第一個(gè)Sector的Status即可知道。如果發(fā)現(xiàn)該塊是Bad Block,應(yīng)該返回BLOCK_STATUS_BAD。如果不是Bad Block,需要讀取這個(gè)塊的起始Sector的Sector Info。如果讀該Sector Info出錯(cuò),應(yīng)該返回BLOCK_STATUS_UNKNOWN。
pSetBlockStatus:
設(shè)定某個(gè)block的狀態(tài),第一個(gè)參數(shù)是Block位址,第二個(gè)是要設(shè)定的狀態(tài)。在這個(gè)函數(shù)中,首先檢查dwStatus是不是 BLOCK_STATUS_BAD,如果是就對(duì)作Bad Block標(biāo)記,然後返回FALSE。如果不是,就將dwStatus寫到該block的第一個(gè)Sector的info中。
pReadSector:
用於讀Flash上的一個(gè)Sector。其中傳入的參數(shù)值代表如下:
startSectorAddr:
Sector的起始位址,就是從哪個(gè)Sector開始。
pSectorBuff:
讀出的每一個(gè)Sector的資料都存放在這個(gè)buffer中。
pSectorInfoBuff:
一般每個(gè)Sector的資訊會(huì)被保存在Flash的資料中。從Flash的資料將該Sector的相關(guān)資訊讀出來(lái),存放在這個(gè)buffer中。這些資料也就是Spare area。
dwNumSectors:
讀取多少個(gè)Sector。
pWriteSector:
意義與上面相同,此處是對(duì)Write。
pEraseBlock:
為Erase block,參數(shù)為第幾個(gè)block。
pPowerUp:
恢復(fù)Flash設(shè)備電源
pPowerDown:
關(guān)閉Flash設(shè)備電源
pGetPhysSectorAddr:
取得在Flash上它physical Address。
pOEMIoControl:
就像很多的IOControl函數(shù)一樣,根據(jù)不同的case,實(shí)現(xiàn)相應(yīng)的功能。針對(duì)NAND Flash來(lái)說(shuō),這裡面不一定都需要implement。事實(shí)上,如果什麼都沒有implement,也不影響使用。
7.2 FAL給File System的函式介面
DSK_Init:
這裡會(huì)先去initial FMD,以便取得Flash基本資料。之後再去initial FAL,以取得對(duì)Flash操作的interface,還有建立Translation Table。
DSK_Deinit:Free FAL object再Free FMD
DSK_Open:這裡並未implement只有debug message。
DSK_Close:這裡並未implement只有debug message,return TRUE。
DSK_Read:Not Used。
DSK_Write:Not Used。
DSK_Seek:Not support。
DSK_PowerDown:直接Call FMD的PowerDown function。
DSK_PowerUp:直接Call FMD的PowerUp function。
DSK_IOControl:
對(duì)Flash的操作皆是透過(guò)這支Function。先根據(jù)進(jìn)來(lái)的Control Code再去做相應(yīng)的檢查;例如對(duì)Flash取得其Information(GetInfo),要確認(rèn)傳進(jìn)來(lái)的Buffer以及Size是否正確,無(wú)誤之後再去做相應(yīng)的動(dòng)作。
因此上述的Open、Close、Read、Write皆是由此Function做處理。
8.?與系統(tǒng)註冊(cè)一個(gè)Device
8.1 FAL、FMD
在 WinCE 裡的Flash driven實(shí)作是由FAL及FMD所組成(Figure 1),FAL以Library的型式,它對(duì)外的interface其Prefix為DSK_開頭(7.2章有介紹),而FMD是Dynamic Link的型式,其Prefix則是FMD_開頭(7.1章有介紹)。要在WinCE上需要MSflash.lib來(lái)趨動(dòng),這會(huì)需要有fal.lib及 fmd.dll,才可以在WinCE裡使用這個(gè)Flash。FAL也要有一個(gè)FMD才可以在WinCE上Run一個(gè)Device,否則在WinCE而言,也只是提供了一個(gè)Interface而沒有可使用的Device。
FAL是由下列File組成的(在此僅列.Cpp)
1. Compactor – 提供Compactor function
2. Fal – Build Mapping Table以及對(duì)FMD Layer下Read、Write、Compactor、Format的動(dòng)作,實(shí)際對(duì)Flash做Read、Write、Erase還是FMD Layer(架構(gòu)請(qǐng)見Figure 1)
3. falmain – 提供給File System的Interface
4. log2physmap – Mapping Table之Update及取得Physical Sector Address。
5. sectormgr – 對(duì)Sector之管理,諸如對(duì)Free-List及Dirty-List之處理(管理),以及提供對(duì)Sector操作的Function
以下做的動(dòng)作是將系統(tǒng)中FAL(Library)從系統(tǒng)中抽出來(lái),再加上修改過(guò)的Flash FMD(Driver),將其在Simulator上得以被註冊(cè)顯示在WinCE的環(huán)境裡。
8.2如何與系統(tǒng)註冊(cè)一個(gè)Storage
Step 1.
在建好一個(gè)OSDesign時(shí),請(qǐng)先Build整個(gè)環(huán)境(約二十至四十分鐘不等),若是先做下面的動(dòng)作再一起B(yǎng)uild,會(huì)出現(xiàn)Error。
Step 2.
加入Project在your clone emulator?(這裡是Clone自Device Emulator : ARMV4I。Clone name : ARVV4IBase)
下的SRC->Drivers (path : C:/WINCE600/PLATFORM/ARMV4IBase/SRC/DRIVERS)
以下是顯示在Visual Studio的情況。
這裡要改下列的數(shù)個(gè)File
Dirs:C:/WINCE600/PLATFORM/your clone emulator/SRC/DRIVES裡,加入新加的Project name(Driver name)。
Example:(# -- 注解)
# @CESYSGEN ENDIF CE_MODULES_SHOWFAL
FALSHOW /
FMDSHOW /
Platfrom.bib:其目的是要定義那些是要包在OS的Image內(nèi),因此要加入新的FMD。
Example:
IF BSP_FMDSHOW1
FMDSHOW1.dll $(_FLATRELEASEDIR)/FMDSHOW1.dll NK SHK
ENDIF
Platfrom.reg:定義冷開機(jī)時(shí)系統(tǒng)啟始的Registry Key及相關(guān)數(shù)值,值得一提的是,Storage的IClass是可以重複的。
Example:
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/FMDSHOW1]
"Prefix"="DSK"
"Dll"="FMDSHOW1.dll"
"IClass"=multi_sz:"{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
之後若是修改Platfrom.reg裡的值只需要Build->Advanced BuildCommands->Build Current BSP and Subprojects即可
Source:是存要Link的library或是會(huì)使用到的library,這個(gè)是每個(gè)Project都會(huì)有的。
Catalog Item:如此建的FMD才可以在Catalog Items View下的Device Drivers裡看到。
Step 3. 以下的選項(xiàng)記得要選起來(lái)
Step 4. 上面的動(dòng)作都做了之後,選取你新建的FMD再整個(gè)Project Build過(guò)。再來(lái),便是Attach Device之後就可以看到Win CE emulator的畫面,點(diǎn)取紅色方框的My Device
Step 5.點(diǎn)取紅色方框的Control Panel
Step6.點(diǎn)取紅色方框的Storage Manger
Step 7. 以下便是新加的FMD。
按下Partitions旁的New Button
會(huì)出現(xiàn)下列視窗,取一個(gè)名字按右上方的OK
會(huì)回到上一個(gè)畫面,選Properties
Step 8. 先選Dismount。
其它的Button會(huì)Enable
選Format Button
Step 9. Choose Start Button
之後會(huì)跳一個(gè)訊問(wèn)Message Box,選確定便會(huì)開始Format。完成後按下OK
Step 10. 回到Partition Properties的畫面,選Mount Button,按下右上方的OK
回到Storage Properties畫面後,按下右上方的OK
Step 11. 回到My Device畫面就可以看到產(chǎn)生了一個(gè)新的Storage。
以上便是去Create一個(gè)新的Flash Device的簡(jiǎn)單流程。
上面這篇分析很清晰,不過(guò)比較零散,大致的類的練習(xí)隨意畫了個(gè)圖:
一個(gè)FAL實(shí)例針對(duì)一個(gè)Region區(qū)域,有些概念需要清楚,Wince的Sector是底層返回的頁(yè)的大小,不要混淆。
針對(duì)大的Nand Flash FAL+FMD絕對(duì)不是好的實(shí)現(xiàn)方式,上電建立映射表的過(guò)程太慢,如果將每個(gè)頁(yè)信息放入一個(gè)集中的地方,又難免導(dǎo)致該處使用過(guò)度。
使用MDD+PDD可能會(huì)更好,還沒實(shí)驗(yàn),之后做對(duì)比。
總結(jié)
以上是生活随笔為你收集整理的WinCE NAND flash - FAL的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 从技术岗位走向管理岗位:机会是留给有准备
- 下一篇: 广州捷宝科技(Android+WINCE