kerneltest/e32test/pccd/t_nandbm.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 29 743008598095
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32test\pccd\t_nandbm.cpp
// Test read/write performance for NAND drives accessed directly
// through the Local Media Sub-System
// When no command parameter is supplied search for first 
// writeable NAND drive that can be found
// If a drive number parameter in the range 0 - F is provided,
// interpret this as a local drive number in the range 0 - 15
// and test the drive if it is a writeable NAND drive
// Please note that local drive numbers at the Local Media Sub-System 
// level are not the same as drive numbers / drive letters at the 
// File Server level. File Server drive numbers / drive letters fall
// in the range 0 - 25 / a - z. The mapping between local drive numbers 
// and File Server drive numbers / drive letters is defined in 
// estart.txt or its equivalent 
// Use TBusLocalDrive directly and bypass the File Server
// Fill NAND user data drive with data prior to executing actual 
// performance tests. TBusLocalDrive should read from areas that have 
// been written to and are therefore assigned. Where areas are 
// unassigned, XSR FTL returns FFs without accessing the NAND flash 
// hardware. This type of behaviour generates misleadingly quick 
// performance figures
// Test various block sizes in the range 16 - 65536 bytes
// 
//


#include <e32test.h>
#include <f32fsys.h>
#include <e32hal.h>
#include <e32uid.h>
#include <f32dbg.h>


LOCAL_D TBuf<1048576> DataBuf;
LOCAL_D	TBusLocalDrive TheDrive;
LOCAL_D TBool ChangedFlag;
LOCAL_D RFs TheFs;

RTest test(_L("Local NAND Drive BenchMark Test"));

LOCAL_C void DoRead(TInt aReadBlockSize)
//
// Do Read benchmark
//
	{
    TInt msgHandle = KLocalMessageHandle;
	TLocalDriveCapsV2 info;
	TPckg<TLocalDriveCapsV2> infoPckg(info);
	TInt maxSize;
	TheDrive.Caps(infoPckg);
	maxSize=I64LOW(info.iSize);
	TInt count,pos,err;
	count=pos=err=0;

	RTimer timer;
	timer.CreateLocal();
	TRequestStatus reqStat;
	timer.After(reqStat,10000000); // After 10 secs
	while(reqStat==KRequestPending)
		{
		if (TheDrive.Read(pos,aReadBlockSize,&DataBuf,msgHandle,0)==KErrNone)
			count++;
		else
			err++;
		pos+=aReadBlockSize;
		if (pos>=(maxSize-aReadBlockSize))
			pos=0;
		}
#if defined (__WINS__)
	test.Printf(_L("Read %d %d byte blocks in 10 secs\n"),count,aReadBlockSize);
#else
	TBuf<60> buf;
	TReal32 rate=((TReal32)(count*aReadBlockSize))/10240.0F;
	TRealFormat rf(10,2);
	buf.Format(_L("Read %d %d byte blocks in 10 secs ("),count,aReadBlockSize);
	buf.AppendNum(rate,rf);
	buf.Append(_L("Kb/s)\n"));
	test.Printf(buf);
#endif
	test.Printf(_L("Errors:%d\n"),err);
	}

LOCAL_C void DoWrite(TInt aWriteBlockSize)
//
// Do write benchmark
//
	{
    TInt msgHandle = KLocalMessageHandle;
	TLocalDriveCapsV2 info;
	TPckg<TLocalDriveCapsV2> infoPckg(info);
	TInt maxSize;
	TheDrive.Caps(infoPckg);
	maxSize=I64LOW(info.iSize);
	TInt count,pos,err;
	count=pos=err=0;

	RTimer timer;
	timer.CreateLocal();
	TRequestStatus reqStat;
	timer.After(reqStat,10000000); // After 10 secs
	while(reqStat==KRequestPending)
		{
		if (TheDrive.Write(pos,aWriteBlockSize,&DataBuf,msgHandle,0)==KErrNone)
			count++;
		else
			err++;
		pos+=aWriteBlockSize;
		if (pos>=(maxSize-aWriteBlockSize))
			pos=0;
		}
#if defined (__WINS__)
	test.Printf(_L("Write %d %d byte blocks in 10 secs\n"),count,aWriteBlockSize);
#else
	TBuf<60> buf;
	TReal32 rate=((TReal32)(count*aWriteBlockSize))/10240.0F;
	TRealFormat rf(10,2);
	buf.Format(_L("Write %d %d byte blocks in 10 secs ("),count,aWriteBlockSize);
	buf.AppendNum(rate,rf);
	buf.Append(_L("Kb/s)\n"));
	test.Printf(buf);
#endif
	test.Printf(_L("Errors:%d\n"),err);
	}

GLDEF_C TInt E32Main()
    {
	test.Title();

	TBuf<0x100> cmd;
	User::CommandLine(cmd);						// put command line into decriptor
	TLex lex(cmd);
	TPtrC param=lex.NextToken();				// point token at local drive number if any
	test.Printf(_L("Local Drive = %S\r\n"),&param);

	TChar localDrv;
	TInt localDrvNum;
	TBusLocalDrive drive;
	TBool changeFlag;
	TLocalDriveCapsV4 driveCaps;
	TPckg<TLocalDriveCapsV4> capsPckg(driveCaps);
	TInt r;
	
	if (param.Length()==0)
		{
		// locate writeable NAND drive
		for (localDrvNum=0; localDrvNum<KMaxLocalDrives; localDrvNum++)
			{

			r = drive.Connect(localDrvNum,changeFlag);

			if (r!=KErrNone)
				continue;

			r = drive.Caps(capsPckg);
  			drive.Disconnect();
			if ((r==KErrNone)
				&&(driveCaps.iType==EMediaNANDFlash)
				&&!(driveCaps.iMediaAtt&KMediaAttWriteProtected)
				&&(driveCaps.iPartitionType!=KPartitionTypeSymbianCrashLog))
			break;
			}
		if (localDrvNum==16)
			{
			test.Printf(_L("Suitable drive could not be found\r\n"));
			test.Printf(_L("Writeable NAND drive required for test\r\n"));
			return(KErrGeneral);
			}
		}
	else
		{
		// is selected local drive number in the range 0-15
		localDrv=param[0];
		localDrv.UpperCase();
		if (localDrv>='0'&&localDrv<='9')
			{
			localDrvNum=((TInt)localDrv-'0');
			}
		else if (localDrv>='A'&&localDrv<='F')
			{
			localDrvNum=((TInt)localDrv-'A'+10);
			}
		else
			{
			test.Printf(_L("Commandline %S invalid\r\n"), &cmd);
			test.Printf(_L("Usage:\r\n"));
			test.Printf(_L("t_nandbm with no arguments, test first suitable NAND drive \r\n"));
			test.Printf(_L("t_nandbm x, where x = 0-F test local drive number 0-15\r\n"));
			return(KErrGeneral);
			}
		// is selected drive suitable for test
		r = drive.Connect(localDrvNum,changeFlag);
		if(r!=KErrNone)
			{
			test.Printf(_L("Can't connect to drive %d\r\n"), localDrvNum);
			return(KErrGeneral);
			}
		r = drive.Caps(capsPckg);
		if(r!=KErrNone)
			{
			test.Printf(_L("Drive %d caps method error\r\n"), localDrvNum);
			return(KErrGeneral);
			}
 		drive.Disconnect();
		if ((driveCaps.iType!=EMediaNANDFlash)
			||(driveCaps.iMediaAtt&KMediaAttWriteProtected)
			||(driveCaps.iPartitionType==KPartitionTypeSymbianCrashLog))
			{
			test.Printf(_L("Drive %d has unsuitable capabilities\r\n"), localDrvNum);
			test.Printf(_L("Writeable NAND drive required for test\r\n"));
			return(KErrGeneral);
			}

		}

	// Fill the nand user data drive with data so TBusLocalDrive reads 
	// from areas that have been written to and are therefore assigned.
	// Where areas are unassigned, XSR FTL returns FFs without accessing 
	// the NAND flash hardware. This type of behaviour generates misleadingly 
	// quick performance figures.
	TInt writesize=1048576;
	TInt pos = 0;
	TInt msgHandle = KLocalMessageHandle;
	
	TheDrive.Connect(localDrvNum,ChangedFlag);
	test.Printf( _L("Fill up NAND drive %d\r\n"),localDrvNum);
	while(writesize>=1)
		{
		test.Printf( _L("%d byte write to pos %d of NAND drive\r\n"),writesize,pos);
		if (TheDrive.Write(pos,writesize,&DataBuf,msgHandle,0)!=KErrNone)
			{
			writesize/=16;
			}
		else
			{
			pos += writesize;
			}
		}

	test.Start(_L("Start Benchmarking ..."));

	DoRead(16);
	DoRead(256);
	DoRead(512);
	DoRead(513);
	DoRead(2048);
	DoRead(4096);
	DoRead(16384);
	DoRead(32768);
	DoRead(65536);

	DoWrite(16);
	DoWrite(256);
	DoWrite(512);
	DoWrite(513); 
	DoWrite(2048);
	DoWrite(4096);
	DoWrite(16384);
	DoWrite(32768);
	DoWrite(65536);
    
	test.End();

	TheFs.Close();

	return(KErrNone);
	}