diff -r 000000000000 -r a41df078684a kerneltest/e32test/system/d_tick.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/system/d_tick.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,686 @@ +// Copyright (c) 1997-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\system\d_tick.cpp +// LDD for testing tick-based timers +// +// + +#include "platform.h" +#include +#if defined(__MEIG__) +#include +#elif defined(__MAWD__) +#include +#elif defined(__MISA__) +#include +#elif defined(__MCOT__) +#include +#elif defined(__MI920__) || defined(__NI1136__) +#include +#elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) +#include +#include +#elif defined(__WINS__) +#include "nk_priv.h" +#elif defined(__RVEMUBOARD__) +#include +#elif defined(__NE1_TB__) +#include +#endif +#include +#include "d_tick.h" +#include "../misc/prbs.h" + +#if defined(__WINS__) +typedef Int64 TCounter; +typedef Int64 TDelta; +#else +typedef TUint TCounter; +typedef TInt TDelta; +#endif + +#if defined(__MISA__)|| defined(__MCOT__) +inline TCounter TIMER() + { return *(volatile TUint*)KHwRwOstOscr; } +#endif +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) +inline TCounter TIMER() + { return TOmapTimer::Timer3Value(); } +#endif +#ifdef __MAWD__ +inline TCounter TIMER() + { return *(volatile TUint*)(KWindBaseAddress+KWindTimer1Value16)&0xffff; } +#endif +#ifdef __MEIG__ +inline TCounter TIMER() + { return *(volatile TUint*)(KEigerBaseAddress+KEigerTimer1Data16)&0xffff; } +#endif +#if defined(__MI920__) || defined(__NI1136__) +inline TCounter TIMER() + { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;} +#endif +#if defined(__RVEMUBOARD__) +inline TCounter TIMER() + { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;} +#endif +#if defined(__NE1_TB__) +inline TCounter TIMER() + { return NETimer::Timer(2).iTimerCount; } +#endif +#if defined(__EPOC32__) && defined(__CPU_X86) +TCounter TIMER(); +void SetUpTimerChannel2(); +#endif +#ifdef __WINS__ +inline TCounter TIMER() + { + LARGE_INTEGER c; + QueryPerformanceCounter(&c); + return c.QuadPart; + } +#endif + +#if defined(__MISA__) || defined(__MCOT__) +inline TDelta TimeDelta(TCounter initial, TCounter final) + { return final-initial; } // SA1100 timer counts up +inline TInt LongTimeDelta(TCounter initial, TCounter final, TUint, TUint) + { return final-initial; } // SA1100 timer counts up +#endif +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) +inline TDelta TimeDelta(TCounter initial, TCounter final) + { return initial-final; } // OMAP timer counts down +inline TInt LongTimeDelta(TCounter initial, TCounter final, TUint, TUint) + { return initial-final; } +#endif +#if defined(__MI920__) || defined(__NI1136__) +inline TDelta TimeDelta(TCounter initial, TCounter final) + { return (initial-final)&0xffff; } // Integrator timer counts down +TInt LongTimeDelta(TCounter initial, TCounter final, TUint init_ms, TUint final_ms) + { + TUint r=(initial-final)&0xffff; // Integrator timer counts down + TUint ms=final_ms-init_ms; + ms=2*ms-r; + ms=(ms+32768)&~0xffff; + return r+ms; + } +#endif +#if defined(__RVEMUBOARD__) +inline TDelta TimeDelta(TCounter initial, TCounter final) + { return (initial-final)&0xffff; } // Timer counts down +TInt LongTimeDelta(TCounter initial, TCounter final, TUint init_ms, TUint final_ms) + { + TUint r=(initial-final)&0xffff; // Timer counts down + TUint ms=final_ms-init_ms; + ms=2*ms-r; + ms=(ms+32768)&~0xffff; + return r+ms; + } +#endif +#if defined(__NE1_TB__) +inline TDelta TimeDelta(TCounter initial, TCounter final) + { return final - initial; } +inline TDelta LongTimeDelta(TCounter initial, TCounter final, TUint, TUint) + { return final - initial; } +#endif +#if defined(__MAWD__) || defined(__MEIG__) +inline TDelta TimeDelta(TCounter initial, TCounter final) + { return (initial-final)&0xffff; } // Eiger/Windermere timer counts down +TInt LongTimeDelta(TCounter initial, TCounter final, TUint init_ms, TUint final_ms) + { + TUint r=(initial-final)&0xffff; // Eiger/Windermere timer counts down + TUint ms=final_ms-init_ms; + ms=2*ms-r; + ms=(ms+32768)&~0xffff; + return r+ms; + } +#endif +#if defined(__EPOC32__) && defined(__CPU_X86) +TDelta TimeDelta(TUint initial, TUint final) + { + TUint tickdiff=(initial-final)&0xffff; + TUint msdiff=((final>>16)-(initial>>16))&0xffff; + msdiff=1193*msdiff-tickdiff; + msdiff=(msdiff+32768)&~0xffff; + return msdiff+tickdiff; + } + +TInt LongTimeDelta(TUint initial, TUint final, TUint init_ms, TUint final_ms) + { + TUint r=(initial-final)&0xffff; // PC timer counts down + TUint ms=final_ms-init_ms; + ms=1193*ms-r; + ms=(ms+32768)&~0xffff; + return r+ms; + } +#endif +#ifdef __WINS__ +inline TDelta TimeDelta(TCounter initial, TCounter final) + { return final-initial; } // counts up +inline TDelta LongTimeDelta(TCounter initial, TCounter final, TUint, TUint) + { return final-initial; } // counts up +#endif + +const TInt KMajorVersionNumber=0; +const TInt KMinorVersionNumber=1; +const TInt KBuildVersionNumber=1; + +const TInt KDaysFrom0ADTo2000AD=730497; // See US_TIME.CPP to verify this +const TInt KSecondsPerDay=86400; + +TUint TicksToMicroseconds(TDelta aTicks) + { +#if defined(__MISA__) || defined(__MCOT__) + Int64 ticks(aTicks); + ticks*=(1000000); + ticks+=KHwOscFreqHz/2; // 3.6864MHz tick + ticks/=KHwOscFreqHz; + return (TUint)ticks; +#endif +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) + // Timer runs at 12Mhz/32 = 375kHz. Each tick is 2.66...us which is 16/6us + aTicks<<=4; // * 16 + aTicks+=3; // rounding to the closest number of us + return (TInt)(aTicks/6); // us = (ticks*16+3)/6 +#endif +#if defined(__MI920__) || defined(__NI1136__) + aTicks<<=14; // 1 tick = 32/3 us + aTicks+=768; // round + return (TInt)(aTicks/1536); +#endif +#if defined(__RVEMUBOARD__) + return (TInt)(aTicks*256); // 1 tick = 256 us +#endif +#if defined(__NE1_TB__) + NETimer& T2 = NETimer::Timer(2); + TUint prescale = __e32_find_ms1_32(T2.iPrescaler & 0x3f); + TUint f = 66666667 >> prescale; + TUint64 x = I64LIT(1000000); + x *= TUint64(aTicks); + x += TUint64(f>>1); + x /= TUint64(f); + return (TUint)x; +#endif +#if defined(__MAWD__) || defined(__MEIG__) + return aTicks*500; // 2kHz tick +#endif +#if defined(__EPOC32__) && defined(__CPU_X86) + return (aTicks*8381+4190)/10000; +#endif +#ifdef __WINS__ + LARGE_INTEGER f; + QueryPerformanceFrequency(&f); + aTicks*=1000000; + aTicks+=f.QuadPart/2; + aTicks/=f.QuadPart; + return (TUint)aTicks; +#endif + } + +class DTick; +class TTickTimer + { +public: + enum TMode + { + EOneShot, + EPeriodic, + EAbsolute, + ETickDelay, + }; +public: + TTickTimer(); + TInt Start(TInt aMode, TUint aMin, TUint aRange, TInt aCount); + void Cancel(); + void CompleteClient(TInt aValue); + static void TickCallBack(TAny* aPtr); + static void SecondCallBack(TAny* aPtr); +public: + TTickLink iTickLink; + TSecondLink iSecondLink; + TMode iMode; + TInt iInterval; + TTimeK iExpiryTime; + TUint iMin; + TUint iRange; + TInt iParam; + TCounter iStartTime0; + TUint iStartTime1; + TCounter iStartTime; + TInt iMinErr; + TInt iMaxErr; + Int64 iTotalErr; + TInt iCount; + TInt iRequestedCount; + TInt iIgnore; + DTick* iLdd; + TInt iId; + TClientRequest* iRequest; + }; + +class DTickFactory : public DLogicalDevice +// +// Tick timer LDD factory +// + { +public: + DTickFactory(); + virtual TInt Install(); //overriding pure virtual + virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual + virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual + }; + +class DTick : public DLogicalChannelBase +// +// Tick timer LDD channel +// + { +public: + DTick(); + ~DTick(); +protected: + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); + virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2); +public: + void TimerExpired(TInt anId); + inline DThread* Client() { return iThread; } +public: + DThread* iThread; + TInt iTickPeriodUs; + TTimeK iYear2000; + TTickTimer iTickTimer[KMaxTimers]; + TUint iSeed[2]; + }; + +TTickTimer::TTickTimer() + : iMode(EOneShot), + iInterval(0), + iExpiryTime(0), + iMin(0), + iRange(1), + iParam(0), + iStartTime0(0), + iStartTime1(0), + iStartTime(0), + iMinErr(KMaxTInt), + iMaxErr(KMinTInt), + iTotalErr(0), + iCount(0), + iRequestedCount(0), + iIgnore(0), + iLdd(NULL), + iId(0), + iRequest(NULL) + { + } + +void TTickTimer::TickCallBack(TAny* aPtr) + { + TCounter timer_val=TIMER(); + TTickTimer& m=*(TTickTimer*)aPtr; + TDelta time=TimeDelta(m.iStartTime, timer_val); + TInt time_us=TicksToMicroseconds(time); + TInt rounded_interval=((m.iInterval+500)/1000)*1000; + TInt error=time_us-rounded_interval; + if (!m.iIgnore) + { + if (errorm.iMaxErr) + m.iMaxErr=error; + m.iTotalErr+=error; + } + if (m.iIgnore==1 && m.iMode==EPeriodic) + { + m.iStartTime0=timer_val; + m.iStartTime1=NKern::TickCount(); + } + if ((m.iIgnore && m.iIgnore--) || (++m.iCountiSeed); + TUint ticks=(rnd%m.iRange)+m.iMin; + m.iInterval=ticks*m.iLdd->iTickPeriodUs; + m.iStartTime=TIMER(); + m.iTickLink.OneShot(m.iInterval, TickCallBack, &m); + } + else if (m.iMode==ETickDelay) + { + m.iStartTime=TIMER(); + m.iTickLink.OneShot(m.iInterval, TickCallBack, &m); + NKern::Sleep(m.iRange); + } + else + m.iStartTime=timer_val; + return; + } + m.CompleteClient(KErrNone); + if (m.iMode==EPeriodic) + { + m.iStartTime0=LongTimeDelta(m.iStartTime0, timer_val, m.iStartTime1, NKern::TickCount()); + m.iTickLink.Cancel(); + } + } + +void TTickTimer::SecondCallBack(TAny* aPtr) + { + TTickTimer& m=*(TTickTimer*)aPtr; + TTimeK now=Kern::SystemTime(); + Int64 error=now-m.iExpiryTime; + if (error>KMaxTInt) + error=KMaxTInt; + if (errorm.iMaxErr) + m.iMaxErr=(TInt)error; + m.iTotalErr+=error; + if (++m.iCountiSeed); + TUint secs=(rnd%m.iRange)+m.iMin; + m.iExpiryTime=now+secs*1000000+999999; + m.iExpiryTime/=1000000; + m.iExpiryTime*=1000000; + m.iSecondLink.At(m.iExpiryTime, SecondCallBack, &m); + return; + } + m.CompleteClient(KErrNone); + } + +TInt TTickTimer::Start(TInt aMode, TUint a1, TUint a2, TInt aCount) + { + TInt r=KErrGeneral; + iMode=(TMode)aMode; + iMin=a1; + iRange=a2; + iMinErr=KMaxTInt; + iMaxErr=KMinTInt; + iTotalErr=0; + iCount=0; + iRequestedCount=aCount; + switch (aMode) + { + case EOneShot: + { + TUint rnd=Random(iLdd->iSeed); + TUint ticks=(rnd%iRange)+iMin; + iInterval=ticks*iLdd->iTickPeriodUs; + iStartTime=TIMER(); + iStartTime0=0; + iStartTime1=0; + iTickLink.OneShot(iInterval, TickCallBack, this); + iIgnore=Min(aCount-1,1); + r=KErrNone; + break; + } + case EPeriodic: + { + iInterval=iMin*iLdd->iTickPeriodUs; + iStartTime=TIMER(); + iStartTime0=iStartTime; + iStartTime1=NKern::TickCount(); + iTickLink.Periodic(iInterval, TickCallBack, this); + iIgnore=Min(aCount-1,1); + r=KErrNone; + break; + } + case EAbsolute: + { + TUint rnd=Random(iLdd->iSeed); + TUint secs=(rnd%iRange)+iMin; + TTimeK now=Kern::SystemTime(); + iExpiryTime=now+secs*1000000+999999; + iExpiryTime/=1000000; + iExpiryTime*=1000000; + iSecondLink.At(iExpiryTime, SecondCallBack, this); + iIgnore=0; + iStartTime0=0; + iStartTime1=0; + r=KErrNone; + break; + } + case ETickDelay: + { + iInterval=iMin*iLdd->iTickPeriodUs; + iStartTime=TIMER(); + iStartTime0=0; + iStartTime1=0; + iTickLink.OneShot(iInterval, TickCallBack, this); + iIgnore=Min(aCount-1,1); + r=KErrNone; + break; + } + default: + break; + } + return r; + } + +void TTickTimer::CompleteClient(TInt aValue) + { + Kern::QueueRequestComplete(iLdd->Client(),iRequest,aValue); + } + +void TTickTimer::Cancel() + { + iTickLink.Cancel(); + iSecondLink.Cancel(); + CompleteClient(KErrCancel); + } + +DECLARE_STANDARD_LDD() + { + return new DTickFactory; + } + +DTickFactory::DTickFactory() + { + iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + //iParseMask=0;//No units, no info, no PDD + //iUnitsMask=0;//Only one thing + } + +TInt DTickFactory::Create(DLogicalChannelBase*& aChannel) +// +// Create a new DTick on this logical device +// + { + aChannel=new DTick; + return aChannel?KErrNone:KErrNoMemory; + } + +TInt DTickFactory::Install() +// +// Install the LDD - overriding pure virtual +// + { + return SetName(&KTickTestLddName); + } + +void DTickFactory::GetCaps(TDes8& aDes) const +// +// Get capabilities - overriding pure virtual +// + { + TCapsTickTestV01 b; + b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b)); + } + +DTick::DTick() +// +// Constructor +// + { + TInt i; + for (i=0; iOpen(); + } + +TInt DTick::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer) +// +// Create channel +// + { + + if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer)) + return KErrNotSupported; + + for (TInt i=0; iSetStatus(info.iStatus); + if (r==KErrNone) + r=m.Start(info.iMode, info.iMin, info.iRange, info.iCount); + break; + } + case RTickTest::EControlStop: + { + m.Cancel(); + break; + } + case RTickTest::EControlGetInfo: + { + STickTestInfo info; + info.iMinErr=m.iMinErr; + info.iMaxErr=m.iMaxErr; + info.iCount=m.iCount; + info.iRequestedCount=m.iRequestedCount; + Int64 avg=m.iTotalErr/m.iCount; + info.iAvgErr=(TInt)avg; + info.iTotalTime=TicksToMicroseconds(m.iStartTime0); + kumemput(a2,&info,sizeof(info)); + break; + } + case RTickTest::EControlReadRtc: + { + TInt hwrtc; + Arch::TheAsic()->SystemTimeInSecondsFrom2000(hwrtc); + *(TTimeK*)a1=Kern::SystemTime(); + TTimeK hwtimeK=(TTimeK)hwrtc; + hwtimeK*=1000000; + hwtimeK+=iYear2000; + kumemput(a2,&hwtimeK,sizeof(hwtimeK)); + break; + } + case RTickTest::EControlGetTickPeriod: + { + r=iTickPeriodUs; + break; + } + default: + r=KErrNotSupported; + break; + } + NKern::ThreadLeaveCS(); + return r; + } +