cetk使用方法--nand flash测试
測(cè)試環(huán)境:
OS:
??? wince5.0
cpu:
??? J9
image:
????ramimage(開(kāi)始是一個(gè)binfs分區(qū)存放ramimage,后面是一個(gè)fat分區(qū)存放user data,它們公用一個(gè)塊驅(qū)動(dòng))
note:
??? 具體測(cè)試command的書寫要參照注冊(cè)表的配置。
??? 本文中頻繁用到的smflash,是設(shè)備名,即傳遞給CreateFile和OpenStore的實(shí)參,如果不確定你塊驅(qū)動(dòng)的設(shè)備名,可以在AP中通過(guò)FindFirstStore以及FindNextStore的方式將其遍歷出來(lái)。
??? 因?yàn)橹鞍l(fā)了一篇存在諸多問(wèn)題,所以重新排版和修改了其中的大部分錯(cuò)誤,并附上我的注冊(cè)表配置。
?
CETK使用方法—NAND Flash(一個(gè)塊驅(qū)動(dòng)并且將Image放到該塊驅(qū)動(dòng)上)
1. 對(duì)測(cè)試有用的TUX關(guān)鍵詞
TUX語(yǔ)法中的關(guān)鍵詞有很多,其中用來(lái)制定傳遞給TUX DLL(即測(cè)試DLL,如flashwear.dll)的關(guān)鍵詞是-c,詳細(xì)解釋如下:
-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.
?????? 在上面的文字中說(shuō)的很清楚,-c用來(lái)傳遞參數(shù)給-d指定的tux dll,如果傳遞的參數(shù)中包含了空格,則應(yīng)用引號(hào)將參數(shù)包起來(lái)。
?????? 如下:
?????? 詳細(xì)的TUX語(yǔ)法參照如下地址:
ms-help://MS.WindowsCE.500/wcedebug5/html/wce50conTuxCommandLineParameters.htm
2. FSD測(cè)試
命令
默認(rèn)命令+-c “-zorch -p msflash”。
細(xì)節(jié)
詳細(xì)解釋如下。
-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
可見(jiàn)參數(shù)-zorch告訴測(cè)試DLL在不備份磁盤數(shù)據(jù)的情況下進(jìn)行測(cè)試。因?yàn)闇y(cè)試會(huì)毀壞測(cè)試磁盤上的文件,所以有此命令參數(shù)。
-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.
可見(jiàn)參數(shù)-p告訴了測(cè)試項(xiàng)到HKEY_LOCAL_MACHINE/System/StorageManager下的哪個(gè)測(cè)試項(xiàng)下搜索相關(guān)信息。
如果磁盤上有多個(gè)分區(qū)的話,還要使用-r傳遞分區(qū)名,相關(guān)解釋如下: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'.
更加詳細(xì)的參數(shù)介紹參照:
ms-help://MS.WindowsCE.500/wcedebug5/html/wce50tskModifyingtheFileSystemDriverTest.htm
3. disktest測(cè)試項(xiàng)
命令:
tux -o -d disktest -c "/disk msflash /oldioctls /maxsectors 128 /store /zorch /profile msflash"
細(xì)節(jié):
從理論上來(lái)說(shuō),TUX調(diào)用disktest.dll對(duì)塊驅(qū)動(dòng)進(jìn)行測(cè)試的時(shí)候,只需要調(diào)用打開(kāi)塊驅(qū)動(dòng)獲取操作Handle,然后調(diào)用DSK_IoControl進(jìn)行讀寫就可以了。但是,實(shí)際操作過(guò)程中發(fā)現(xiàn)由于smflash.dll由Storage Manager進(jìn)行加載,所以無(wú)法使用CreateFile獲取塊驅(qū)動(dòng)的操作句柄,而必須調(diào)用OpenStore。
PB幫助文檔中在介紹通過(guò)傳遞給TUX DLL參數(shù)決定使用CreateFile還是OpenStore打開(kāi)塊驅(qū)動(dòng)的時(shí)候,提到如下內(nèi)容:
/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); ??? } } |
?????? 關(guān)于/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的參數(shù)的話,系統(tǒng)就會(huì)去搜索所有的dsk1~9。其實(shí)不是這么回事,這個(gè)地方有兩個(gè)錯(cuò)誤:
>> /disk的參數(shù)描述不正確
正確的描述應(yīng)該如下:
| 參數(shù) | 獲取塊驅(qū)動(dòng)的操作句柄 |
| /disk | CreateFile(DSK1~9) |
| /disk *** | CreateFile(***) |
| /disk *** /store | OpenStore(***) |
| /disk /store | 通過(guò)設(shè)備管理器發(fā)送STORE_MOUNT_GUID的Store,具體參照DEV_DetectFirstDevice(&STORE_MOUNT_GUID, szDisk, MAX_PATH) |
| /store | 通過(guò)設(shè)備管理器發(fā)送BLOCK_DRIVER_GUID的塊驅(qū)動(dòng),DEV_DetectFirstDevice(&BLOCK_DRIVER_GUID, szDisk, MAX_PATH) |
>> /disk的***描述不正確
?????? ***是任意可以傳遞給OpenStore或者CreateFile的參數(shù)。
?????? 詳細(xì)的參數(shù)如下:
tux -o -d disktest -c "/disk msflash /oldioctls /maxsectors 128 /store /zorch /profile msflash"
?
>> 傳遞Command但是TUX DLL的解析有問(wèn)題
從TUX DLL最開(kāi)始的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> |
?????? 但是有的時(shí)候你給/disk傳遞的參數(shù)TUX DLL解析不出來(lái),經(jīng)過(guò)反復(fù)實(shí)踐,下面的一條命令是萬(wàn)能命令:
tux -o -d disktest -c "/disk msflash /oldioctls /maxsectors 128 /store /zorch /profile msflash"
?????? 保證可以解析出來(lái)device name。
?????? 仔細(xì)的看了看源代碼,但是還是沒(méi)有找到原因。從源代碼上來(lái)看,這些解析工作由函數(shù)ProcessCmdLine調(diào)用類CClParse的成員函數(shù)來(lái)實(shí)現(xiàn),不存在任何問(wèn)題。
4. Flashwear測(cè)試
?
命令
默認(rèn)命令+-c”/zorch /profile msflash /store /disk msflash”或者/disk msflash /repeat 1 /sectors 64 /store都行
同時(shí)需要修改注冊(cè)表。修改Flash注冊(cè)表的Profile為FlashDisk,這是Microsoft Flashwear 測(cè)試DLL的Bug引起的。Flashwear的參數(shù)意義和DiskTest一致,同樣它也存在Bug。
細(xì)節(jié)
詳細(xì)如下:
| ? 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,則操作的時(shí)候會(huì)出現(xiàn)如下的錯(cuò)誤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
?????? 另外,在測(cè)試Sector為>=2048的塊設(shè)備驅(qū)動(dòng)的時(shí)候,該測(cè)試Item的1~124項(xiàng)會(huì)全部Failed。原因是Tux Dll的設(shè)計(jì)Bug造成,這部分代碼如下:
?????? 從下面的代碼中可以看到,首先根據(jù)測(cè)試sector的個(gè)數(shù),申請(qǐng)兩段buffer,一段用來(lái)存放待寫入的數(shù)據(jù),一段用來(lái)存放讀出的數(shù)據(jù)。
然后將寫Buffer pWriteBuffer初始化,并調(diào)用Dsk_WriteSectors將數(shù)據(jù)寫入到塊驅(qū)動(dòng)上;
最后調(diào)用Dsk_ReadSectors將數(shù)據(jù)從塊驅(qū)動(dòng)上讀取,并比較是否一致。
| 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; } |
?????? 上面描述的流程是沒(méi)有問(wèn)題的,但是下面的讀函數(shù)Dsk_ReadSectors和寫函數(shù)Dsk_WriteSectors卻有問(wèn)題,即讀寫數(shù)據(jù)的長(zhǎng)度都是cSectors * DEF_SECTOR_SIZE[Passion5]?,而不是cBytes(cSectors*Sector_size)。這將直接影響到上面函數(shù)ReadWritePerf中對(duì)讀寫數(shù)據(jù)的比較,導(dǎo)致測(cè)試結(jié)果出錯(cuò)。
?????? 簡(jiǎn)單說(shuō),就是對(duì)于Sector為>=512字節(jié)的情況,會(huì)導(dǎo)致測(cè)試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測(cè)試的源碼,修改上述的Bug。
5. rw_all及rwtest
這兩種測(cè)試的TUX DLL,同樣存在Bug,它只會(huì)去以CreateFile的方式打開(kāi)流驅(qū)動(dòng),并獲取其操作句柄,實(shí)際上對(duì)于Mulitple-bin的情況,需要調(diào)用OpenStore,這是因?yàn)?/span>smflash.dll是由storage manager加載。
具體修改的方法在此不再贅述。
?
附注冊(cè)表配置:
| ; 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 ?????? |
?
任何問(wèn)題歡迎給我留言或者發(fā)郵件到guopeixin@126.com進(jìn)行討論。
?[Passion1]這個(gè)值其實(shí)就是通過(guò)/store來(lái)進(jìn)行控制
?[Passion2]這里就設(shè)Device Name
?[Passion3]這里透過(guò)DeviceIoControl調(diào)用IOCTL_DISK_DEVICE_INFO?[Passion3]來(lái)獲取測(cè)試塊驅(qū)動(dòng)的Profile值
?[Passion4]這里是flash wear tux dll的一個(gè)Bug,應(yīng)該將該行代碼注釋掉
?[Passion5]這里的值錯(cuò)誤,應(yīng)該根據(jù)實(shí)際的塊驅(qū)動(dòng)賦值
?[Passion6]這里的值錯(cuò)誤,應(yīng)該根據(jù)實(shí)際的塊驅(qū)動(dòng)賦值
?[Passion7]這里的值同樣錯(cuò)誤,應(yīng)該根據(jù)實(shí)際的塊驅(qū)動(dòng)賦值
總結(jié)
以上是生活随笔為你收集整理的cetk使用方法--nand flash测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 电视会员层层加码,想要畅通无阻观看所有节
- 下一篇: KITL--概念篇