cetk使用方法--nand flash测试

来源:互联网 发布:mac卸载java 编辑:程序博客网 时间:2024/05/21 14:01

测试环境:

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在不备份磁盘数据的情况下进行测试。因为测试会毁坏测试磁盘上的文件,所以有此命令参数。

-pSpecify 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.dllStorage 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_GUIDStore,具体参照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注册表的ProfileFlashDisk,这是Microsoft Flashwear 测试DLLBug引起的。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的块设备驱动的时候,该测试Item1~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] ,而不是cBytescSectors*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_allrwtest

这两种测试的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]这里的值同样错误,应该根据实际的块驱动赋值