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) 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;
}