【ARM-WINCE】WinCE5.0/6.0下,通過command line實現自動化編譯

iDotNetSpace發表於2008-07-08

在網上的很多論壇中都看到有人提問:應用程式如何直接讀寫Flash的扇區,或者是類似的問題。總之,就是希望應用程式能夠直接訪問Flash裝置,直接讀寫扇區的資料,或者作其他的操作。這幾天沒事,就嘗試著做了一下,把我的方法介紹給大家。

先做個簡單的介紹。WinCE支援Flash裝置,一般指Nandflash或者是NORFlash,採用的架構一般是FAL+FMD架構,我們實現FMD相關的介面函式,Flash的驅動就算完成了。當WinCE啟動以後,我們能夠看到Flash裝置的磁碟。我們可以操作磁碟上面的檔案,但是不能直接操作flash裝置,對Flash裝置的操作無非就是:讀,寫,擦除,讀ID。

現在開始介紹實現的方法。我們如果想在應用程式中直接呼叫FMD中的FMD_ReadSector(..),FMD_WriteSector(..),FMD_EraseBlock(..)是不太現實的。這裡再補充一下,這三個函式分別是Flash的讀扇區,寫扇區,擦除塊的函式。好像有點羅嗦了。但是我們可以在應用程式中呼叫到FMD_OEMIoControl(..)函式,這個是可以做到的。所以我們需要改一下Flash裝置的驅動程式,也就是改Flash裝置驅動中的FMD_OEMIoControl(..)這個函式。我的改動如下:

BOOL  FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
    PFMDInterface pInterface = (PFMDInterface)pOutBuf;


    RETAILMSG(1, (TEXT("FMD_OEMIoControl: control code is 0x%x\r\n"), dwIoControlCode));
    switch(dwIoControlCode)
    {
        case IOCTL_FMD_GET_INTERFACE:
            if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
            {
                 DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_INTERFACE bad parameter(s).\r\n")));
                 return(FALSE);
            }   
            pInterface->cbSize = sizeof(FMDInterface);
            pInterface->pInit = FMD_Init;
            pInterface->pDeInit = FMD_Deinit;
            pInterface->pGetInfo = FMD_GetInfo;       
            pInterface->pGetInfoEx = NULL; //FMD_GetInfoEx;
            pInterface->pGetBlockStatus = FMD_GetBlockStatus;    
            pInterface->pSetBlockStatus = FMD_SetBlockStatus;
            pInterface->pReadSector = FMD_ReadSector;
            pInterface->pWriteSector = FMD_WriteSector;
            pInterface->pEraseBlock = FMD_EraseBlock;
            pInterface->pPowerUp = FMD_PowerUp;
            pInterface->pPowerDown = FMD_PowerDown;
            pInterface->pGetPhysSectorAddr = NULL;           
            pInterface->pOEMIoControl = FMD_OEMIoControl;           
            break;
       case 0xff123456:
            FMD_ReadSector(..);                //呼叫讀Sector函式
            break;
       case 0xff654321:
            FMD_WriteSector(..);                //呼叫寫Sector函式
            break;
       case 0xff123457:
            FMD_EraseBlock(..);               //呼叫擦除Block函式
            break;
       default:
            DEBUGMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
            return(FALSE);
    }

    return(TRUE);

在FMD_OEMIoControl(..)函式裡面增加了3個case,這3個case裡面呼叫了讀/寫/擦除函式。至於Case的值,我是隨便定義的。這樣Flash裝置的驅動部分就改完了。

在改完Flash驅動以後,我下面會提供兩種方法,每一種方法都和Flash裝置的登錄檔配置有關:

1. 以Nandflash為例,當然對於NORFlash來說大同小異,登錄檔配置如下:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\NANDFlash]
"Dll"="ep94xxnandflash.dll"
"Prefix"="DSK"
"Order"=dword:4
;"Ioctl"=dword:4
"Profile"="NSFlash"
"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"


; Override names in default profile
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NSFlash]
 "Name"="Ep94xx NAND Flash"
 "Folder"="NANDFlash"
 "PartitionDriver"="MSPart.dll"
 "AutoMount"=dword:1
 "AutoPart"=dword:1
 "AutoFormat"=dword:1

[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NSFlash\FATFS]
"EnableCache"=dword:1
"CacheSize"=dword:1000
"MountBootable"=dword:1
"Flags"=dword:00000024
"CheckForFormat"=dword:1

然後編寫應用程式,主要就是通過CreateFile來開啟DSK1:裝置,然後通過DeviceIoControl(..)函式來呼叫FMD_OEMIoControl(..)函式,來達到直接讀/寫/擦除Flash裝置的目的。應用程式程式碼如下:

HANDLE hFirm;

 hFirm = CreateFile(TEXT("DSK1:"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 if(hFirm == INVALID_HANDLE_VALUE)
 {
  printf("Open Flash Device Failed");
  return 0;
 }

 iRet = DeviceIoControl(hFirm, 0xff123456, para1, para2, para3, para4, para5, para6);  //Read Flash Sector
 iRet = DeviceIoControl(hFirm, 0xff654321, para1, para2, para3, para4, para5, para6);  //Write Flash Sector
 iRet = DeviceIoControl(hFirm, 0xff123457, para1, para2, para3, para4, para5, para6);  //Erase Flash Block

 printf("DeviceIoControl OK\r\n");


 while(1)
  ;

通過上面的應用程式,就能夠呼叫到Flash裝置驅動中的FMD_OEMIoControl(..)函式,這樣根據不同的case就可以呼叫讀/寫/擦除函式了。

2. 以Nandflash為例,當然對於NORFlash來說大同小異,登錄檔配置如下:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\NANDFlash]
"Dll"="ep94xxnandflash.dll"
"Prefix"="DSK"
"Order"=dword:4
;"Ioctl"=dword:4
"Profile"="NSFlash"
"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"


; Override names in default profile
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NSFlash]
 "Name"="Ep94xx NAND Flash"
 "Folder"="NANDFlash"
 "PartitionDriver"="MSPart.dll"
 "AutoMount"=dword:1
 "AutoPart"=dword:1
 "AutoFormat"=dword:1

[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NSFlash\FATFS]
"EnableCache"=dword:1
"CacheSize"=dword:1000
"MountBootable"=dword:1
"Flags"=dword:00000024
"CheckForFormat"=dword:1

[HKEY_LOCAL_MACHINE\System\StorageManager\AutoLoad\NSFlash]
"DriverPath"="Drivers\\BuiltIn\\NANDFlash"
"LoadFlags"=dword:0
"BootPhase"=dword:1

然後編寫應用程式,主要就是通過OpenStore來開啟NSFlash,然後通過DeviceIoControl(..)函式來呼叫FMD_OEMIoControl(..)函式,來達到直接讀/寫/擦除Flash裝置的目的。應用程式程式碼如下:

 HANDLE hFirm;

 hFirm = OpenStore(L"NSFlash");
 if(hFirm == INVALID_HANDLE_VALUE)
 {
  printf("Open Flash Device Failed");
  return 0;
 }

 iRet = DeviceIoControl(hFirm, 0xff123456, para1, para2, para3, para4, para5, para6);
 iRet = DeviceIoControl(hFirm, 0xff654321, para1, para2, para3, para4, para5, para6);
 iRet = DeviceIoControl(hFirm, 0xff123457, para1, para2, para3, para4, para5, para6);

 printf("DeviceIoControl OK\r\n");

 while(1)
  ;

通過這種方法,也可以在應用程式中呼叫到FMD_OEMIoControl(..)函式,從而達到直接訪問Flash裝置的目的。

總結一下,上面的兩種方法大致原理其實是一樣的,都是通過DeviceIoControl函式來呼叫FMD_OEMIoControl函式,然後達到直接訪問Flash驅動的目的,這樣就可以在應用程式中直接讀/寫/擦除Flash裝置了。

最後需要注意的是:你的Flash驅動裡面需要對讀/寫/擦除等直接操作Flash硬體的函式進行保護,因為Flash裝置應該是由WinCE的檔案系統來管理的,而現在你的應用程式也可以直接訪問它了,所以保險起見,新增互斥量保護避免訪問衝突。

上面的所有實現,都是在WinCE6.0上面做得,相信在WinCE5.0上面應該差不多。

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

相關文章