【ARM-WINCE 】 WinCE中nandflash驅動開發介紹

iDotNetSpace發表於2008-07-08

先來談一下flash,flash是一種非易失儲存器,一般flash儲存裝置分為Nandflash和Norflash。這兩種flash各有優缺點。在讀寫速度上,norflash的讀速度快一些,nandflash的寫速度會快一些。Nandflash的容量一般都比Norflash大很多,而且相比價格比較便宜。但是Norflash支援XIP,而nandflash不支援,而且Nandflash可能有壞塊。相關的比較,網上很多文章都有介紹,這裡就說這麼多了。

這裡介紹nandflash驅動,在WinCE中,有專門針對flash儲存裝置驅動的支援,一般傳統採用FAL+FMD的架構。在WinCE最新的版本中,也就是Windows CE6.0 R2中,還支援MDD+PDD的架構。在FAL+FMD架構中,FAL層由微軟來實現,我們需要實現FMD層的相關介面函式。在MDD+PDD的架構中,MDD替換了原來架構中的FAL,而PDD相當於原來的FMD,只要實現PDD層就可以了。如果你的系統已經升級到WinCE6.0 R2,那麼你應該可以在\WINCE600\Public\COMMON\OAK\DRIVERS目錄下面找到這兩種架構驅動的原始碼。 由於MDD+PDD的架構在WinCE6.0 R2中才有支援,本人也沒有實現過。所以這裡只介紹基於FAL+FMD架構下,nandflash驅動的開發,這也是目前大家都採用的開發flash驅動的架構。

如上面所說,我們需要實現FMD層的相關介面,下面來介紹一下各個介面函式:

1. PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut): 這個是Flash裝置的初始化函式。在WinCE啟動的時候,要載入Flash驅動時,首先呼叫這個函式對flash裝置進行初始化。如果你的系統中有nandflash的controller,那麼你需要在這裡對你的nandflash controller進行初始化。如果沒有的話,你需要針對你的硬體設計進行相關的片選,時序等進行配置。返回一個handle表示成功,這個handle將被FMD_Deinit(..)函式用到,如果返回NULL表示失敗。

2. BOOL FMD_Deinit(PVOID hFMD): 這個函式在nandflash驅動解除安裝的時候被呼叫,引數就是FMD_Init函式返回的Handle.一般在這個函式裡面,你可以釋放一些用到的資源,然後關閉nandflash controller。

3. BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors): 這個函式用於讀nandflash的一個扇區。對於nandflash來說,分大page和小page,大page是2048個bytes一頁,小page是512個bytes一頁。所以大page每個扇區有2048 bytes,小page每個扇區有512 bytes。

    startSectorAddr: nandflash物理扇區的起始地址,對於nandflash來說,就是nandflash中從哪個page開始。

    pSectorBuff:扇區資料buffer,從nandflash中讀出的每一個扇區的資料都存放在這個buffer中。

    pSectorInfoBuff:扇區資訊buffer,一般每個扇區的資訊會被儲存在nandflash的帶外資料中,針對小page,帶外資料有16 bytes,大page有64 bytes。從nandflash的帶外資料將該扇區的相關資訊讀出來,存放在這個buffer中。

    dwNumSectors:讀取多少個扇區,對於nandflash來說相當於讀取多少個page。

4. BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors): 該函式用於寫nandflash的一個扇區。引數和上面的FMD_ReadSector的引數意思一樣,就不多說了。

5. BOOL FMD_EraseBlock(BLOCK_ID blockID): 該函式用於擦出nandflash的一個block,引數為要擦除nandflash的block地址,也就是第幾個block。

6. DWORD FMD_GetBlockStatus(BLOCK_ID blockID): 該函式獲得nandflash中某一個block的狀態。引數為nandflash的block地址。由於nandflash中可能有壞塊,所以針對nandflash,這個函式首先會檢查當前塊是否是壞塊,這個一般通過讀取當前block的第0個page和第1個page的帶外資料。對於小page nandflash一般是讀取第5個byte,對於大page nandflash一般讀取第0個byte,如果不為0xff表示該塊是壞塊。當然,至於具體該讀哪個byte,最好還是看一下所用nandflash的datasheet,確認一下,不同的廠家可能有所不同。如果發現該塊是壞塊,應該返回BLOCK_STATUS_BAD。如果不是壞塊,需要讀取這個塊的起始扇區的扇區資訊。如果讀該扇區資訊出錯,應該返回BLOCK_STATUS_UNKNOWN,否則,判斷獨到的資訊,返回相應結果。

7. BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus): 該函式設定nandflash某個block的狀態,第一個引數是nandflash的block地址,第二個是要設定的狀態。在這個函式中,首先檢查dwStatus是不是BLOCK_STATUS_BAD,如果是就對nandflash作壞塊標記,然後返回FALSE。如果不是,就將dwStatus寫到該block的第0個page的扇區info中。這個函式和上面的函式正好是相反的。

8. BOOL FMD_GetInfo(PFlashInfo pFlashInfo): 該函式用於返回flash的資訊。其中pFlashInfo是一個包含flash資訊的結構。

    pFlashInfo->flashType:flash的型別,對於nandflash來說,應該是NAND。

    pFlashInfo->wDataBytesPerSector:一個扇區多少個bytes,對於大page是2048,對於小page是512。

    pFlashInfo->dwNumBlocks:flash中總共有多少個block,查一下所用的nandflash的datasheet就知道了。

     pFlashInfo->wSectorsPerBlock:每個block中包含多少個扇區。

    pFlashInfo->dwBytesPerBlock:每個block中包含多少個bytes。

9. VOID FMD_PowerDown()和VOID FMD_PowerUp(): 這兩個函式用於電源管理。FMD_PowerDown()用於關閉flash裝置電源,FMD_PowerUp()用於恢復flash裝置電源。根據你所用處理器和相關硬體環境,去實現這兩個函式。不實現也不會影響nandflash的使用。

10. BOOL FMD_OEMIoControl(..): 就像很多的IOControl函式一樣,根據不同的case,實現相應的功能。針對nandflash來說,這裡面的case不一定都需要實現。事實上,如果什麼都沒有實現,也不影響nandflash的使用。在WinCE的文件中,定義了一些需要實現的case,你可以實現,也可以不去實現。

對於nandflash來說,實現上述函式就可以了。在nandflash出廠的時候,廠家已經對nandflash中的壞塊進行了標記。所以第一次對nandflash操作的時候,不要隨便擦除nandflash,因為這樣可能會把壞塊標記擦掉,這樣你就判斷不出哪個塊是壞塊了。

關於ECC校驗,目前很多處理帶有nandflash controller,而且nandflash controller帶有硬體ECC功能。如果沒有硬體ECC,也可以使用軟體ECC,軟ECC的程式碼可以在\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\BLOCK\MSFLASHFMD\ECC下找到。一般來說,ECC校驗會對512個BYTE產生3個位元組的校驗碼,也就是說對小PAGE來說,每個PAGE有3個位元組的ecc校驗碼;對於大PAGE來說,有12個位元組。這些校驗碼應該在寫扇區資料的時候,被寫在扇區的帶外資料裡面。當讀扇區資料時,會先把資料讀出來,然後根據這些資料計算ecc,再和讀出來的ecc進行比較,如果一致,則表示正確。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-374493/,如需轉載,請註明出處,否則將追究法律責任。

相關文章