sl@0
|
1 |
// Copyright (c) 2003-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\benchmark\bm_mcot_pdd.cpp
|
sl@0
|
15 |
// PDD to provide OS timer services to benchmark programs
|
sl@0
|
16 |
//
|
sl@0
|
17 |
//
|
sl@0
|
18 |
|
sl@0
|
19 |
#include <kernel/kernel.h>
|
sl@0
|
20 |
#include <cotulla.h>
|
sl@0
|
21 |
|
sl@0
|
22 |
|
sl@0
|
23 |
#include "k32bm.h"
|
sl@0
|
24 |
|
sl@0
|
25 |
class DBMMcotDevice : public DPhysicalDevice
|
sl@0
|
26 |
{
|
sl@0
|
27 |
public:
|
sl@0
|
28 |
DBMMcotDevice();
|
sl@0
|
29 |
virtual TInt Install();
|
sl@0
|
30 |
virtual void GetCaps(TDes8& aDes) const;
|
sl@0
|
31 |
virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
|
sl@0
|
32 |
virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
|
sl@0
|
33 |
};
|
sl@0
|
34 |
|
sl@0
|
35 |
class DBMMcotChannel : public DBMPChannel
|
sl@0
|
36 |
{
|
sl@0
|
37 |
public:
|
sl@0
|
38 |
DBMMcotChannel();
|
sl@0
|
39 |
~DBMMcotChannel();
|
sl@0
|
40 |
|
sl@0
|
41 |
// Report timing spec
|
sl@0
|
42 |
virtual TBMTicks TimerPeriod();
|
sl@0
|
43 |
// Get current OST tick time
|
sl@0
|
44 |
virtual TBMTicks TimerStamp();
|
sl@0
|
45 |
// Tick/nS conversions
|
sl@0
|
46 |
virtual TBMNs TimerTicksToNs(TBMTicks);
|
sl@0
|
47 |
virtual TBMTicks TimerNsToTicks(TBMNs);
|
sl@0
|
48 |
// Pass in client ISRs to invoke
|
sl@0
|
49 |
virtual TInt BindInterrupt(MBMIsr*);
|
sl@0
|
50 |
virtual TInt BindInterrupt(MBMInterruptLatencyIsr*);
|
sl@0
|
51 |
// Invoke an ISR
|
sl@0
|
52 |
virtual void RequestInterrupt();
|
sl@0
|
53 |
virtual void CancelInterrupt();
|
sl@0
|
54 |
|
sl@0
|
55 |
private:
|
sl@0
|
56 |
|
sl@0
|
57 |
// Attach to OST interrupt
|
sl@0
|
58 |
TInt BindInterrupt();
|
sl@0
|
59 |
|
sl@0
|
60 |
static const TInt KBMMcotInterruptDelayTicks = KHwOscFreqHz / 1000; // ie. delay ~ 1 ms timer tick!
|
sl@0
|
61 |
static const TBMTicks KBMMcotPeriod = (((TBMTicks) 1) << 32);
|
sl@0
|
62 |
static const TBMNs KBMMcotNsPerTick = (1000*1000*1000) / KHwOscFreqHz;
|
sl@0
|
63 |
|
sl@0
|
64 |
// Real ISR (calls out to client)
|
sl@0
|
65 |
static void Isr(TAny*);
|
sl@0
|
66 |
|
sl@0
|
67 |
MBMIsr* iIsr;
|
sl@0
|
68 |
MBMInterruptLatencyIsr* iInterruptLatencyIsr;
|
sl@0
|
69 |
};
|
sl@0
|
70 |
|
sl@0
|
71 |
// Standard boiler plate PDD factory object
|
sl@0
|
72 |
|
sl@0
|
73 |
DECLARE_STANDARD_PDD()
|
sl@0
|
74 |
//
|
sl@0
|
75 |
// Create a new device
|
sl@0
|
76 |
//
|
sl@0
|
77 |
{
|
sl@0
|
78 |
__ASSERT_CRITICAL;
|
sl@0
|
79 |
return new DBMMcotDevice;
|
sl@0
|
80 |
}
|
sl@0
|
81 |
|
sl@0
|
82 |
DBMMcotDevice::DBMMcotDevice()
|
sl@0
|
83 |
//
|
sl@0
|
84 |
// Constructor
|
sl@0
|
85 |
//
|
sl@0
|
86 |
{
|
sl@0
|
87 |
//iUnitsMask=0;
|
sl@0
|
88 |
iVersion = TVersion(1,0,1);
|
sl@0
|
89 |
}
|
sl@0
|
90 |
|
sl@0
|
91 |
TInt DBMMcotDevice::Install()
|
sl@0
|
92 |
//
|
sl@0
|
93 |
// Install the device driver.
|
sl@0
|
94 |
//
|
sl@0
|
95 |
{
|
sl@0
|
96 |
TInt r = SetName(&KBMPdName);
|
sl@0
|
97 |
return r;
|
sl@0
|
98 |
}
|
sl@0
|
99 |
|
sl@0
|
100 |
void DBMMcotDevice::GetCaps(TDes8& aDes) const
|
sl@0
|
101 |
//
|
sl@0
|
102 |
// Return the Comm capabilities.
|
sl@0
|
103 |
//
|
sl@0
|
104 |
{
|
sl@0
|
105 |
}
|
sl@0
|
106 |
|
sl@0
|
107 |
TInt DBMMcotDevice::Create(DBase*& aChannel, TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
|
sl@0
|
108 |
//
|
sl@0
|
109 |
// Create a channel on the device.
|
sl@0
|
110 |
//
|
sl@0
|
111 |
{
|
sl@0
|
112 |
__ASSERT_CRITICAL;
|
sl@0
|
113 |
aChannel = new DBMMcotChannel;
|
sl@0
|
114 |
return aChannel?KErrNone:KErrNoMemory;
|
sl@0
|
115 |
}
|
sl@0
|
116 |
|
sl@0
|
117 |
TInt DBMMcotDevice::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
|
sl@0
|
118 |
{
|
sl@0
|
119 |
if (!Kern::QueryVersionSupported(iVersion,aVer))
|
sl@0
|
120 |
{
|
sl@0
|
121 |
return KErrNotSupported;
|
sl@0
|
122 |
}
|
sl@0
|
123 |
return KErrNone;
|
sl@0
|
124 |
}
|
sl@0
|
125 |
|
sl@0
|
126 |
// Actual device channel functions, called by LDD
|
sl@0
|
127 |
|
sl@0
|
128 |
// Clear saved ISR members
|
sl@0
|
129 |
DBMMcotChannel::DBMMcotChannel()
|
sl@0
|
130 |
{
|
sl@0
|
131 |
// iIsr = NULL;
|
sl@0
|
132 |
// iInterruptLatencyIsr = NULL;
|
sl@0
|
133 |
}
|
sl@0
|
134 |
|
sl@0
|
135 |
// If we ever initialised the timers to generate ISRs, clear
|
sl@0
|
136 |
DBMMcotChannel::~DBMMcotChannel()
|
sl@0
|
137 |
{
|
sl@0
|
138 |
if (iIsr || iInterruptLatencyIsr)
|
sl@0
|
139 |
{
|
sl@0
|
140 |
TCotulla::DisableOstInterrupt(KHwOstMatchGeneral);
|
sl@0
|
141 |
TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
|
sl@0
|
142 |
Interrupt::Disable(KIntIdOstMatchGeneral);
|
sl@0
|
143 |
TCotulla::ModifyIntLevels(KHtIntsOstMatchGeneral,0);
|
sl@0
|
144 |
Interrupt::Unbind(KIntIdOstMatchGeneral);
|
sl@0
|
145 |
}
|
sl@0
|
146 |
}
|
sl@0
|
147 |
|
sl@0
|
148 |
TBMTicks DBMMcotChannel::TimerPeriod()
|
sl@0
|
149 |
{
|
sl@0
|
150 |
return KBMMcotPeriod;
|
sl@0
|
151 |
}
|
sl@0
|
152 |
|
sl@0
|
153 |
// Read OST and return tick count
|
sl@0
|
154 |
TBMTicks DBMMcotChannel::TimerStamp()
|
sl@0
|
155 |
{
|
sl@0
|
156 |
return TUint(TCotulla::OstData());
|
sl@0
|
157 |
}
|
sl@0
|
158 |
|
sl@0
|
159 |
TBMNs DBMMcotChannel::TimerTicksToNs(TBMTicks ticks)
|
sl@0
|
160 |
{
|
sl@0
|
161 |
return ticks * KBMMcotNsPerTick;
|
sl@0
|
162 |
}
|
sl@0
|
163 |
|
sl@0
|
164 |
TBMTicks DBMMcotChannel::TimerNsToTicks(TBMNs ns)
|
sl@0
|
165 |
{
|
sl@0
|
166 |
return ns / KBMMcotNsPerTick;
|
sl@0
|
167 |
}
|
sl@0
|
168 |
|
sl@0
|
169 |
// Actual ISR called when benchmark timer fires
|
sl@0
|
170 |
void DBMMcotChannel::Isr(TAny* ptr)
|
sl@0
|
171 |
{
|
sl@0
|
172 |
DBMMcotChannel* mCh = (DBMMcotChannel*) ptr;
|
sl@0
|
173 |
BM_ASSERT(mCh->iIsr || mCh->iInterruptLatencyIsr);
|
sl@0
|
174 |
if (mCh->iIsr)
|
sl@0
|
175 |
{
|
sl@0
|
176 |
// Call the handler with the current OST time
|
sl@0
|
177 |
mCh->iIsr->Isr(TUint(TCotulla::OstData()));
|
sl@0
|
178 |
}
|
sl@0
|
179 |
else
|
sl@0
|
180 |
{
|
sl@0
|
181 |
// Call the handler with the difference between NOW and the time the match timer was set for
|
sl@0
|
182 |
// ie. the latency between the timer interrupt set and when it was called.
|
sl@0
|
183 |
mCh->iInterruptLatencyIsr->InterruptLatencyIsr(TCotulla::OstData() - TCotulla::OstMatch(KHwOstMatchGeneral));
|
sl@0
|
184 |
}
|
sl@0
|
185 |
TCotulla::DisableOstInterrupt(KHwOstMatchGeneral);
|
sl@0
|
186 |
TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
|
sl@0
|
187 |
}
|
sl@0
|
188 |
|
sl@0
|
189 |
|
sl@0
|
190 |
// Bind the OST match interrupt to a FIQ ISR - it will interrupt running IRQ service
|
sl@0
|
191 |
// routines.
|
sl@0
|
192 |
TInt DBMMcotChannel::BindInterrupt()
|
sl@0
|
193 |
{
|
sl@0
|
194 |
TInt r = Interrupt::Bind(KIntIdOstMatchGeneral, Isr, this);
|
sl@0
|
195 |
if (r != KErrNone)
|
sl@0
|
196 |
{
|
sl@0
|
197 |
return r;
|
sl@0
|
198 |
}
|
sl@0
|
199 |
TCotulla::ModifyIntLevels(0, KHtIntsOstMatchGeneral); // route new timer interrupt to FIQ
|
sl@0
|
200 |
TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
|
sl@0
|
201 |
Interrupt::Enable(KIntIdOstMatchGeneral);
|
sl@0
|
202 |
return KErrNone;
|
sl@0
|
203 |
}
|
sl@0
|
204 |
|
sl@0
|
205 |
// NB! Only one of these is ever used per channel opening, ie. the
|
sl@0
|
206 |
// channel must be closed and re-opened between installing client ISR
|
sl@0
|
207 |
TInt DBMMcotChannel::BindInterrupt(MBMIsr* aIsr)
|
sl@0
|
208 |
{
|
sl@0
|
209 |
BM_ASSERT(!iIsr);
|
sl@0
|
210 |
BM_ASSERT(!iInterruptLatencyIsr);
|
sl@0
|
211 |
iIsr = aIsr;
|
sl@0
|
212 |
return BindInterrupt();
|
sl@0
|
213 |
}
|
sl@0
|
214 |
|
sl@0
|
215 |
TInt DBMMcotChannel::BindInterrupt(MBMInterruptLatencyIsr* aIsr)
|
sl@0
|
216 |
{
|
sl@0
|
217 |
BM_ASSERT(!iIsr);
|
sl@0
|
218 |
BM_ASSERT(!iInterruptLatencyIsr);
|
sl@0
|
219 |
iInterruptLatencyIsr = aIsr;
|
sl@0
|
220 |
return BindInterrupt();
|
sl@0
|
221 |
}
|
sl@0
|
222 |
|
sl@0
|
223 |
// Called by client to request an interrupt (ISR/latency ISR) invocation in ~1mS.
|
sl@0
|
224 |
void DBMMcotChannel::RequestInterrupt()
|
sl@0
|
225 |
{
|
sl@0
|
226 |
BM_ASSERT(iIsr || iInterruptLatencyIsr);
|
sl@0
|
227 |
TCotulla::SetOstMatch(TCotulla::OstData()+KBMMcotInterruptDelayTicks,KHwOstMatchGeneral);
|
sl@0
|
228 |
TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
|
sl@0
|
229 |
TCotulla::EnableOstInterrupt(KHwOstMatchGeneral);
|
sl@0
|
230 |
}
|
sl@0
|
231 |
|
sl@0
|
232 |
// Called to cancel if client dies/killed after ISR scheduled ???
|
sl@0
|
233 |
void DBMMcotChannel::CancelInterrupt()
|
sl@0
|
234 |
{
|
sl@0
|
235 |
if (iIsr || iInterruptLatencyIsr)
|
sl@0
|
236 |
{
|
sl@0
|
237 |
TCotulla::DisableOstInterrupt(KHwOstMatchGeneral);
|
sl@0
|
238 |
TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
|
sl@0
|
239 |
}
|
sl@0
|
240 |
}
|
sl@0
|
241 |
|