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