cetk使用方法--nand flash测试
測試環境:
OS:
??? wince5.0
cpu:
??? J9
image:
????ramimage(開始是一個binfs分區存放ramimage,后面是一個fat分區存放user data,它們公用一個塊驅動)
note:
??? 具體測試command的書寫要參照注冊表的配置。
??? 本文中頻繁用到的smflash,是設備名,即傳遞給CreateFile和OpenStore的實參,如果不確定你塊驅動的設備名,可以在AP中通過FindFirstStore以及FindNextStore的方式將其遍歷出來。
??? 因為之前發了一篇存在諸多問題,所以重新排版和修改了其中的大部分錯誤,并附上我的注冊表配置。
?
CETK使用方法—NAND Flash(一個塊驅動并且將Image放到該塊驅動上)
1. 對測試有用的TUX關鍵詞
TUX語法中的關鍵詞有很多,其中用來制定傳遞給TUX DLL(即測試DLL,如flashwear.dll)的關鍵詞是-c,詳細解釋如下:
-c parameters
This parameter allows you to pass a parameter string to the Tux test DLL itself. The parameter string that you pass is associated with the DLL most recently specified with the -d parameter. This behavior allows you to specify different parameters for each Tux test DLL. If the string that you specify contains spaces or other special characters, then you should surround the string with quotation marks.
?????? 在上面的文字中說的很清楚,-c用來傳遞參數給-d指定的tux dll,如果傳遞的參數中包含了空格,則應用引號將參數包起來。
?????? 如下:
?????? 詳細的TUX語法參照如下地址:
ms-help://MS.WindowsCE.500/wcedebug5/html/wce50conTuxCommandLineParameters.htm
2. FSD測試
命令
默認命令+-c “-zorch -p msflash”。
細節
詳細解釋如下。
-zorch: If you run the unmodified test, it will fail. In the results file you will see a message warning you to back up data on all cards and disks that are attached to the testing device before running the test. It then instructs you to modify the command line by right clicking on the test in the CETK tree control, choosing Edit Command Line, and adding the following switch to the command line: -zorch
可見參數-zorch告訴測試DLL在不備份磁盤數據的情況下進行測試。因為測試會毀壞測試磁盤上的文件,所以有此命令參數。
-p:Specify the storage profile to which to restrict testing, found in the registry under the HKEY_LOCAL_MACHINE/System/StorageManager/Profiles key. The default storage profile is PCMCIA.
可見參數-p告訴了測試項到HKEY_LOCAL_MACHINE/System/StorageManager下的哪個測試項下搜索相關信息。
如果磁盤上有多個分區的話,還要使用-r傳遞分區名,相關解釋如下:Specify the root directory in which to run the test. If you provide this option, the test only runs in the specified directory and ignores the –s and –p options. This flag is useful for a file system driver that does not use storage profiles such as a network file system driver. If the name of the root directory includes spaces, surround the name of the directory with single quotation marks; for example, -r '/Storage Card'.
更加詳細的參數介紹參照:
ms-help://MS.WindowsCE.500/wcedebug5/html/wce50tskModifyingtheFileSystemDriverTest.htm
3. disktest測試項
命令:
tux -o -d disktest -c "/disk msflash /oldioctls /maxsectors 128 /store /zorch /profile msflash"
細節:
從理論上來說,TUX調用disktest.dll對塊驅動進行測試的時候,只需要調用打開塊驅動獲取操作Handle,然后調用DSK_IoControl進行讀寫就可以了。但是,實際操作過程中發現由于smflash.dll由Storage Manager進行加載,所以無法使用CreateFile獲取塊驅動的操作句柄,而必須調用OpenStore。
PB幫助文檔中在介紹通過傳遞給TUX DLL參數決定使用CreateFile還是OpenStore打開塊驅動的時候,提到如下內容:
/store
Specify that the test opens a handle to the disk by using the OpenStore function instead of the CreateFile function.
Opening a handle by using the OpenStore function is not required to test block driver functionality. However, it is useful for testing a storage device that Filesys.exe loads automatically if you cannot open the storage device as a stream device. For example, you can open a handle to a flash driver for ROM by using the OpenStore function.
代碼中可以找到如下的
| HANDLE OpenDevice( ??? LPCTSTR pszDiskName) // -------------------------------------------------------------------- { ??? // open the device as either a store or a stream device ??? if(g_fOpenAsStore[Passion1]?) ??? { ??????? return OpenStore(pszDiskName); ??? } ??? else ??? { ??????? return CreateFile(pszDiskName, GENERIC_READ, FILE_SHARE_READ, ??????????????? NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ??? } } |
?????? 關于/disk dsk*,幫助文檔中提到:
Specify the device name of the disk to be tested.
If you do not specify this parameter, the test probes for a mass storage disk on devices DSK1-9. Specifying this parameter overrides the automatic detection process and forces the test to use the disk that you specify.
可以看到,如果不配置/disk的參數的話,系統就會去搜索所有的dsk1~9。其實不是這么回事,這個地方有兩個錯誤:
>> /disk的參數描述不正確
正確的描述應該如下:
| 參數 | 獲取塊驅動的操作句柄 |
| /disk | CreateFile(DSK1~9) |
| /disk *** | CreateFile(***) |
| /disk *** /store | OpenStore(***) |
| /disk /store | 通過設備管理器發送STORE_MOUNT_GUID的Store,具體參照DEV_DetectFirstDevice(&STORE_MOUNT_GUID, szDisk, MAX_PATH) |
| /store | 通過設備管理器發送BLOCK_DRIVER_GUID的塊驅動,DEV_DetectFirstDevice(&BLOCK_DRIVER_GUID, szDisk, MAX_PATH) |
>> /disk的***描述不正確
?????? ***是任意可以傳遞給OpenStore或者CreateFile的參數。
?????? 詳細的參數如下:
tux -o -d disktest -c "/disk msflash /oldioctls /maxsectors 128 /store /zorch /profile msflash"
?
>> 傳遞Command但是TUX DLL的解析有問題
從TUX DLL最開始的Log信息中看到如下的信息:
| TUXMAIN.CPP: DLL_PROCESS_ATTACH ShellProc(SPM_LOAD_DLL, ...) calledDISKTEST: Usage: tux -o -d disktest -c"/disk <disk> /profile <profile> /maxsectors <count> /oldioctls"?????? /disk <disk>??????? : name of the disk to test (e.g. DSK1:); default = first detected disk?????? /profile <profile>? : limit to devices of the specified storage profile; default = all profiles?????? /maxsectors <count> : maximum number of sectors per operation; default = 128?????? /oldioctls????????? : use legacy DISK_IOCTL_* codes?????? /store????????????? : open the disk using the OpenStore() APIShellProc(SPM_SHELL_INFO, ...) calledCommand Line: "/disk msflash /oldioctls /maxsectors 128 /store /zorch /profile msflash". DISKTEST: Disk Device Name = msflash[Passion2]? DISKTEST: Forcing use of legacy DISK_IOCTL* style control codes DISKTEST: Will open disk as a store (using OpenStore()) DISKTEST: Max Sectors per operation = 128 ShellProc(SPM_REGISTER, ...) called<TESTGROUP> |
?????? 但是有的時候你給/disk傳遞的參數TUX DLL解析不出來,經過反復實踐,下面的一條命令是萬能命令:
tux -o -d disktest -c "/disk msflash /oldioctls /maxsectors 128 /store /zorch /profile msflash"
?????? 保證可以解析出來device name。
?????? 仔細的看了看源代碼,但是還是沒有找到原因。從源代碼上來看,這些解析工作由函數ProcessCmdLine調用類CClParse的成員函數來實現,不存在任何問題。
4. Flashwear測試
?
命令
默認命令+-c”/zorch /profile msflash /store /disk msflash”或者/disk msflash /repeat 1 /sectors 64 /store都行
同時需要修改注冊表。修改Flash注冊表的Profile為FlashDisk,這是Microsoft Flashwear 測試DLL的Bug引起的。Flashwear的參數意義和DiskTest一致,同樣它也存在Bug。
細節
詳細如下:
| ? SHELLPROCAPI ShellProc(UINT uMsg, SPPARAM spParam) { ??? LPSPS_BEGIN_TEST??? pBT; ??? LPSPS_END_TEST????? pET; ?????? ??? switch (uMsg) ??? { ?????? case SPM_SHELL_INFO: ????????????? // Sent once to the DLL immediately after SPM_LOAD_DLL to give the DLL ????????????? // some useful information about its parent shell and environment. The ????????????? // spParam parameter will contain a pointer to a SPS_SHELL_INFO ????????????? // structure. The pointer to the structure may be stored for later use ????????????? // as it will remain valid for the life of this Tux Dll. The DLL may ????????????? // return SPR_FAIL to prevent the DLL from continuing to load. ????????????? Debug(TEXT("ShellProc(SPM_SHELL_INFO, ...) called")); ????????????? ????????????? // Store a pointer to our shell info for later use. ????????????? g_pShellInfo = (LPSPS_SHELL_INFO)spParam; ????????????? Initialize();??? ????????????? break; ?????? //... ?????? } ?????? //... }} |
?
?
| //check its profile if(!DeviceIoControl(hDisk, IOCTL_DISK_DEVICE_INFO[Passion3]?, &sdi, sizeof(STORAGEDEVICEINFO), NULL, 0, &cbReturned, NULL)) { ??? g_pKato->Log(LOG_DETAIL, _T("device /"%s/" does not support IOCTL_DISK_DEVICE_INFO (required for /profile option); error %u"), szDisk, GetLastError()); ??? VERIFY(CloseHandle(hDisk)); ??? hDisk = INVALID_HANDLE_VALUE; ??? continue; } else { ??? // check for a profile match ??? if(0 != wcsicmp(_T("FlashDisk"), sdi.szProfile))[Passion4]? ??? { ??????? g_pKato->Log(LOG_DETAIL, _T("device /"%s/" profile /"%s/" does not match specified profile /"FlashDisk/""), szDisk, sdi.szProfile); ??????? VERIFY(CloseHandle(hDisk)); ??????? hDisk = INVALID_HANDLE_VALUE; ??????? continue; ??? } } |
?????? 如果Profile不是FlashDisk,則操作的時候會出現如下的錯誤Log信息:
opening a handle to storage device "msflash" OpenStore("msflash") device "msflash" profile "MSFlash" does not match specified profile "FlashDisk!" !!!msflash is not a MSFlash device, we have to re-enumerate the system to find one!!! ERROR: found no mass storage devices!
!!!ERROR: There's no MSFlash device in the system!!! FLSHWEAR: using "" disk device
?????? 另外,在測試Sector為>=2048的塊設備驅動的時候,該測試Item的1~124項會全部Failed。原因是Tux Dll的設計Bug造成,這部分代碼如下:
?????? 從下面的代碼中可以看到,首先根據測試sector的個數,申請兩段buffer,一段用來存放待寫入的數據,一段用來存放讀出的數據。
然后將寫Buffer pWriteBuffer初始化,并調用Dsk_WriteSectors將數據寫入到塊驅動上;
最后調用Dsk_ReadSectors將數據從塊驅動上讀取,并比較是否一致。
| BOOL ReadWritePerf(HANDLE hDisk, DWORD startSector, DWORD cSectors, DWORD cBytes) { ??? BOOL fRet = FALSE; ??? BYTE *pWriteBuffer = NULL; ??? BYTE *pReadBuffer = NULL; ? ?? ?pWriteBuffer = new BYTE[cBytes]; ??? if(NULL == pWriteBuffer) { ??????? ERRFAIL("new BYTE[]"); ??????? goto done; ??? } ? ??? pReadBuffer = new BYTE[cBytes]; ??? if(NULL == pReadBuffer) { ??????? ERRFAIL("new BYTE[]"); ??????? goto done; ??? } ??? ??? memset(pWriteBuffer, (BYTE)Random(), cBytes); ? ??? if(g_pWritePerfLog) g_pWritePerfLog->StartTick(); ??? if(!Dsk_WriteSectors(hDisk, startSector, cSectors, pWriteBuffer)) { ??????? if(g_pWritePerfLog) g_pWritePerfLog->EndTick(); ??????? ERRFAIL("Dsk_WriteSectors()"); ??????? goto done; ??? } ??? if(g_pWritePerfLog) g_pWritePerfLog->EndTick(); ? ??? if(g_pReadPerfLog) g_pReadPerfLog->StartTick(); ??? if(!Dsk_ReadSectors(hDisk, startSector, cSectors, pReadBuffer)) { ??????? if(g_pReadPerfLog) g_pReadPerfLog->EndTick();??? ??????? ERRFAIL("Dsk_ReadSectors()"); ??????? goto done; ??? } ??? if(g_pReadPerfLog) g_pReadPerfLog->EndTick(); ? ??? if(0 != memcmp(pWriteBuffer, pReadBuffer, cBytes)) { ??????? LOG(L"bad data while reading %u sectors at sector %u", cSectors, startSector); ??????? ERRFAIL("data read is different from data written"); ??????? goto done; ??? } ? ??? if(g_fDelete) { ??????? if(!Dsk_DeleteSectors(hDisk, startSector, cSectors)) { ??????????? ERRFAIL("Dsk_DeleteSectors()"); ??????????? goto done; ??????? } ??? } ? ??? fRet = TRUE; done: ??? if(NULL != pReadBuffer) { ??????? delete[] pReadBuffer; ??? } ??? if(NULL != pWriteBuffer) { ??????? delete[] pWriteBuffer; ??? } ??? return fRet; } |
?????? 上面描述的流程是沒有問題的,但是下面的讀函數Dsk_ReadSectors和寫函數Dsk_WriteSectors卻有問題,即讀寫數據的長度都是cSectors * DEF_SECTOR_SIZE[Passion5]?,而不是cBytes(cSectors*Sector_size)。這將直接影響到上面函數ReadWritePerf中對讀寫數據的比較,導致測試結果出錯。
?????? 簡單說,就是對于Sector為>=512字節的情況,會導致測試Failed。
| BOOL Dsk_WriteSectors(HANDLE hDisk, DWORD startSector, DWORD cSectors, PBYTE pData) { ??? BOOL fRet; ??? SG_REQ sgReq; ??? DWORD cBytes; ? ??? // build sg request buffer -- single sg buffer ??? sgReq.sr_start = startSector; ??? sgReq.sr_num_sec = cSectors; ??? sgReq.sr_num_sg = 1; ??? sgReq.sr_callback = NULL; // no callback under CE ??? sgReq.sr_sglist[0].sb_len = cSectors * DEF_SECTOR_SIZE[Passion6]?; ??? sgReq.sr_sglist[0].sb_buf = pData; ? ??? fRet = DeviceIoControl(hDisk, DISK_IOCTL_WRITE, &sgReq, sizeof(sgReq), NULL, 0, &cBytes, NULL); ? ??? if(FALSE == fRet) { ??????? g_pKato->Log(LOG_COMMENT, L"FAILED: DeviceIoControl(0x%08x, DISK_IOCTL_WRITE) failed error %u", hDisk, GetLastError()); ??????? fRet = DeviceIoControl(hDisk, IOCTL_DISK_WRITE, &sgReq, sizeof(sgReq), NULL, 0, &cBytes, NULL); ??? } ? ??? if(FALSE == fRet) { ??????? g_pKato->Log(LOG_DETAIL, L"FAILED: DeviceIoControl(0x%08x, IOCTL_DISK_WRITE) failed error %u", hDisk, GetLastError()); ??? } ? ??? return fRet; } ? BOOL Dsk_ReadSectors(HANDLE hDisk, DWORD startSector, DWORD cSectors, PBYTE pData) { ??? BOOL fRet; ??? SG_REQ sgReq; ??? DWORD cBytes; ? ??? // build sg request buffer -- single sg buffer ??? sgReq.sr_start = startSector; ??? sgReq.sr_num_sec = cSectors; ??? sgReq.sr_num_sg = 1; ??? sgReq.sr_callback = NULL; // no callback under CE ??? sgReq.sr_sglist[0].sb_len = cSectors * DEF_SECTOR_SIZE[Passion7]?; ??? sgReq.sr_sglist[0].sb_buf = pData; ? ??? fRet = DeviceIoControl(hDisk, DISK_IOCTL_READ, &sgReq, sizeof(sgReq), NULL, 0, &cBytes, NULL); ? ??? if(FALSE == fRet) { ??????? g_pKato->Log(LOG_COMMENT, L"FAILED: DeviceIoControl(0x%08x, DISK_IOCTL_READ) failed error %u", hDisk, GetLastError()); ??????? fRet = DeviceIoControl(hDisk, IOCTL_DISK_READ, &sgReq, sizeof(sgReq), NULL, 0, &cBytes, NULL); ??? } ? ??? if(FALSE == fRet) { ??????? g_pKato->Log(LOG_DETAIL, L"FAILED: DeviceIoControl(0x%08x, IOCTL_DISK_READ) failed error %u", hDisk, GetLastError()); ??? } ??? ??? return fRet; } |
?
?????? 解決方法就是重新Build Flashwear測試的源碼,修改上述的Bug。
5. rw_all及rwtest
這兩種測試的TUX DLL,同樣存在Bug,它只會去以CreateFile的方式打開流驅動,并獲取其操作句柄,實際上對于Mulitple-bin的情況,需要調用OpenStore,這是因為smflash.dll是由storage manager加載。
具體修改的方法在此不再贅述。
?
附注冊表配置:
| ; HIVE BOOT SECTION ? [HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/MSFlash] ?????? "DriverPath"="Drivers//BuiltIn//MSFlash" ?????? "Order"=dword:0 ?????? "MountFlags"=dword:11 ?????? "LoadFlags"=dword:1 ;load synchronously ?????? "BootPhase"=dword:0 ?????? "Flags"=dword:1000 ?????? [HKEY_LOCAL_MACHINE/Drivers/BuiltIn/MSFlash] ?????? "Prefix"="DSK" ?????? "Order"=dword:0 ?????? "Dll"="smflash.dll"??????? ?????? "Profile"="FlashDisk" ?????? "FriendlyName"="MSFLASH Driver" ?????? "BootPhase"=dword:0 IF BSP_USE_HIVE_REGISTRY ?????? "Flags"=dword:1000 ENDIF ?????? [HKEY_LOCAL_MACHINE/System/StorageManager/BinFS] ?????? "FriendlyName"="BIN Filesystem" ?????? "Dll"="binfs.dll" ?????? "Paging"=dword:1 ?????? "Order"=dword:0? ?????? "MountFlags"=dword:10 ;specifies to mount as an external rom file system ????????????????????????????????????????? ;if set to 11, it will be an hidden file system like mitac solution ?????? "BootPhase"=dword:0 ?????? [HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/FlashDisk] ?????? "DefaultFileSystem"="BINFS" ?????? "PartitionDriver"="mspart.dll" ?????? "AutoMount"=dword:1 ?????? "AutoPart"=dword:1 ?????? "Folder"="NandFlash" ?????? "Name"="Microsoft Flash Disk" ?????? "BootPhase"=dword:0 IF BSP_USE_HIVE_REGISTRY ?????? "Flags"=dword:1000 ENDIF ?????? "MountAsHidden"=dword:1 ?????? "MountAsRom"=dword:1 ?????? [HKEY_LOCAL_MACHINE/System/StorageManager/FATFS] ?????? "Flags"=dword:00000014???????????????????? ; FATFS_ENABLE_BACKUP_FAT | FATFS_DISABLE_AUTOSCAN ?????? "CheckForFormat"=dword:1 ?????? "EnableWriteBack"=dword:1 ?????? "MountAsRoot"=dword:1???????????? ; for ROM-only file system??? ?????? "DisableAutoScan"=dword:1 ?????? [HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/FlashDisk/FATFS] ?????? "FriendlyName"="FAT FileSystem" ?????? "Dll"="fatfsd.dll" ?????? "Flags"=dword:00280014 ?????? "Paging"=dword:1 ?????? "CacheSize"=dword:0 ?????? "EnableCacheWarm"=dword:0 ?????? "EnableCache"=dword:1 IF BSP_USE_HIVE_REGISTRY ?????? "MountAsBootable"=dword:1 ;Specifies that the file system may contain the system registry ENDIF ?????? "MountAsRom"=dword:1? ;Specifies to mount as an external ROM file system ?????? "MountAsRoot"=dword:1 ;Specifies to mount as the root of the file system ?????? |
?
任何問題歡迎給我留言或者發郵件到guopeixin@126.com進行討論。
?[Passion1]這個值其實就是通過/store來進行控制
?[Passion2]這里就設Device Name
?[Passion3]這里透過DeviceIoControl調用IOCTL_DISK_DEVICE_INFO?[Passion3]來獲取測試塊驅動的Profile值
?[Passion4]這里是flash wear tux dll的一個Bug,應該將該行代碼注釋掉
?[Passion5]這里的值錯誤,應該根據實際的塊驅動賦值
?[Passion6]這里的值錯誤,應該根據實際的塊驅動賦值
?[Passion7]這里的值同樣錯誤,應該根據實際的塊驅動賦值
總結
以上是生活随笔為你收集整理的cetk使用方法--nand flash测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电视会员层层加码,想要畅通无阻观看所有节
- 下一篇: KITL--概念篇