os/kernelhwsrv/kerneltest/e32test/system/d_tick.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\system\d_tick.cpp
sl@0
    15
// LDD for testing tick-based timers
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
#include "platform.h"
sl@0
    20
#include <assp.h>
sl@0
    21
#if defined(__MEIG__)
sl@0
    22
#include <cl7211.h>
sl@0
    23
#elif defined(__MAWD__)
sl@0
    24
#include <windermere.h>
sl@0
    25
#elif defined(__MISA__)
sl@0
    26
#include <sa1100.h>
sl@0
    27
#elif defined(__MCOT__)
sl@0
    28
#include <cotulla.h>
sl@0
    29
#elif defined(__MI920__) || defined(__NI1136__)
sl@0
    30
#include <integratorap.h>
sl@0
    31
#elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) 
sl@0
    32
#include <omap.h>
sl@0
    33
#include <omap_timer.h>
sl@0
    34
#elif defined(__WINS__)
sl@0
    35
#include "nk_priv.h"
sl@0
    36
#elif defined(__RVEMUBOARD__)
sl@0
    37
#include <rvemuboard.h>
sl@0
    38
#elif defined(__NE1_TB__)
sl@0
    39
#include <upd35001_timer.h>
sl@0
    40
#endif
sl@0
    41
#include <kernel/kern_priv.h>
sl@0
    42
#include "d_tick.h"
sl@0
    43
#include "../misc/prbs.h"
sl@0
    44
sl@0
    45
#if defined(__WINS__)
sl@0
    46
typedef Int64 TCounter;
sl@0
    47
typedef Int64 TDelta;
sl@0
    48
#else
sl@0
    49
typedef TUint TCounter;
sl@0
    50
typedef TInt TDelta;
sl@0
    51
#endif
sl@0
    52
sl@0
    53
#if defined(__MISA__)|| defined(__MCOT__)
sl@0
    54
inline TCounter TIMER()
sl@0
    55
	{ return *(volatile TUint*)KHwRwOstOscr; }
sl@0
    56
#endif
sl@0
    57
#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) 
sl@0
    58
inline TCounter TIMER()
sl@0
    59
	{ return TOmapTimer::Timer3Value(); }
sl@0
    60
#endif
sl@0
    61
#ifdef __MAWD__
sl@0
    62
inline TCounter TIMER()
sl@0
    63
	{ return *(volatile TUint*)(KWindBaseAddress+KWindTimer1Value16)&0xffff; }
sl@0
    64
#endif
sl@0
    65
#ifdef __MEIG__
sl@0
    66
inline TCounter TIMER()
sl@0
    67
	{ return *(volatile TUint*)(KEigerBaseAddress+KEigerTimer1Data16)&0xffff; }
sl@0
    68
#endif
sl@0
    69
#if defined(__MI920__) || defined(__NI1136__)
sl@0
    70
inline TCounter TIMER()
sl@0
    71
	{ return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
sl@0
    72
#endif
sl@0
    73
#if defined(__RVEMUBOARD__)
sl@0
    74
inline TCounter TIMER()
sl@0
    75
	{ return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
sl@0
    76
#endif
sl@0
    77
#if defined(__NE1_TB__)
sl@0
    78
inline TCounter TIMER()
sl@0
    79
	{ return NETimer::Timer(2).iTimerCount; }
sl@0
    80
#endif
sl@0
    81
#if defined(__EPOC32__) && defined(__CPU_X86)
sl@0
    82
TCounter TIMER();
sl@0
    83
void SetUpTimerChannel2();
sl@0
    84
#endif
sl@0
    85
#ifdef __WINS__
sl@0
    86
inline TCounter TIMER()
sl@0
    87
	{
sl@0
    88
	LARGE_INTEGER c;
sl@0
    89
	QueryPerformanceCounter(&c);
sl@0
    90
	return c.QuadPart;
sl@0
    91
	}
sl@0
    92
#endif
sl@0
    93
sl@0
    94
#if defined(__MISA__) || defined(__MCOT__)
sl@0
    95
inline TDelta TimeDelta(TCounter initial, TCounter final)
sl@0
    96
	{ return final-initial; }				// SA1100 timer counts up
sl@0
    97
inline TInt LongTimeDelta(TCounter initial, TCounter final, TUint, TUint)
sl@0
    98
	{ return final-initial; }				// SA1100 timer counts up
sl@0
    99
#endif
sl@0
   100
#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
sl@0
   101
inline TDelta TimeDelta(TCounter initial, TCounter final)
sl@0
   102
	{ return initial-final; }				// OMAP timer counts down
sl@0
   103
inline TInt LongTimeDelta(TCounter initial, TCounter final, TUint, TUint)
sl@0
   104
	{ return initial-final; }
sl@0
   105
#endif
sl@0
   106
#if defined(__MI920__) || defined(__NI1136__)
sl@0
   107
inline TDelta TimeDelta(TCounter initial, TCounter final)
sl@0
   108
	{ return (initial-final)&0xffff; }		// Integrator timer counts down
sl@0
   109
TInt LongTimeDelta(TCounter initial, TCounter final, TUint init_ms, TUint final_ms)
sl@0
   110
	{
sl@0
   111
	TUint r=(initial-final)&0xffff;			// Integrator timer counts down
sl@0
   112
	TUint ms=final_ms-init_ms;
sl@0
   113
	ms=2*ms-r;
sl@0
   114
	ms=(ms+32768)&~0xffff;
sl@0
   115
	return r+ms;
sl@0
   116
	}
sl@0
   117
#endif
sl@0
   118
#if defined(__RVEMUBOARD__)
sl@0
   119
inline TDelta TimeDelta(TCounter initial, TCounter final)
sl@0
   120
	{ return (initial-final)&0xffff; }		// Timer counts down
sl@0
   121
TInt LongTimeDelta(TCounter initial, TCounter final, TUint init_ms, TUint final_ms)
sl@0
   122
	{
sl@0
   123
	TUint r=(initial-final)&0xffff;			// Timer counts down
sl@0
   124
	TUint ms=final_ms-init_ms;
sl@0
   125
	ms=2*ms-r;
sl@0
   126
	ms=(ms+32768)&~0xffff;
sl@0
   127
	return r+ms;
sl@0
   128
	}
sl@0
   129
#endif
sl@0
   130
#if defined(__NE1_TB__)
sl@0
   131
inline TDelta TimeDelta(TCounter initial, TCounter final)
sl@0
   132
	{ return final - initial; }
sl@0
   133
inline TDelta LongTimeDelta(TCounter initial, TCounter final, TUint, TUint)
sl@0
   134
	{ return final - initial; }
sl@0
   135
#endif
sl@0
   136
#if defined(__MAWD__) || defined(__MEIG__)
sl@0
   137
inline TDelta TimeDelta(TCounter initial, TCounter final)
sl@0
   138
	{ return (initial-final)&0xffff; }		// Eiger/Windermere timer counts down
sl@0
   139
TInt LongTimeDelta(TCounter initial, TCounter final, TUint init_ms, TUint final_ms)
sl@0
   140
	{
sl@0
   141
	TUint r=(initial-final)&0xffff;			// Eiger/Windermere timer counts down
sl@0
   142
	TUint ms=final_ms-init_ms;
sl@0
   143
	ms=2*ms-r;
sl@0
   144
	ms=(ms+32768)&~0xffff;
sl@0
   145
	return r+ms;
sl@0
   146
	}
sl@0
   147
#endif
sl@0
   148
#if defined(__EPOC32__) && defined(__CPU_X86)
sl@0
   149
TDelta TimeDelta(TUint initial, TUint final)
sl@0
   150
	{
sl@0
   151
	TUint tickdiff=(initial-final)&0xffff;
sl@0
   152
	TUint msdiff=((final>>16)-(initial>>16))&0xffff;
sl@0
   153
	msdiff=1193*msdiff-tickdiff;
sl@0
   154
	msdiff=(msdiff+32768)&~0xffff;
sl@0
   155
	return msdiff+tickdiff;
sl@0
   156
	}
sl@0
   157
sl@0
   158
TInt LongTimeDelta(TUint initial, TUint final, TUint init_ms, TUint final_ms)
sl@0
   159
	{
sl@0
   160
	TUint r=(initial-final)&0xffff;			// PC timer counts down
sl@0
   161
	TUint ms=final_ms-init_ms;
sl@0
   162
	ms=1193*ms-r;
sl@0
   163
	ms=(ms+32768)&~0xffff;
sl@0
   164
	return r+ms;
sl@0
   165
	}
sl@0
   166
#endif
sl@0
   167
#ifdef __WINS__
sl@0
   168
inline TDelta TimeDelta(TCounter initial, TCounter final)
sl@0
   169
	{ return final-initial; }		// counts up
sl@0
   170
inline TDelta LongTimeDelta(TCounter initial, TCounter final, TUint, TUint)
sl@0
   171
	{ return final-initial; }		// counts up
sl@0
   172
#endif
sl@0
   173
sl@0
   174
const TInt KMajorVersionNumber=0;
sl@0
   175
const TInt KMinorVersionNumber=1;
sl@0
   176
const TInt KBuildVersionNumber=1;
sl@0
   177
sl@0
   178
const TInt KDaysFrom0ADTo2000AD=730497;		// See US_TIME.CPP to verify this
sl@0
   179
const TInt KSecondsPerDay=86400;
sl@0
   180
sl@0
   181
TUint TicksToMicroseconds(TDelta aTicks)
sl@0
   182
	{
sl@0
   183
#if defined(__MISA__) || defined(__MCOT__)
sl@0
   184
	Int64 ticks(aTicks);
sl@0
   185
	ticks*=(1000000);
sl@0
   186
	ticks+=KHwOscFreqHz/2;		// 3.6864MHz tick
sl@0
   187
	ticks/=KHwOscFreqHz;
sl@0
   188
	return (TUint)ticks;
sl@0
   189
#endif
sl@0
   190
#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) 
sl@0
   191
	// Timer runs at 12Mhz/32 = 375kHz. Each tick is 2.66...us which is 16/6us
sl@0
   192
	aTicks<<=4;		// * 16
sl@0
   193
	aTicks+=3;	    // rounding to the closest number of us
sl@0
   194
	return (TInt)(aTicks/6);	// us = (ticks*16+3)/6
sl@0
   195
#endif
sl@0
   196
#if defined(__MI920__) || defined(__NI1136__)
sl@0
   197
	aTicks<<=14;	// 1 tick = 32/3 us
sl@0
   198
	aTicks+=768;	// round
sl@0
   199
	return (TInt)(aTicks/1536);
sl@0
   200
#endif
sl@0
   201
#if defined(__RVEMUBOARD__)
sl@0
   202
	return (TInt)(aTicks*256);  // 1 tick = 256 us
sl@0
   203
#endif
sl@0
   204
#if defined(__NE1_TB__)
sl@0
   205
	NETimer& T2 = NETimer::Timer(2);
sl@0
   206
	TUint prescale = __e32_find_ms1_32(T2.iPrescaler & 0x3f);
sl@0
   207
	TUint f = 66666667 >> prescale;
sl@0
   208
	TUint64 x = I64LIT(1000000);
sl@0
   209
	x *= TUint64(aTicks);
sl@0
   210
	x += TUint64(f>>1);
sl@0
   211
	x /= TUint64(f);
sl@0
   212
	return (TUint)x;
sl@0
   213
#endif
sl@0
   214
#if defined(__MAWD__) || defined(__MEIG__)
sl@0
   215
	return aTicks*500;					// 2kHz tick
sl@0
   216
#endif
sl@0
   217
#if defined(__EPOC32__) && defined(__CPU_X86)
sl@0
   218
	return (aTicks*8381+4190)/10000;
sl@0
   219
#endif
sl@0
   220
#ifdef __WINS__
sl@0
   221
	LARGE_INTEGER f;
sl@0
   222
	QueryPerformanceFrequency(&f);
sl@0
   223
	aTicks*=1000000;
sl@0
   224
	aTicks+=f.QuadPart/2;
sl@0
   225
	aTicks/=f.QuadPart;
sl@0
   226
	return (TUint)aTicks;
sl@0
   227
#endif
sl@0
   228
	}
sl@0
   229
sl@0
   230
class DTick;
sl@0
   231
class TTickTimer
sl@0
   232
	{
sl@0
   233
public:
sl@0
   234
	enum TMode
sl@0
   235
		{
sl@0
   236
		EOneShot,
sl@0
   237
		EPeriodic,
sl@0
   238
		EAbsolute,
sl@0
   239
		ETickDelay,
sl@0
   240
		};
sl@0
   241
public:
sl@0
   242
	TTickTimer();
sl@0
   243
	TInt Start(TInt aMode, TUint aMin, TUint aRange, TInt aCount);
sl@0
   244
	void Cancel();
sl@0
   245
	void CompleteClient(TInt aValue);
sl@0
   246
	static void TickCallBack(TAny* aPtr);
sl@0
   247
	static void SecondCallBack(TAny* aPtr);
sl@0
   248
public:
sl@0
   249
	TTickLink iTickLink;
sl@0
   250
	TSecondLink iSecondLink;
sl@0
   251
	TMode iMode;
sl@0
   252
	TInt iInterval;
sl@0
   253
	TTimeK iExpiryTime;
sl@0
   254
	TUint iMin;
sl@0
   255
	TUint iRange;
sl@0
   256
	TInt iParam;
sl@0
   257
	TCounter iStartTime0;
sl@0
   258
	TUint iStartTime1;
sl@0
   259
	TCounter iStartTime;
sl@0
   260
	TInt iMinErr;
sl@0
   261
	TInt iMaxErr;
sl@0
   262
	Int64 iTotalErr;
sl@0
   263
	TInt iCount;
sl@0
   264
	TInt iRequestedCount;
sl@0
   265
	TInt iIgnore;
sl@0
   266
	DTick* iLdd;
sl@0
   267
	TInt iId;
sl@0
   268
	TClientRequest* iRequest;
sl@0
   269
	};
sl@0
   270
sl@0
   271
class DTickFactory : public DLogicalDevice
sl@0
   272
//
sl@0
   273
// Tick timer LDD factory
sl@0
   274
//
sl@0
   275
	{
sl@0
   276
public:
sl@0
   277
	DTickFactory();
sl@0
   278
	virtual TInt Install();						//overriding pure virtual
sl@0
   279
	virtual void GetCaps(TDes8& aDes) const;	//overriding pure virtual
sl@0
   280
	virtual TInt Create(DLogicalChannelBase*& aChannel);	//overriding pure virtual
sl@0
   281
	};
sl@0
   282
sl@0
   283
class DTick : public DLogicalChannelBase
sl@0
   284
//
sl@0
   285
// Tick timer LDD channel
sl@0
   286
//
sl@0
   287
	{
sl@0
   288
public:
sl@0
   289
	DTick();
sl@0
   290
	~DTick();
sl@0
   291
protected:
sl@0
   292
	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
sl@0
   293
	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
sl@0
   294
public:
sl@0
   295
	void TimerExpired(TInt anId);
sl@0
   296
	inline DThread* Client() { return iThread; }
sl@0
   297
public:
sl@0
   298
	DThread* iThread;
sl@0
   299
	TInt iTickPeriodUs;
sl@0
   300
	TTimeK iYear2000;
sl@0
   301
	TTickTimer iTickTimer[KMaxTimers];
sl@0
   302
	TUint iSeed[2];
sl@0
   303
	};
sl@0
   304
sl@0
   305
TTickTimer::TTickTimer()
sl@0
   306
	:	iMode(EOneShot),
sl@0
   307
		iInterval(0),
sl@0
   308
		iExpiryTime(0),
sl@0
   309
		iMin(0),
sl@0
   310
		iRange(1),
sl@0
   311
		iParam(0),
sl@0
   312
		iStartTime0(0),
sl@0
   313
		iStartTime1(0),
sl@0
   314
		iStartTime(0),
sl@0
   315
		iMinErr(KMaxTInt),
sl@0
   316
		iMaxErr(KMinTInt),
sl@0
   317
		iTotalErr(0),
sl@0
   318
		iCount(0),
sl@0
   319
		iRequestedCount(0),
sl@0
   320
		iIgnore(0),
sl@0
   321
		iLdd(NULL),
sl@0
   322
		iId(0),
sl@0
   323
		iRequest(NULL)
sl@0
   324
	{
sl@0
   325
	}
sl@0
   326
sl@0
   327
void TTickTimer::TickCallBack(TAny* aPtr)
sl@0
   328
	{
sl@0
   329
	TCounter timer_val=TIMER();
sl@0
   330
	TTickTimer& m=*(TTickTimer*)aPtr;
sl@0
   331
	TDelta time=TimeDelta(m.iStartTime, timer_val);
sl@0
   332
	TInt time_us=TicksToMicroseconds(time);
sl@0
   333
	TInt rounded_interval=((m.iInterval+500)/1000)*1000;
sl@0
   334
	TInt error=time_us-rounded_interval;
sl@0
   335
	if (!m.iIgnore)
sl@0
   336
		{
sl@0
   337
		if (error<m.iMinErr)
sl@0
   338
			m.iMinErr=error;
sl@0
   339
		if (error>m.iMaxErr)
sl@0
   340
			m.iMaxErr=error;
sl@0
   341
		m.iTotalErr+=error;
sl@0
   342
		}
sl@0
   343
	if (m.iIgnore==1 && m.iMode==EPeriodic)
sl@0
   344
		{
sl@0
   345
		m.iStartTime0=timer_val;
sl@0
   346
		m.iStartTime1=NKern::TickCount();
sl@0
   347
		}
sl@0
   348
	if ((m.iIgnore && m.iIgnore--) || (++m.iCount<m.iRequestedCount))
sl@0
   349
		{
sl@0
   350
		if (m.iMode==EOneShot)
sl@0
   351
			{
sl@0
   352
			TUint rnd=Random(m.iLdd->iSeed);
sl@0
   353
			TUint ticks=(rnd%m.iRange)+m.iMin;
sl@0
   354
			m.iInterval=ticks*m.iLdd->iTickPeriodUs;
sl@0
   355
			m.iStartTime=TIMER();
sl@0
   356
			m.iTickLink.OneShot(m.iInterval, TickCallBack, &m);
sl@0
   357
			}
sl@0
   358
		else if (m.iMode==ETickDelay)
sl@0
   359
			{
sl@0
   360
			m.iStartTime=TIMER();
sl@0
   361
			m.iTickLink.OneShot(m.iInterval, TickCallBack, &m);
sl@0
   362
			NKern::Sleep(m.iRange);
sl@0
   363
			}
sl@0
   364
		else
sl@0
   365
			m.iStartTime=timer_val;
sl@0
   366
		return;
sl@0
   367
		}
sl@0
   368
	m.CompleteClient(KErrNone);
sl@0
   369
	if (m.iMode==EPeriodic)
sl@0
   370
		{
sl@0
   371
		m.iStartTime0=LongTimeDelta(m.iStartTime0, timer_val, m.iStartTime1, NKern::TickCount());
sl@0
   372
		m.iTickLink.Cancel();
sl@0
   373
		}
sl@0
   374
	}
sl@0
   375
sl@0
   376
void TTickTimer::SecondCallBack(TAny* aPtr)
sl@0
   377
	{
sl@0
   378
	TTickTimer& m=*(TTickTimer*)aPtr;
sl@0
   379
	TTimeK now=Kern::SystemTime();
sl@0
   380
	Int64 error=now-m.iExpiryTime;
sl@0
   381
	if (error>KMaxTInt)
sl@0
   382
		error=KMaxTInt;
sl@0
   383
	if (error<KMinTInt)
sl@0
   384
		error=KMinTInt;
sl@0
   385
	if (error<m.iMinErr)
sl@0
   386
		m.iMinErr=(TInt)error;
sl@0
   387
	if (error>m.iMaxErr)
sl@0
   388
		m.iMaxErr=(TInt)error;
sl@0
   389
	m.iTotalErr+=error;
sl@0
   390
	if (++m.iCount<m.iRequestedCount)
sl@0
   391
		{
sl@0
   392
		TUint rnd=Random(m.iLdd->iSeed);
sl@0
   393
		TUint secs=(rnd%m.iRange)+m.iMin;
sl@0
   394
		m.iExpiryTime=now+secs*1000000+999999;
sl@0
   395
		m.iExpiryTime/=1000000;
sl@0
   396
		m.iExpiryTime*=1000000;
sl@0
   397
		m.iSecondLink.At(m.iExpiryTime, SecondCallBack, &m);
sl@0
   398
		return;
sl@0
   399
		}
sl@0
   400
	m.CompleteClient(KErrNone);
sl@0
   401
	}
sl@0
   402
sl@0
   403
TInt TTickTimer::Start(TInt aMode, TUint a1, TUint a2, TInt aCount)
sl@0
   404
	{
sl@0
   405
	TInt r=KErrGeneral;
sl@0
   406
	iMode=(TMode)aMode;
sl@0
   407
	iMin=a1;
sl@0
   408
	iRange=a2;
sl@0
   409
	iMinErr=KMaxTInt;
sl@0
   410
	iMaxErr=KMinTInt;
sl@0
   411
	iTotalErr=0;
sl@0
   412
	iCount=0;
sl@0
   413
	iRequestedCount=aCount;
sl@0
   414
	switch (aMode)
sl@0
   415
		{
sl@0
   416
		case EOneShot:
sl@0
   417
			{
sl@0
   418
			TUint rnd=Random(iLdd->iSeed);
sl@0
   419
			TUint ticks=(rnd%iRange)+iMin;
sl@0
   420
			iInterval=ticks*iLdd->iTickPeriodUs;
sl@0
   421
			iStartTime=TIMER();
sl@0
   422
			iStartTime0=0;
sl@0
   423
			iStartTime1=0;
sl@0
   424
			iTickLink.OneShot(iInterval, TickCallBack, this);
sl@0
   425
			iIgnore=Min(aCount-1,1);
sl@0
   426
			r=KErrNone;
sl@0
   427
			break;
sl@0
   428
			}
sl@0
   429
		case EPeriodic:
sl@0
   430
			{
sl@0
   431
			iInterval=iMin*iLdd->iTickPeriodUs;
sl@0
   432
			iStartTime=TIMER();
sl@0
   433
			iStartTime0=iStartTime;
sl@0
   434
			iStartTime1=NKern::TickCount();
sl@0
   435
			iTickLink.Periodic(iInterval, TickCallBack, this);
sl@0
   436
			iIgnore=Min(aCount-1,1);
sl@0
   437
			r=KErrNone;
sl@0
   438
			break;
sl@0
   439
			}
sl@0
   440
		case EAbsolute:
sl@0
   441
			{
sl@0
   442
			TUint rnd=Random(iLdd->iSeed);
sl@0
   443
			TUint secs=(rnd%iRange)+iMin;
sl@0
   444
			TTimeK now=Kern::SystemTime();
sl@0
   445
			iExpiryTime=now+secs*1000000+999999;
sl@0
   446
			iExpiryTime/=1000000;
sl@0
   447
			iExpiryTime*=1000000;
sl@0
   448
			iSecondLink.At(iExpiryTime, SecondCallBack, this);
sl@0
   449
			iIgnore=0;
sl@0
   450
			iStartTime0=0;
sl@0
   451
			iStartTime1=0;
sl@0
   452
			r=KErrNone;
sl@0
   453
			break;
sl@0
   454
			}
sl@0
   455
		case ETickDelay:
sl@0
   456
			{
sl@0
   457
			iInterval=iMin*iLdd->iTickPeriodUs;
sl@0
   458
			iStartTime=TIMER();
sl@0
   459
			iStartTime0=0;
sl@0
   460
			iStartTime1=0;
sl@0
   461
			iTickLink.OneShot(iInterval, TickCallBack, this);
sl@0
   462
			iIgnore=Min(aCount-1,1);
sl@0
   463
			r=KErrNone;
sl@0
   464
			break;
sl@0
   465
			}
sl@0
   466
		default:
sl@0
   467
			break;
sl@0
   468
		}
sl@0
   469
	return r;
sl@0
   470
	}
sl@0
   471
sl@0
   472
void TTickTimer::CompleteClient(TInt aValue)
sl@0
   473
	{
sl@0
   474
	Kern::QueueRequestComplete(iLdd->Client(),iRequest,aValue);
sl@0
   475
	}
sl@0
   476
sl@0
   477
void TTickTimer::Cancel()
sl@0
   478
	{
sl@0
   479
	iTickLink.Cancel();
sl@0
   480
	iSecondLink.Cancel();
sl@0
   481
	CompleteClient(KErrCancel);
sl@0
   482
	}
sl@0
   483
sl@0
   484
DECLARE_STANDARD_LDD()
sl@0
   485
	{
sl@0
   486
    return new DTickFactory;
sl@0
   487
    }
sl@0
   488
sl@0
   489
DTickFactory::DTickFactory()
sl@0
   490
    {
sl@0
   491
    iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
sl@0
   492
    //iParseMask=0;//No units, no info, no PDD
sl@0
   493
    //iUnitsMask=0;//Only one thing
sl@0
   494
    }
sl@0
   495
sl@0
   496
TInt DTickFactory::Create(DLogicalChannelBase*& aChannel)
sl@0
   497
//
sl@0
   498
// Create a new DTick on this logical device
sl@0
   499
//
sl@0
   500
    {
sl@0
   501
	aChannel=new DTick;
sl@0
   502
	return aChannel?KErrNone:KErrNoMemory;
sl@0
   503
    }
sl@0
   504
sl@0
   505
TInt DTickFactory::Install()
sl@0
   506
//
sl@0
   507
// Install the LDD - overriding pure virtual
sl@0
   508
//
sl@0
   509
    {
sl@0
   510
    return SetName(&KTickTestLddName);
sl@0
   511
    }
sl@0
   512
sl@0
   513
void DTickFactory::GetCaps(TDes8& aDes) const
sl@0
   514
//
sl@0
   515
// Get capabilities - overriding pure virtual
sl@0
   516
//
sl@0
   517
    {
sl@0
   518
    TCapsTickTestV01 b;
sl@0
   519
    b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
sl@0
   520
    Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
sl@0
   521
    }
sl@0
   522
sl@0
   523
DTick::DTick()
sl@0
   524
//
sl@0
   525
// Constructor
sl@0
   526
//
sl@0
   527
    {
sl@0
   528
	TInt i;
sl@0
   529
	for (i=0; i<KMaxTimers; i++)
sl@0
   530
		{
sl@0
   531
		iTickTimer[i].iLdd=this;
sl@0
   532
		iTickTimer[i].iId=i;
sl@0
   533
		}
sl@0
   534
	iSeed[0]=NKern::TickCount();
sl@0
   535
	iSeed[1]=0;
sl@0
   536
	iTickPeriodUs=Kern::TickPeriod();
sl@0
   537
sl@0
   538
	// Careful with the constants here or GCC will get it wrong
sl@0
   539
	iYear2000=Int64(KDaysFrom0ADTo2000AD)*Int64(KSecondsPerDay);
sl@0
   540
	iYear2000*=1000000;
sl@0
   541
sl@0
   542
	iThread=&Kern::CurrentThread();
sl@0
   543
	iThread->Open();
sl@0
   544
    }
sl@0
   545
sl@0
   546
TInt DTick::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
sl@0
   547
//
sl@0
   548
// Create channel
sl@0
   549
//
sl@0
   550
    {
sl@0
   551
sl@0
   552
    if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
sl@0
   553
		return KErrNotSupported;
sl@0
   554
sl@0
   555
	for (TInt i=0; i<KMaxTimers; i++)
sl@0
   556
		{
sl@0
   557
		TInt r = Kern::CreateClientRequest(iTickTimer[i].iRequest);
sl@0
   558
		if (r != KErrNone)
sl@0
   559
			return r;
sl@0
   560
		}
sl@0
   561
	
sl@0
   562
#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
sl@0
   563
	// Set up Timer3 as a free-running timer at 12Mhz/32 = 375kHz
sl@0
   564
	TOmapTimer::SetTimer3Ctrl(	TOmapTimer::KHtOSTimer_Cntl_Ar
sl@0
   565
									| TOmapTimer::KHtOSTimer_Cntl_Free
sl@0
   566
									| TOmapTimer::KHtOSTimer_Cntl_ClkEnable );
sl@0
   567
	TOmapTimer::SetTimer3Prescale( TOmapTimer::EPrescaleBy32 );
sl@0
   568
	// Autoreload 0xFFFFFFFF to effectively wrap from zero back to 0xFFFFFFFF
sl@0
   569
	TOmapTimer::SetTimer3LoadTim( 0xFFFFFFFF );
sl@0
   570
	TOmapTimer::StartTimer3();
sl@0
   571
#endif
sl@0
   572
#if defined(__MI920__) || defined(__NI1136__)
sl@0
   573
	// Set up timer 1 as free running 93.75KHz clock
sl@0
   574
    TIntegratorAP::SetTimerLoad(TIntegratorAP::ECounterTimer1, 0);			// start from 0xffff downwards
sl@0
   575
    TIntegratorAP::SetTimerMode(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerModeFreeRunning);
sl@0
   576
    TIntegratorAP::SetTimerPreScale(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerPreScaleDiv256);	// 93.75kHz wrap 699ms
sl@0
   577
    TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EEnable);
sl@0
   578
	TIntegratorAP::DisableIrq(TIntegratorAP::EIrqSet0,EIntIdTimer0);		// make sure timer int is disabled
sl@0
   579
#endif
sl@0
   580
#if defined(__RVEMUBOARD__)
sl@0
   581
	// Switch timer 1 to a 1MHz clock in the system controller Ctrl register
sl@0
   582
	TRvEmuBoard::SetSCCtrl(KTimer1EnSel);
sl@0
   583
sl@0
   584
	// Set up timer 1 as free running 3.90625kHz clock
sl@0
   585
	TRvEmuBoard::SetTimerMode(KHwCounterTimer1, TRvEmuBoard::ETimerModeFreeRunning);
sl@0
   586
	TRvEmuBoard::SetTimerPreScale(KHwCounterTimer1, TRvEmuBoard::ETimerPreScaleDiv256);// 3.90625kHz wrap 16.777s
sl@0
   587
	TRvEmuBoard::EnableTimer(KHwCounterTimer1, TRvEmuBoard::EEnable);
sl@0
   588
#endif
sl@0
   589
#if defined(__NE1_TB__)
sl@0
   590
	// nothing to do since we use fast counter
sl@0
   591
#endif
sl@0
   592
#ifdef __MAWD__
sl@0
   593
	// Set up timer 1 as free running 2kHz clock
sl@0
   594
	TWind::SetBuzzerControl(0);		// disable buzzer
sl@0
   595
	TWind::SetTimer1Control(KWindTimer1ControlTimerEnable);
sl@0
   596
	TWind::SetTimer1Load(0);
sl@0
   597
#endif
sl@0
   598
#ifdef __MEIG__
sl@0
   599
	// Set up timer 1 as free running 2kHz clock
sl@0
   600
	TEiger::ModifyControl21(KEigerControlTimer1PreOrFree|KEigerControlTimer1K512OrK2|
sl@0
   601
							KEigerControlBuzzerToggle|KEigerControlBuzzerTimer1OrToggle,0);
sl@0
   602
	TEiger::SetTimer1Data(0);
sl@0
   603
#endif
sl@0
   604
#if defined(__EPOC32__) && defined(__CPU_X86)
sl@0
   605
	// Set up timer channel 2 as free running counter at 14318180/12 Hz
sl@0
   606
	SetUpTimerChannel2();
sl@0
   607
#endif
sl@0
   608
	return KErrNone;
sl@0
   609
	}
sl@0
   610
sl@0
   611
DTick::~DTick()
sl@0
   612
//
sl@0
   613
// Destructor
sl@0
   614
//
sl@0
   615
    {
sl@0
   616
	TInt i;
sl@0
   617
	for (i=0; i<KMaxTimers; i++)
sl@0
   618
		{
sl@0
   619
		iTickTimer[i].Cancel();
sl@0
   620
		Kern::DestroyClientRequest(iTickTimer[i].iRequest);
sl@0
   621
		}
sl@0
   622
	Kern::SafeClose((DObject*&)iThread, NULL);
sl@0
   623
    }
sl@0
   624
sl@0
   625
TInt DTick::Request(TInt aFunction, TAny* a1, TAny* a2)
sl@0
   626
//
sl@0
   627
// Runs in context of client thread, system unlocked on entry and exit
sl@0
   628
//
sl@0
   629
	{
sl@0
   630
	NKern::ThreadEnterCS();			// stop thread kills
sl@0
   631
	TInt r=KErrNone;
sl@0
   632
	TInt id=(TInt)a1;
sl@0
   633
	TTickTimer& m=iTickTimer[id];
sl@0
   634
	switch (aFunction)
sl@0
   635
		{
sl@0
   636
		case RTickTest::EControlStart:
sl@0
   637
			{
sl@0
   638
			STimerStartInfo info;
sl@0
   639
			kumemget(&info,a2,sizeof(info));
sl@0
   640
			r=m.iRequest->SetStatus(info.iStatus);
sl@0
   641
			if (r==KErrNone)
sl@0
   642
				r=m.Start(info.iMode, info.iMin, info.iRange, info.iCount);
sl@0
   643
			break;
sl@0
   644
			}
sl@0
   645
		case RTickTest::EControlStop:
sl@0
   646
			{
sl@0
   647
			m.Cancel();
sl@0
   648
			break;
sl@0
   649
			}
sl@0
   650
		case RTickTest::EControlGetInfo:
sl@0
   651
			{
sl@0
   652
			STickTestInfo info;
sl@0
   653
			info.iMinErr=m.iMinErr;
sl@0
   654
			info.iMaxErr=m.iMaxErr;
sl@0
   655
			info.iCount=m.iCount;
sl@0
   656
			info.iRequestedCount=m.iRequestedCount;
sl@0
   657
			Int64 avg=m.iTotalErr/m.iCount;
sl@0
   658
			info.iAvgErr=(TInt)avg;
sl@0
   659
			info.iTotalTime=TicksToMicroseconds(m.iStartTime0);
sl@0
   660
			kumemput(a2,&info,sizeof(info));
sl@0
   661
			break;
sl@0
   662
			}
sl@0
   663
		case RTickTest::EControlReadRtc:
sl@0
   664
			{
sl@0
   665
			TInt hwrtc;
sl@0
   666
			Arch::TheAsic()->SystemTimeInSecondsFrom2000(hwrtc);
sl@0
   667
			*(TTimeK*)a1=Kern::SystemTime();
sl@0
   668
			TTimeK hwtimeK=(TTimeK)hwrtc;
sl@0
   669
			hwtimeK*=1000000;
sl@0
   670
			hwtimeK+=iYear2000;
sl@0
   671
			kumemput(a2,&hwtimeK,sizeof(hwtimeK));
sl@0
   672
			break;
sl@0
   673
			}
sl@0
   674
		case RTickTest::EControlGetTickPeriod:
sl@0
   675
			{
sl@0
   676
			r=iTickPeriodUs;
sl@0
   677
			break;
sl@0
   678
			}
sl@0
   679
		default:
sl@0
   680
			r=KErrNotSupported;
sl@0
   681
			break;
sl@0
   682
		}
sl@0
   683
	NKern::ThreadLeaveCS();
sl@0
   684
	return r;
sl@0
   685
	}
sl@0
   686