|
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\misc\d_rndtim.cpp |
|
15 // LDD for generating random interrupts |
|
16 // |
|
17 // |
|
18 |
|
19 #include "platform.h" |
|
20 #include <kernel/kern_priv.h> |
|
21 #include "d_rndtim.h" |
|
22 #include "../misc/prbs.h" |
|
23 |
|
24 #if defined(__MAWD__) |
|
25 #include <windermere.h> |
|
26 #elif defined(__MISA__) |
|
27 #define INT_ID KIntIdOstMatchGeneral |
|
28 #include <sa1100.h> |
|
29 #elif defined(__MCOT__) |
|
30 #define INT_ID KIntIdOstMatchGeneral |
|
31 #include <cotulla.h> |
|
32 #elif defined(__MI920__) || defined(__NI1136__) |
|
33 #include <integratorap.h> |
|
34 #elif defined(__EPOC32__) && defined(__CPU_X86) |
|
35 #include <x86.h> |
|
36 #endif |
|
37 |
|
38 #ifndef INT_ID |
|
39 #error Random timer ISR not supported on this platform |
|
40 #endif |
|
41 |
|
42 |
|
43 const TInt KMajorVersionNumber=0; |
|
44 const TInt KMinorVersionNumber=1; |
|
45 const TInt KBuildVersionNumber=1; |
|
46 |
|
47 class DRndTimFactory : public DLogicalDevice |
|
48 // |
|
49 // IPC copy LDD factory |
|
50 // |
|
51 { |
|
52 public: |
|
53 DRndTimFactory(); |
|
54 virtual TInt Install(); //overriding pure virtual |
|
55 virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual |
|
56 virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual |
|
57 }; |
|
58 |
|
59 class DRndTim : public DLogicalChannelBase |
|
60 // |
|
61 // Millisecond timer LDD channel |
|
62 // |
|
63 { |
|
64 public: |
|
65 DRndTim(); |
|
66 virtual ~DRndTim(); |
|
67 protected: |
|
68 virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer); |
|
69 virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2); |
|
70 public: |
|
71 static void TimerIsr(TAny* aPtr); |
|
72 static void IDfcFn(TAny* aPtr); |
|
73 void StartTimer(); |
|
74 void StopTimer(); |
|
75 TInt SetPriority(TInt aHandle, TInt aPriority); |
|
76 TInt Calibrate(TInt aMilliseconds); |
|
77 public: |
|
78 TInt iIntId; |
|
79 NFastSemaphore iSem; |
|
80 volatile TUint32 iSeed[2]; |
|
81 volatile TUint32 iIsrCount; |
|
82 DThread* iThread; |
|
83 TDfc iIDfc; |
|
84 }; |
|
85 |
|
86 DECLARE_STANDARD_LDD() |
|
87 { |
|
88 return new DRndTimFactory; |
|
89 } |
|
90 |
|
91 DRndTimFactory::DRndTimFactory() |
|
92 // |
|
93 // Constructor |
|
94 // |
|
95 { |
|
96 iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
97 //iParseMask=0;//No units, no info, no PDD |
|
98 //iUnitsMask=0;//Only one thing |
|
99 } |
|
100 |
|
101 TInt DRndTimFactory::Create(DLogicalChannelBase*& aChannel) |
|
102 // |
|
103 // Create a new DRndTim on this logical device |
|
104 // |
|
105 { |
|
106 aChannel=new DRndTim; |
|
107 return aChannel?KErrNone:KErrNoMemory; |
|
108 } |
|
109 |
|
110 TInt DRndTimFactory::Install() |
|
111 // |
|
112 // Install the LDD - overriding pure virtual |
|
113 // |
|
114 { |
|
115 return SetName(&KRndTimLddName); |
|
116 } |
|
117 |
|
118 void DRndTimFactory::GetCaps(TDes8& aDes) const |
|
119 // |
|
120 // Get capabilities - overriding pure virtual |
|
121 // |
|
122 { |
|
123 TCapsRndTimV01 b; |
|
124 b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
125 Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b)); |
|
126 } |
|
127 |
|
128 DRndTim::DRndTim() |
|
129 // |
|
130 // Constructor |
|
131 // |
|
132 : iIntId(-1), |
|
133 iIDfc(&IDfcFn, this) |
|
134 { |
|
135 iThread=&Kern::CurrentThread(); |
|
136 iThread->Open(); |
|
137 iSem.iOwningThread = &iThread->iNThread; |
|
138 iSeed[0] = 0xb504f333u; |
|
139 iSeed[1] = 0xf9de6484u; |
|
140 } |
|
141 |
|
142 DRndTim::~DRndTim() |
|
143 { |
|
144 StopTimer(); |
|
145 if (iIntId >= 0) |
|
146 Interrupt::Unbind(iIntId); |
|
147 Kern::SafeClose((DObject*&)iThread, NULL); |
|
148 } |
|
149 |
|
150 TInt DRndTim::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer) |
|
151 // |
|
152 // Create channel |
|
153 // |
|
154 { |
|
155 |
|
156 if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer)) |
|
157 return KErrNotSupported; |
|
158 StopTimer(); |
|
159 TInt r = Interrupt::Bind(INT_ID, &TimerIsr, this); |
|
160 if (r == KErrNone) |
|
161 iIntId = INT_ID; |
|
162 return r; |
|
163 } |
|
164 |
|
165 TInt DRndTim::Request(TInt aFunction, TAny* a1, TAny* a2) |
|
166 { |
|
167 TInt r = KErrNotSupported; |
|
168 switch (aFunction) |
|
169 { |
|
170 case RRndTim::EControlWait: |
|
171 NKern::FSWait(&iSem); |
|
172 r = KErrNone; |
|
173 break; |
|
174 case RRndTim::EControlSetPriority: |
|
175 r = SetPriority(TInt(a1), TInt(a2)); |
|
176 break; |
|
177 case RRndTim::EControlStartTimer: |
|
178 NKern::ThreadEnterCS(); |
|
179 StartTimer(); |
|
180 NKern::ThreadLeaveCS(); |
|
181 break; |
|
182 case RRndTim::EControlStopTimer: |
|
183 NKern::ThreadEnterCS(); |
|
184 StopTimer(); |
|
185 NKern::ThreadLeaveCS(); |
|
186 break; |
|
187 case RRndTim::EControlCalibrate: |
|
188 NKern::ThreadEnterCS(); |
|
189 r = Calibrate(TInt(a1)); |
|
190 NKern::ThreadLeaveCS(); |
|
191 break; |
|
192 default: |
|
193 break; |
|
194 } |
|
195 return r; |
|
196 } |
|
197 |
|
198 TInt DRndTim::SetPriority(TInt aHandle, TInt aPriority) |
|
199 { |
|
200 TInt r = KErrBadHandle; |
|
201 DThread& c = Kern::CurrentThread(); |
|
202 NKern::ThreadEnterCS(); |
|
203 NKern::LockSystem(); |
|
204 DThread* t = (DThread*)Kern::ObjectFromHandle(&c, aHandle, EThread); |
|
205 if (t && !t->Open()) |
|
206 { |
|
207 NKern::UnlockSystem(); |
|
208 r = Kern::SetThreadPriority(aPriority, t); |
|
209 t->Close(NULL); |
|
210 } |
|
211 else |
|
212 NKern::UnlockSystem(); |
|
213 NKern::ThreadLeaveCS(); |
|
214 return r; |
|
215 } |
|
216 |
|
217 TInt DRndTim::Calibrate(TInt aMilliseconds) |
|
218 { |
|
219 TUint32 n1, n2; |
|
220 TInt ticks = NKern::TimerTicks(aMilliseconds); |
|
221 n1 = iIsrCount; |
|
222 NKern::Sleep(ticks); |
|
223 n2 = iIsrCount; |
|
224 return (TInt)(n2-n1); |
|
225 } |
|
226 |
|
227 void DRndTim::StartTimer() |
|
228 { |
|
229 #if defined(__MISA__) |
|
230 // for SA11x0 use OST match 0 |
|
231 TSa1100::ModifyIntLevels(0,KHtIntsOstMatchGeneral); // route new timer interrupt to FIQ |
|
232 TSa1100::SetOstMatchEOI(KHwOstMatchGeneral); |
|
233 TUint oscr=TSa1100::OstData(); |
|
234 TSa1100::SetOstMatch(KHwOstMatchGeneral, oscr + 5000); |
|
235 TSa1100::EnableOstInterrupt(KHwOstMatchGeneral); |
|
236 #elif defined(__MCOT__) |
|
237 // for SA11x0 use OST match 0 |
|
238 TCotulla::ModifyIntLevels(0,KHtIntsOstMatchGeneral); // route new timer interrupt to FIQ |
|
239 TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); |
|
240 TUint oscr=TCotulla::OstData(); |
|
241 TCotulla::SetOstMatch(KHwOstMatchGeneral, oscr + 5000); |
|
242 TCotulla::EnableOstInterrupt(KHwOstMatchGeneral); |
|
243 #endif |
|
244 Interrupt::Enable(INT_ID); |
|
245 } |
|
246 |
|
247 void DRndTim::StopTimer() |
|
248 { |
|
249 #if defined(__MISA__) |
|
250 Interrupt::Disable(KIntIdOstMatchGeneral); |
|
251 TSa1100::DisableOstInterrupt(KHwOstMatchGeneral); |
|
252 TSa1100::SetOstMatchEOI(KHwOstMatchGeneral); |
|
253 #elif defined(__MCOT__) |
|
254 Interrupt::Disable(KIntIdOstMatchGeneral); |
|
255 TCotulla::DisableOstInterrupt(KHwOstMatchGeneral); |
|
256 TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); |
|
257 #endif |
|
258 } |
|
259 |
|
260 void DRndTim::TimerIsr(TAny* aPtr) |
|
261 { |
|
262 DRndTim* d = (DRndTim*)aPtr; |
|
263 ++d->iIsrCount; |
|
264 #if defined(__MISA__) |
|
265 TUint interval = Random((TUint*)d->iSeed); |
|
266 interval &= 0x3ff; |
|
267 interval += 256; // 256-1279 ticks = approx 69 to 347 microseconds |
|
268 TUint oscr=TSa1100::OstData(); |
|
269 TSa1100::SetOstMatch(KHwOstMatchGeneral, oscr + interval); |
|
270 TSa1100::SetOstMatchEOI(KHwOstMatchGeneral); |
|
271 #elif defined(__MCOT__) |
|
272 TUint interval = Random((TUint*)d->iSeed); |
|
273 interval &= 0x3ff; |
|
274 interval += 256; // 256-1279 ticks = approx 69 to 347 microseconds |
|
275 TUint oscr=TCotulla::OstData(); |
|
276 TCotulla::SetOstMatch(KHwOstMatchGeneral, oscr + interval); |
|
277 TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); |
|
278 #endif |
|
279 d->iIDfc.Add(); |
|
280 } |
|
281 |
|
282 void DRndTim::IDfcFn(TAny* aPtr) |
|
283 { |
|
284 DRndTim* d = (DRndTim*)aPtr; |
|
285 d->iSem.Signal(); |
|
286 } |
|
287 |
|
288 |