--- /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 <assp.h>
+#if defined(__MEIG__)
+#include <cl7211.h>
+#elif defined(__MAWD__)
+#include <windermere.h>
+#elif defined(__MISA__)
+#include <sa1100.h>
+#elif defined(__MCOT__)
+#include <cotulla.h>
+#elif defined(__MI920__) || defined(__NI1136__)
+#include <integratorap.h>
+#elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+#include <omap.h>
+#include <omap_timer.h>
+#elif defined(__WINS__)
+#include "nk_priv.h"
+#elif defined(__RVEMUBOARD__)
+#include <rvemuboard.h>
+#elif defined(__NE1_TB__)
+#include <upd35001_timer.h>
+#endif
+#include <kernel/kern_priv.h>
+#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 (error<m.iMinErr)
+ m.iMinErr=error;
+ if (error>m.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.iCount<m.iRequestedCount))
+ {
+ if (m.iMode==EOneShot)
+ {
+ TUint rnd=Random(m.iLdd->iSeed);
+ 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 (error<KMinTInt)
+ error=KMinTInt;
+ if (error<m.iMinErr)
+ m.iMinErr=(TInt)error;
+ if (error>m.iMaxErr)
+ m.iMaxErr=(TInt)error;
+ m.iTotalErr+=error;
+ if (++m.iCount<m.iRequestedCount)
+ {
+ TUint rnd=Random(m.iLdd->iSeed);
+ 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; i<KMaxTimers; i++)
+ {
+ iTickTimer[i].iLdd=this;
+ iTickTimer[i].iId=i;
+ }
+ iSeed[0]=NKern::TickCount();
+ iSeed[1]=0;
+ iTickPeriodUs=Kern::TickPeriod();
+
+ // Careful with the constants here or GCC will get it wrong
+ iYear2000=Int64(KDaysFrom0ADTo2000AD)*Int64(KSecondsPerDay);
+ iYear2000*=1000000;
+
+ iThread=&Kern::CurrentThread();
+ iThread->Open();
+ }
+
+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; i<KMaxTimers; i++)
+ {
+ TInt r = Kern::CreateClientRequest(iTickTimer[i].iRequest);
+ if (r != KErrNone)
+ return r;
+ }
+
+#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+ // Set up Timer3 as a free-running timer at 12Mhz/32 = 375kHz
+ TOmapTimer::SetTimer3Ctrl( TOmapTimer::KHtOSTimer_Cntl_Ar
+ | TOmapTimer::KHtOSTimer_Cntl_Free
+ | TOmapTimer::KHtOSTimer_Cntl_ClkEnable );
+ TOmapTimer::SetTimer3Prescale( TOmapTimer::EPrescaleBy32 );
+ // Autoreload 0xFFFFFFFF to effectively wrap from zero back to 0xFFFFFFFF
+ TOmapTimer::SetTimer3LoadTim( 0xFFFFFFFF );
+ TOmapTimer::StartTimer3();
+#endif
+#if defined(__MI920__) || defined(__NI1136__)
+ // Set up timer 1 as free running 93.75KHz clock
+ TIntegratorAP::SetTimerLoad(TIntegratorAP::ECounterTimer1, 0); // start from 0xffff downwards
+ TIntegratorAP::SetTimerMode(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerModeFreeRunning);
+ TIntegratorAP::SetTimerPreScale(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerPreScaleDiv256); // 93.75kHz wrap 699ms
+ TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EEnable);
+ TIntegratorAP::DisableIrq(TIntegratorAP::EIrqSet0,EIntIdTimer0); // make sure timer int is disabled
+#endif
+#if defined(__RVEMUBOARD__)
+ // Switch timer 1 to a 1MHz clock in the system controller Ctrl register
+ TRvEmuBoard::SetSCCtrl(KTimer1EnSel);
+
+ // Set up timer 1 as free running 3.90625kHz clock
+ TRvEmuBoard::SetTimerMode(KHwCounterTimer1, TRvEmuBoard::ETimerModeFreeRunning);
+ TRvEmuBoard::SetTimerPreScale(KHwCounterTimer1, TRvEmuBoard::ETimerPreScaleDiv256);// 3.90625kHz wrap 16.777s
+ TRvEmuBoard::EnableTimer(KHwCounterTimer1, TRvEmuBoard::EEnable);
+#endif
+#if defined(__NE1_TB__)
+ // nothing to do since we use fast counter
+#endif
+#ifdef __MAWD__
+ // Set up timer 1 as free running 2kHz clock
+ TWind::SetBuzzerControl(0); // disable buzzer
+ TWind::SetTimer1Control(KWindTimer1ControlTimerEnable);
+ TWind::SetTimer1Load(0);
+#endif
+#ifdef __MEIG__
+ // Set up timer 1 as free running 2kHz clock
+ TEiger::ModifyControl21(KEigerControlTimer1PreOrFree|KEigerControlTimer1K512OrK2|
+ KEigerControlBuzzerToggle|KEigerControlBuzzerTimer1OrToggle,0);
+ TEiger::SetTimer1Data(0);
+#endif
+#if defined(__EPOC32__) && defined(__CPU_X86)
+ // Set up timer channel 2 as free running counter at 14318180/12 Hz
+ SetUpTimerChannel2();
+#endif
+ return KErrNone;
+ }
+
+DTick::~DTick()
+//
+// Destructor
+//
+ {
+ TInt i;
+ for (i=0; i<KMaxTimers; i++)
+ {
+ iTickTimer[i].Cancel();
+ Kern::DestroyClientRequest(iTickTimer[i].iRequest);
+ }
+ Kern::SafeClose((DObject*&)iThread, NULL);
+ }
+
+TInt DTick::Request(TInt aFunction, TAny* a1, TAny* a2)
+//
+// Runs in context of client thread, system unlocked on entry and exit
+//
+ {
+ NKern::ThreadEnterCS(); // stop thread kills
+ TInt r=KErrNone;
+ TInt id=(TInt)a1;
+ TTickTimer& m=iTickTimer[id];
+ switch (aFunction)
+ {
+ case RTickTest::EControlStart:
+ {
+ STimerStartInfo info;
+ kumemget(&info,a2,sizeof(info));
+ r=m.iRequest->SetStatus(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;
+ }
+