|
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\system\d_mstim.cpp |
|
15 // LDD for testing millisecond timer |
|
16 // |
|
17 // |
|
18 |
|
19 #include "plat_priv.h" |
|
20 #if defined(__MEIG__) |
|
21 #include <cl7211.h> |
|
22 #elif defined(__MAWD__) |
|
23 #include <windermere.h> |
|
24 #elif defined(__MISA__) |
|
25 #include <sa1100.h> |
|
26 #elif defined(__MCOT__) |
|
27 #include <cotulla.h> |
|
28 #elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) |
|
29 #include <omap.h> |
|
30 #include <omap_timer.h> |
|
31 #elif defined(__MI920__) || defined(__NI1136__) |
|
32 #ifdef __MI920__ |
|
33 #define USE_CM920_FRC |
|
34 #endif |
|
35 #ifdef USE_CM920_FRC |
|
36 #include <iolines.h> |
|
37 #else |
|
38 #include <integratorap.h> |
|
39 #endif |
|
40 #elif defined(__RVEMUBOARD__) |
|
41 #include <rvemuboard.h> |
|
42 #elif defined(__NE1_TB__) |
|
43 #include <upd35001_timer.h> |
|
44 #endif |
|
45 #include "d_mstim.h" |
|
46 #include "../misc/prbs.h" |
|
47 |
|
48 #if defined(__WINS__) |
|
49 typedef Int64 TCounter; |
|
50 typedef Int64 TDelta; |
|
51 const TDelta KMaxDelta = 0x7fffffffffffffff; |
|
52 const TDelta KMinDelta = 0x8000000000000000; |
|
53 #else |
|
54 typedef TUint TCounter; |
|
55 typedef TInt TDelta; |
|
56 const TDelta KMaxDelta = KMaxTInt; |
|
57 const TDelta KMinDelta = KMinTInt; |
|
58 #endif |
|
59 |
|
60 #ifdef __MISA__ |
|
61 inline TCounter TIMER() |
|
62 { return *(volatile TUint*)KHwRwOstOscr; } |
|
63 #endif |
|
64 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) |
|
65 inline TCounter TIMER() |
|
66 { return TOmapTimer::Timer3Value(); } |
|
67 #endif |
|
68 #ifdef __MCOT__ |
|
69 inline TCounter TIMER() |
|
70 { return *(volatile TUint*)KHwRwOstOscr; } |
|
71 #endif |
|
72 #ifdef __MAWD__ |
|
73 inline TCounter TIMER() |
|
74 { return *(volatile TUint*)(KWindBaseAddress+KWindTimer1Value16)&0xffff; } |
|
75 #endif |
|
76 #ifdef __MEIG__ |
|
77 inline TCounter TIMER() |
|
78 { return *(volatile TUint*)(KEigerBaseAddress+KEigerTimer1Data16)&0xffff;} |
|
79 #endif |
|
80 #if defined(__MI920__) || defined(__NI1136__) |
|
81 inline TCounter TIMER() |
|
82 #ifdef USE_CM920_FRC |
|
83 { return *(volatile TUint*)(KHwRwCoreClkCounter);} // 32-bit Core module counter inc's at 24MHz |
|
84 #else |
|
85 { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;} |
|
86 #endif |
|
87 #endif |
|
88 #if defined(__RVEMUBOARD__) |
|
89 inline TCounter TIMER() |
|
90 { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;} |
|
91 #endif |
|
92 #ifdef __NE1_TB__ |
|
93 inline TCounter TIMER() |
|
94 { return NETimer::Timer(2).iTimerCount; } |
|
95 #endif |
|
96 #if defined(__EPOC32__) && defined(__CPU_X86) |
|
97 TCounter TIMER(); |
|
98 void SetUpTimerChannel2(); |
|
99 #endif |
|
100 |
|
101 #ifdef __WINS__ |
|
102 inline TCounter TIMER() |
|
103 { |
|
104 LARGE_INTEGER c; |
|
105 QueryPerformanceCounter(&c); |
|
106 return c.QuadPart; |
|
107 } |
|
108 #endif |
|
109 |
|
110 #if defined(__MISA__) || (defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__))) |
|
111 inline TDelta TimeDelta(TCounter initial, TCounter final) |
|
112 { return final-initial; } // SA1100 timer counts up |
|
113 #endif |
|
114 #if defined(__MCOT__) |
|
115 inline TDelta TimeDelta(TCounter initial, TCounter final) |
|
116 { return final-initial; } // Cotulla timer counts up |
|
117 #endif |
|
118 #if defined(__MAWD__) || defined(__MEIG__) || (!defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__))) |
|
119 inline TDelta TimeDelta(TCounter initial, TCounter final) |
|
120 { return (initial-final)&0xffff; } // Eiger/Windermere/Integrator timer counts down |
|
121 #endif |
|
122 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) |
|
123 inline TDelta TimeDelta(TCounter initial, TCounter final) |
|
124 { return (initial-final);} // OMAP timer counts down |
|
125 #endif |
|
126 #if defined(__EPOC32__) && defined(__CPU_X86) |
|
127 TDelta TimeDelta(TUint initial, TUint final) |
|
128 { |
|
129 TUint tickdiff=(initial-final)&0xffff; |
|
130 TUint msdiff=((final>>16)-(initial>>16))&0xffff; |
|
131 msdiff=1193*msdiff-tickdiff; |
|
132 msdiff=(msdiff+32768)&~0xffff; |
|
133 return msdiff+tickdiff; |
|
134 } |
|
135 #endif |
|
136 #ifdef __NE1_TB__ |
|
137 inline TDelta TimeDelta(TCounter initial, TCounter final) |
|
138 { return final - initial; } |
|
139 #endif |
|
140 #ifdef __WINS__ |
|
141 inline TDelta TimeDelta(TCounter initial, TCounter final) |
|
142 { return final-initial; } // counts up |
|
143 #endif |
|
144 #if defined(__RVEMUBOARD__) |
|
145 inline TDelta TimeDelta(TCounter initial, TCounter final) |
|
146 { return (initial-final)&0xffff; } // Timer counts down |
|
147 #endif |
|
148 |
|
149 const TInt KMajorVersionNumber=0; |
|
150 const TInt KMinorVersionNumber=1; |
|
151 const TInt KBuildVersionNumber=1; |
|
152 |
|
153 const TInt KMaxMsTim=9; |
|
154 const TInt KMaxMsTimR=9; |
|
155 |
|
156 TInt TicksToMicroseconds(TDelta aTicks) |
|
157 { |
|
158 #if defined(__MISA__) || defined(__MCOT__) |
|
159 Int64 ticks(aTicks); |
|
160 ticks*=(1000000); |
|
161 ticks+=KHwOscFreqHz/2; // 3.6864MHz tick |
|
162 ticks/=KHwOscFreqHz; |
|
163 return (TInt)ticks; |
|
164 #endif |
|
165 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) |
|
166 // Timer runs at 12Mhz/32 = 375kHz. Each tick is 2.66...us which is 16/6us |
|
167 aTicks<<=4; // * 16 |
|
168 aTicks+=3; // rounding to the closest number of us |
|
169 return (TInt)(aTicks/6); // us = (ticks*16+3)/6 |
|
170 #endif |
|
171 #if defined(__MI920__) || defined(__NI1136__) |
|
172 #if defined(USE_CM920_FRC) |
|
173 Int64 ticks(aTicks); |
|
174 ticks*=(1000000); |
|
175 ticks+=24000000/2; |
|
176 ticks/=24000000; |
|
177 return (TInt)ticks; |
|
178 #else |
|
179 aTicks<<=14; // 1 tick = 32/3 us |
|
180 aTicks+=768; // round |
|
181 return (TInt)(aTicks/1536); |
|
182 #endif |
|
183 #endif |
|
184 #if defined(__RVEMUBOARD__) |
|
185 return (TInt)(aTicks*256); // 1 tick = 256 us |
|
186 #endif |
|
187 #if defined(__MAWD__) || defined(__MEIG__) |
|
188 return aTicks*500; // 2kHz tick |
|
189 #endif |
|
190 #if defined(__NE1_TB__) |
|
191 NETimer& T2 = NETimer::Timer(2); |
|
192 TUint prescale = __e32_find_ms1_32(T2.iPrescaler & 0x3f); |
|
193 TInt f = 66666667 >> prescale; |
|
194 TInt64 x = I64LIT(1000000); |
|
195 x *= TInt64(aTicks); |
|
196 x += TInt64(f>>1); |
|
197 x /= TInt64(f); |
|
198 return (TInt)x; |
|
199 #endif |
|
200 #if defined(__EPOC32__) && defined(__CPU_X86) |
|
201 TInt x = aTicks; |
|
202 TInt y = x; |
|
203 y -= ((3*x)>>4); // * 0.D |
|
204 y += (aTicks>>12); // * 0.D00D |
|
205 TInt z = (6*x)>>8; // * 0.06 |
|
206 y += z; // * 0.D60D |
|
207 y += (x>>9); // * 0.D68D |
|
208 y += (z>>16); // * 0.D68D6 |
|
209 y += (z>>20); // * 0.D68D66 |
|
210 return y; |
|
211 #endif |
|
212 #ifdef __WINS__ |
|
213 LARGE_INTEGER f; |
|
214 QueryPerformanceFrequency(&f); |
|
215 aTicks*=1000000; |
|
216 aTicks+=f.QuadPart-1; |
|
217 aTicks/=f.QuadPart; |
|
218 return (TInt)aTicks; |
|
219 #endif |
|
220 } |
|
221 |
|
222 |
|
223 void InitTimer() |
|
224 { |
|
225 #ifdef __MAWD__ |
|
226 // Set up timer 1 as free running 2kHz clock |
|
227 TWind::SetBuzzerControl(0); // disable buzzer |
|
228 TWind::SetTimer1Control(KWindTimer1ControlTimerEnable); |
|
229 TWind::SetTimer1Load(0); |
|
230 #endif |
|
231 #ifdef __MEIG__ |
|
232 // Set up timer 1 as free running 2kHz clock |
|
233 TEiger::ModifyControl21(KEigerControlTimer1PreOrFree|KEigerControlTimer1K512OrK2| |
|
234 KEigerControlBuzzerToggle|KEigerControlBuzzerTimer1OrToggle,0); |
|
235 TEiger::SetTimer1Data(0); |
|
236 #endif |
|
237 #if defined(__MISA__) |
|
238 // MISA free running counter is always active - no initialisation required |
|
239 #endif |
|
240 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) |
|
241 // Set up Timer3 as a free-running timer at 12Mhz/32 = 375kHz |
|
242 TOmapTimer::SetTimer3Ctrl( TOmapTimer::KHtOSTimer_Cntl_Ar |
|
243 | TOmapTimer::KHtOSTimer_Cntl_Free |
|
244 | TOmapTimer::KHtOSTimer_Cntl_ClkEnable ); |
|
245 TOmapTimer::SetTimer3Prescale( TOmapTimer::EPrescaleBy32 ); |
|
246 // Autoreload 0xFFFFFFFF to effectively wrap from zero back to 0xFFFFFFFF |
|
247 TOmapTimer::SetTimer3LoadTim( 0xFFFFFFFF ); |
|
248 TOmapTimer::StartTimer3(); |
|
249 #endif |
|
250 #if defined(__MI920__) || defined(__NI1136__) |
|
251 #if !defined(USE_CM920_FRC) |
|
252 TIntegratorAP::SetTimerMode(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerModeFreeRunning); |
|
253 TIntegratorAP::SetTimerPreScale(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerPreScaleDiv256); // 93.75kHz wrap 699ms |
|
254 TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EEnable); |
|
255 #endif |
|
256 #endif |
|
257 #if defined(__RVEMUBOARD__) |
|
258 // Switch timer 1 to a 1MHz clock in the system controller Ctrl register |
|
259 TRvEmuBoard::SetSCCtrl(KTimer1EnSel); |
|
260 |
|
261 // Set up timer 1 as free running 3.90625kHz clock |
|
262 TRvEmuBoard::SetTimerMode(KHwCounterTimer1, TRvEmuBoard::ETimerModeFreeRunning); |
|
263 TRvEmuBoard::SetTimerPreScale(KHwCounterTimer1, TRvEmuBoard::ETimerPreScaleDiv256);// 3.90625kHz wrap 16.777s |
|
264 TRvEmuBoard::EnableTimer(KHwCounterTimer1, TRvEmuBoard::EEnable); |
|
265 #endif |
|
266 #if defined(__NE1_TB__) |
|
267 // nothing to do since variant has already set up timer |
|
268 #endif |
|
269 #if defined(__EPOC32__) && defined(__CPU_X86) |
|
270 // Set up timer channel 2 as free running counter at 14318180/12 Hz |
|
271 SetUpTimerChannel2(); |
|
272 #endif |
|
273 } |
|
274 |
|
275 // global Dfc Que |
|
276 TDynamicDfcQue* gDfcQ; |
|
277 |
|
278 class NTimerQTest |
|
279 { |
|
280 public: |
|
281 static inline NTimerQ& Timer() |
|
282 { return *(NTimerQ*)NTimerQ::TimerAddress(); } |
|
283 static inline TUint32 MsCount() |
|
284 { return Timer().iMsCount; } |
|
285 static inline void Setup(TAny* aPtr) |
|
286 { NTimerQ& m=Timer(); m.iDebugFn=Test; m.iDebugPtr=aPtr; } |
|
287 static inline void Stop() |
|
288 { NTimerQ& m=Timer(); m.iDebugFn=NULL; m.iDebugPtr=NULL; } |
|
289 static inline TBool XferC() |
|
290 { return Timer().iTransferringCancelled; } |
|
291 static inline TBool CritC() |
|
292 { return Timer().iCriticalCancelled; } |
|
293 static void Test(TAny* aPtr, TInt aPos); |
|
294 }; |
|
295 |
|
296 class DMsTim; |
|
297 |
|
298 class TMsTim : public NTimer |
|
299 { |
|
300 public: |
|
301 enum TMode |
|
302 { |
|
303 EIntAfter, |
|
304 EDfcAfter, |
|
305 EIntAgain, |
|
306 EDfcAgain, |
|
307 EIntCancel, |
|
308 EDfcCancel, |
|
309 EUserDfcAfter |
|
310 }; |
|
311 |
|
312 enum TModeX |
|
313 { |
|
314 EIntAgainOnce=7, |
|
315 EUserDfcAgainOnce |
|
316 }; |
|
317 public: |
|
318 TMsTim(); |
|
319 ~TMsTim(); |
|
320 TInt Create(); |
|
321 TInt Start(TInt aMode, TInt aInterval, TInt aParam); |
|
322 static void MsCallBack(TAny* aPtr); |
|
323 static void IDfcFn(TAny* aPtr); |
|
324 static void DfcFn(TAny* aPtr); |
|
325 void CompleteClient(TInt aValue); |
|
326 public: |
|
327 TMode iMode; |
|
328 TInt iInterval; |
|
329 TInt iParam; |
|
330 TCounter iStartTime; |
|
331 TDelta iMin; |
|
332 TDelta iMax; |
|
333 Int64 iTotal; |
|
334 TInt iCount; |
|
335 DMsTim* iLdd; |
|
336 TInt iId; |
|
337 TClientRequest* iRequest; |
|
338 TDfc iIDfc; |
|
339 TDfc iCompletionDfc; |
|
340 }; |
|
341 |
|
342 class TMsTimRand : public NTimer |
|
343 { |
|
344 public: |
|
345 TMsTimRand(); |
|
346 #ifdef __SMP__ |
|
347 ~TMsTimRand(); |
|
348 #endif |
|
349 TInt Start(TInt aInterval, DMsTim* aLdd, TInt aPos); |
|
350 static void MsCallBack(TAny* aPtr); |
|
351 void FillWithGarbage(TUint aFillValue); |
|
352 public: |
|
353 TInt iInterval; |
|
354 TCounter iStartTime; |
|
355 DMsTim* iLdd; |
|
356 }; |
|
357 |
|
358 class DMsTimFactory : public DLogicalDevice |
|
359 // |
|
360 // Millisecond timer LDD factory |
|
361 // |
|
362 { |
|
363 public: |
|
364 DMsTimFactory(); |
|
365 ~DMsTimFactory(); |
|
366 virtual TInt Install(); //overriding pure virtual |
|
367 virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual |
|
368 virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual |
|
369 }; |
|
370 |
|
371 class DMsTim : public DLogicalChannel |
|
372 // |
|
373 // Millisecond timer LDD channel |
|
374 // |
|
375 { |
|
376 public: |
|
377 DMsTim(); |
|
378 ~DMsTim(); |
|
379 protected: |
|
380 virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); |
|
381 TInt DoControl(TInt aFunction, TAny* a1, TAny* a2); |
|
382 TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2); |
|
383 virtual void HandleMsg(TMessageBase* aMsg); |
|
384 public: |
|
385 void TimerExpired(TInt anId); |
|
386 inline DThread* Client() { return iThread; } |
|
387 public: |
|
388 DThread* iThread; |
|
389 TMsTim iMsTim[KMaxMsTim]; |
|
390 TMsTimRand iMsTimR[KMaxMsTimR]; |
|
391 TInt iRandMin; |
|
392 TInt iRandMax; |
|
393 TInt iXferC; |
|
394 TInt iCritC; |
|
395 TInt iStartFail; |
|
396 TInt iCallBacks; |
|
397 TInt iCompletions; |
|
398 TUint iSeed[2]; |
|
399 }; |
|
400 |
|
401 TMsTim::TMsTim() |
|
402 : NTimer(MsCallBack,this), |
|
403 iMode(EIntAfter), |
|
404 iInterval(0), |
|
405 iParam(0), |
|
406 iStartTime(0), |
|
407 iMin(KMaxDelta), |
|
408 iMax(KMinDelta), |
|
409 iTotal(0), |
|
410 iCount(0), |
|
411 iRequest(NULL), |
|
412 iIDfc(IDfcFn,this), |
|
413 iCompletionDfc(DfcFn,this,gDfcQ,1) |
|
414 { |
|
415 } |
|
416 |
|
417 TMsTim::~TMsTim() |
|
418 { |
|
419 Kern::DestroyClientRequest(iRequest); |
|
420 #ifdef __SMP__ |
|
421 NTimer* nt = STATIC_CAST(NTimer*,this); |
|
422 new (nt) NTimer(&MsCallBack, this); // so NTimer destructor doesn't kill us |
|
423 #endif |
|
424 } |
|
425 |
|
426 TInt TMsTim::Create() |
|
427 { |
|
428 return Kern::CreateClientRequest(iRequest); |
|
429 } |
|
430 |
|
431 void TMsTim::IDfcFn(TAny* aPtr) |
|
432 { |
|
433 TMsTim& m=*(TMsTim*)aPtr; |
|
434 TInt c = NKern::CurrentContext(); |
|
435 __NK_ASSERT_ALWAYS(c == NKern::EIDFC); |
|
436 __NK_ASSERT_ALWAYS(NKern::KernelLocked(1)); |
|
437 m.iCompletionDfc.DoEnque(); |
|
438 } |
|
439 |
|
440 void TMsTim::DfcFn(TAny* aPtr) |
|
441 { |
|
442 TMsTim& m=*(TMsTim*)aPtr; |
|
443 if (m.iMode==EUserDfcAfter) |
|
444 { |
|
445 TCounter timer_val=TIMER(); |
|
446 TDelta time=TimeDelta(m.iStartTime, timer_val); |
|
447 ++m.iCount; |
|
448 if (time<m.iMin) |
|
449 m.iMin=time; |
|
450 if (time>m.iMax) |
|
451 m.iMax=time; |
|
452 m.iTotal+=time; |
|
453 } |
|
454 m.iLdd->TimerExpired(m.iId); |
|
455 } |
|
456 |
|
457 void TestThreadContext() |
|
458 { |
|
459 TInt c1 = NKern::CurrentContext(); |
|
460 NKern::Lock(); |
|
461 TInt c2 = NKern::CurrentContext(); |
|
462 NKern::Unlock(); |
|
463 __NK_ASSERT_ALWAYS((c1 == NKern::EThread) && (c2 == NKern::EThread)); |
|
464 } |
|
465 |
|
466 void TMsTim::MsCallBack(TAny* aPtr) |
|
467 { |
|
468 TInt c = NKern::CurrentContext(); |
|
469 TCounter timer_val=TIMER(); |
|
470 TMsTim& m=*(TMsTim*)aPtr; |
|
471 TDelta time=TimeDelta(m.iStartTime, timer_val); |
|
472 if (++m.iCount>0 || (m.iMode!=EIntAgain && m.iMode!=EDfcAgain)) |
|
473 { |
|
474 if (time<m.iMin) |
|
475 m.iMin=time; |
|
476 if (time>m.iMax) |
|
477 m.iMax=time; |
|
478 m.iTotal+=time; |
|
479 } |
|
480 switch (m.iMode) |
|
481 { |
|
482 case EIntAfter: |
|
483 __NK_ASSERT_ALWAYS(c == NKern::EInterrupt); |
|
484 m.iIDfc.Add(); |
|
485 break; |
|
486 case EDfcAfter: |
|
487 TestThreadContext(); |
|
488 m.iCompletionDfc.Enque(); |
|
489 break; |
|
490 case EIntAgain: |
|
491 __NK_ASSERT_ALWAYS(c == NKern::EInterrupt); |
|
492 m.iStartTime=TIMER(); |
|
493 m.Again(m.iInterval); |
|
494 break; |
|
495 case EDfcAgain: |
|
496 TestThreadContext(); |
|
497 m.iStartTime=TIMER(); |
|
498 m.Again(m.iInterval); |
|
499 break; |
|
500 case EIntCancel: |
|
501 __NK_ASSERT_ALWAYS(c == NKern::EInterrupt); |
|
502 m.iLdd->iMsTim[m.iParam].Cancel(); |
|
503 m.iIDfc.Add(); |
|
504 break; |
|
505 case EDfcCancel: |
|
506 TestThreadContext(); |
|
507 m.iLdd->iMsTim[m.iParam].Cancel(); |
|
508 m.iCompletionDfc.Enque(); |
|
509 break; |
|
510 case EUserDfcAfter: |
|
511 __NK_ASSERT_ALWAYS(EFalse); |
|
512 break; |
|
513 } |
|
514 } |
|
515 |
|
516 TInt TMsTim::Start(TInt aMode, TInt aInterval, TInt aParam) |
|
517 { |
|
518 TInt r=KErrGeneral; |
|
519 TInt c=0; |
|
520 TCounter holder=TIMER(); // holds the start value of timer |
|
521 switch (aMode) |
|
522 { |
|
523 case EIntAgain: |
|
524 c=-1; |
|
525 case EIntAfter: |
|
526 case EIntCancel: |
|
527 r=OneShot(aInterval); |
|
528 break; |
|
529 case EDfcAgain: |
|
530 c=-1; |
|
531 case EDfcAfter: |
|
532 case EDfcCancel: |
|
533 r=OneShot(aInterval,ETrue); |
|
534 break; |
|
535 case EIntAgainOnce: |
|
536 case EUserDfcAgainOnce: |
|
537 #ifdef __SMP__ |
|
538 i8888.iHState2=FALSE; |
|
539 #else |
|
540 iCompleteInDfc=FALSE; |
|
541 #endif |
|
542 r=Again(aInterval); |
|
543 if (aMode==EUserDfcAgainOnce) |
|
544 aMode=EUserDfcAfter; |
|
545 else |
|
546 aMode=EIntAfter; |
|
547 break; |
|
548 case EUserDfcAfter: |
|
549 r=OneShot(aInterval, iCompletionDfc); |
|
550 break; |
|
551 } |
|
552 if (r!=KErrNone) |
|
553 return r; |
|
554 iStartTime=holder; |
|
555 iMode=TMode(aMode); |
|
556 iInterval=aInterval; |
|
557 iParam=aParam; |
|
558 iMin=KMaxDelta; |
|
559 iMax=KMinDelta; |
|
560 iTotal=0; |
|
561 iCount=c; |
|
562 return KErrNone; |
|
563 } |
|
564 |
|
565 void TMsTim::CompleteClient(TInt aValue) |
|
566 { |
|
567 Kern::QueueRequestComplete(iLdd->Client(),iRequest,aValue); |
|
568 } |
|
569 |
|
570 TMsTimRand::TMsTimRand() |
|
571 : NTimer(&MsCallBack,this) |
|
572 { |
|
573 memset(this,0,sizeof(TMsTimRand)); |
|
574 #ifdef __SMP__ |
|
575 NTimer* nt = STATIC_CAST(NTimer*,this); |
|
576 new (nt) NTimer(&MsCallBack,this); |
|
577 #else |
|
578 iFunction=MsCallBack; // avoid triggering assertion in NTimer::OneShot() |
|
579 #endif |
|
580 } |
|
581 |
|
582 #ifdef __SMP__ |
|
583 TMsTimRand::~TMsTimRand() |
|
584 { |
|
585 NTimer* nt = STATIC_CAST(NTimer*,this); |
|
586 new (nt) NTimer(&MsCallBack, this); // so NTimer destructor doesn't kill us |
|
587 } |
|
588 #endif |
|
589 |
|
590 void TMsTimRand::FillWithGarbage(TUint aFill) |
|
591 { |
|
592 #ifdef __SMP__ |
|
593 TUint32 f = aFill; |
|
594 f |= (f<<8); |
|
595 f |= (f<<16); |
|
596 iNext = (SDblQueLink*)f; |
|
597 iPrev = (SDblQueLink*)f; |
|
598 iDfcQ = (TDfcQue*)f; |
|
599 iPtr = (TAny*)f; |
|
600 iFn = (NEventFn)f; |
|
601 iTiedLink.iNext = (SDblQueLink*)f; |
|
602 iTiedLink.iPrev = (SDblQueLink*)f; |
|
603 #else |
|
604 memset(this, (TUint8)aFill, 16); |
|
605 #endif |
|
606 } |
|
607 |
|
608 TInt TMsTimRand::Start(TInt aInterval, DMsTim* aLdd, TInt aPos) |
|
609 { |
|
610 iLdd=aLdd; |
|
611 #ifdef __SMP__ |
|
612 TUint fill=(aPos<<5)|(i8888.iHState1<<2)|3; |
|
613 #else |
|
614 TUint fill=(aPos<<5)|(iState<<2)|3; |
|
615 iPad1 = (TUint8)fill; |
|
616 #endif |
|
617 TInt r=OneShot(aInterval,ETrue); |
|
618 if (r==KErrNone) |
|
619 { |
|
620 iPtr=this; |
|
621 iInterval=aInterval; |
|
622 iStartTime=TIMER(); |
|
623 #ifdef __SMP__ |
|
624 iFn=MsCallBack; |
|
625 i8888.iHState0 = (TUint8)fill; |
|
626 if (i8888.iHState1!=EHolding) |
|
627 *(TUint*)0xfcd1fcd1=i8888.iHState1; |
|
628 #else |
|
629 iFunction=MsCallBack; |
|
630 iUserFlags = (TUint8)fill; |
|
631 if (iState!=EHolding) |
|
632 *(TUint*)0xfcd1fcd1=iState; |
|
633 #endif |
|
634 } |
|
635 return r; |
|
636 } |
|
637 |
|
638 void TMsTimRand::MsCallBack(TAny* aPtr) |
|
639 { |
|
640 TMsTimRand& m=*(TMsTimRand*)aPtr; |
|
641 TCounter time=TIMER(); |
|
642 TDelta elapsed=TimeDelta(m.iStartTime,time); |
|
643 TInt error=TicksToMicroseconds(elapsed)-m.iInterval*1000; |
|
644 if (error<m.iLdd->iRandMin) |
|
645 m.iLdd->iRandMin=error; |
|
646 if (error>m.iLdd->iRandMax) |
|
647 m.iLdd->iRandMax=error; |
|
648 ++m.iLdd->iCompletions; |
|
649 m.FillWithGarbage(0xd9); |
|
650 } |
|
651 |
|
652 void NTimerQTest::Test(TAny* aPtr, TInt aPos) |
|
653 { |
|
654 DMsTim& ldd=*(DMsTim*)aPtr; |
|
655 ++ldd.iCallBacks; |
|
656 if (aPos==7) |
|
657 return; |
|
658 TUint action=Random(ldd.iSeed)&31; |
|
659 TMsTimRand& m=ldd.iMsTimR[action&7]; |
|
660 if (action<8) |
|
661 { |
|
662 #ifdef __SMP__ |
|
663 TUint fill=(aPos<<5)|(m.i8888.iHState1<<2)|3; |
|
664 #else |
|
665 TUint fill=(aPos<<5)|(m.iState<<2)|3; |
|
666 #endif |
|
667 m.Cancel(); |
|
668 m.FillWithGarbage(fill); |
|
669 } |
|
670 else if (action<16) |
|
671 { |
|
672 TUint iv=(Random(ldd.iSeed)&31)+32; |
|
673 TInt r=m.Start(iv,&ldd,aPos); |
|
674 if (r!=KErrNone) |
|
675 ++ldd.iStartFail; |
|
676 } |
|
677 if (XferC()) |
|
678 ++ldd.iXferC; |
|
679 if (CritC()) |
|
680 ++ldd.iCritC; |
|
681 } |
|
682 |
|
683 DECLARE_STANDARD_LDD() |
|
684 { |
|
685 return new DMsTimFactory; |
|
686 } |
|
687 |
|
688 DMsTimFactory::DMsTimFactory() |
|
689 // |
|
690 // Constructor |
|
691 // |
|
692 { |
|
693 iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
694 //iParseMask=0;//No units, no info, no PDD |
|
695 //iUnitsMask=0;//Only one thing |
|
696 } |
|
697 |
|
698 TInt DMsTimFactory::Create(DLogicalChannelBase*& aChannel) |
|
699 // |
|
700 // Create a new DMsTim on this logical device |
|
701 // |
|
702 { |
|
703 aChannel=new DMsTim; |
|
704 return aChannel?KErrNone:KErrNoMemory; |
|
705 } |
|
706 |
|
707 const TInt KDMsTimThreadPriority = 27; |
|
708 _LIT(KDMsTimThread,"DMsTimThread"); |
|
709 |
|
710 TInt DMsTimFactory::Install() |
|
711 // |
|
712 // Install the LDD - overriding pure virtual |
|
713 // |
|
714 { |
|
715 // Allocate a kernel thread to run the DFC |
|
716 TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDMsTimThreadPriority, KDMsTimThread); |
|
717 |
|
718 if (r != KErrNone) |
|
719 return r; |
|
720 |
|
721 return SetName(&KMsTimerLddName); |
|
722 } |
|
723 |
|
724 void DMsTimFactory::GetCaps(TDes8& aDes) const |
|
725 // |
|
726 // Get capabilities - overriding pure virtual |
|
727 // |
|
728 { |
|
729 TCapsMsTimV01 b; |
|
730 b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
731 Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b)); |
|
732 } |
|
733 |
|
734 /** |
|
735 Destructor |
|
736 */ |
|
737 DMsTimFactory::~DMsTimFactory() |
|
738 { |
|
739 if (gDfcQ) |
|
740 gDfcQ->Destroy(); |
|
741 } |
|
742 |
|
743 DMsTim::DMsTim() |
|
744 // |
|
745 // Constructor |
|
746 // |
|
747 { |
|
748 iThread=&Kern::CurrentThread(); |
|
749 iThread->Open(); |
|
750 TInt i; |
|
751 for (i=0; i<KMaxMsTim; i++) |
|
752 { |
|
753 iMsTim[i].iLdd=this; |
|
754 iMsTim[i].iId=i; |
|
755 } |
|
756 for (i=0; i<KMaxMsTimR; i++) |
|
757 { |
|
758 iMsTimR[i].iLdd=this; |
|
759 } |
|
760 iSeed[0]=NTimerQTest::MsCount(); |
|
761 iSeed[1]=0; |
|
762 } |
|
763 |
|
764 TInt DMsTim::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer) |
|
765 // |
|
766 // Create channel |
|
767 // |
|
768 { |
|
769 if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer)) |
|
770 return KErrNotSupported; |
|
771 InitTimer(); |
|
772 SetDfcQ(gDfcQ); |
|
773 for (TInt i = 0 ; i < KMaxMsTim ; ++i) |
|
774 { |
|
775 TInt r = iMsTim[i].Create(); |
|
776 if (r != KErrNone) |
|
777 return r; |
|
778 } |
|
779 iMsgQ.Receive(); |
|
780 #ifdef __SMP__ |
|
781 NKern::ThreadSetCpuAffinity(NKern::CurrentThread(), NKern::NumberOfCpus() - 1); // Try and avoid the cpu the test app is running on |
|
782 #endif |
|
783 return KErrNone; |
|
784 } |
|
785 |
|
786 DMsTim::~DMsTim() |
|
787 // |
|
788 // Destructor |
|
789 // |
|
790 { |
|
791 #if defined(__MI920__) || defined(__NI1136__) |
|
792 #if !defined(USE_CM920_FRC) |
|
793 TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EDisable); |
|
794 #endif |
|
795 #endif |
|
796 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) |
|
797 TOmapTimer::SetTimer3Ctrl( 0 ); // disable the timer |
|
798 #endif |
|
799 Kern::SafeClose((DObject*&)iThread, NULL); |
|
800 } |
|
801 |
|
802 void DMsTim::HandleMsg(TMessageBase* aMsg) |
|
803 { |
|
804 TInt r=KErrNone; |
|
805 TThreadMessage& m=*(TThreadMessage*)aMsg; |
|
806 TInt id=m.iValue; |
|
807 if (id==(TInt)ECloseMsg) |
|
808 { |
|
809 NTimerQTest::Stop(); |
|
810 TInt i; |
|
811 for (i=0; i<KMaxMsTim; i++) |
|
812 { |
|
813 iMsTim[i].Cancel(); |
|
814 iMsTim[i].iCompletionDfc.Cancel(); |
|
815 iMsTim[i].CompleteClient(KErrCancel); |
|
816 } |
|
817 for (i=0; i<KMaxMsTimR; i++) |
|
818 { |
|
819 iMsTimR[i].Cancel(); |
|
820 iMsTimR[i].FillWithGarbage(0x01); |
|
821 } |
|
822 m.Complete(KErrNone,EFalse); |
|
823 iMsgQ.CompleteAll(KErrServerTerminated); |
|
824 return; |
|
825 } |
|
826 else if (id<0) |
|
827 { |
|
828 TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); |
|
829 r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2()); |
|
830 } |
|
831 else |
|
832 { |
|
833 r=DoControl(id,m.Ptr0(),m.Ptr1()); |
|
834 } |
|
835 m.Complete(r,ETrue); |
|
836 } |
|
837 |
|
838 TInt DMsTim::DoControl(TInt aFunction, TAny* a1, TAny* a2) |
|
839 { |
|
840 TInt r=KErrNone; |
|
841 TInt id=(TInt)a1; |
|
842 TMsTim& m=iMsTim[id]; |
|
843 TInt interval=(TInt)a2; |
|
844 switch (aFunction) |
|
845 { |
|
846 case RMsTim::EControlStartPeriodicInt: |
|
847 r=m.Start(TMsTim::EIntAgain,interval,0); |
|
848 break; |
|
849 case RMsTim::EControlStartPeriodicDfc: |
|
850 r=m.Start(TMsTim::EDfcAgain,interval,0); |
|
851 break; |
|
852 case RMsTim::EControlStopPeriodic: |
|
853 m.Cancel(); |
|
854 m.iCompletionDfc.Cancel(); |
|
855 break; |
|
856 case RMsTim::EControlGetInfo: |
|
857 { |
|
858 SMsTimerInfo info; |
|
859 info.iMin=TicksToMicroseconds(m.iMin); |
|
860 info.iMax=TicksToMicroseconds(m.iMax); |
|
861 info.iCount=m.iCount; |
|
862 Int64 avg=m.iTotal/m.iCount; |
|
863 info.iAvg=TicksToMicroseconds((TInt)avg); |
|
864 |
|
865 r=Kern::ThreadRawWrite(iThread,a2,&info,sizeof(info)); |
|
866 break; |
|
867 } |
|
868 case RMsTim::EControlBeginRandomTest: |
|
869 { |
|
870 iRandMin=KMaxTInt; |
|
871 iRandMax=KMinTInt; |
|
872 iXferC=0; |
|
873 iCritC=0; |
|
874 iStartFail=0; |
|
875 iCallBacks=0; |
|
876 iCompletions=0; |
|
877 NTimerQTest::Setup(this); |
|
878 break; |
|
879 } |
|
880 case RMsTim::EControlEndRandomTest: |
|
881 { |
|
882 NTimerQTest::Stop(); |
|
883 TInt i; |
|
884 for (i=0; i<KMaxMsTimR; i++) |
|
885 { |
|
886 iMsTimR[i].Cancel(); |
|
887 iMsTimR[i].FillWithGarbage(0x35); |
|
888 } |
|
889 break; |
|
890 } |
|
891 case RMsTim::EControlGetRandomTestInfo: |
|
892 { |
|
893 SRandomTestInfo info; |
|
894 info.iMin=iRandMin; |
|
895 info.iMax=iRandMax; |
|
896 info.iXferC=iXferC; |
|
897 info.iCritC=iCritC; |
|
898 info.iStartFail=iStartFail; |
|
899 info.iCallBacks=iCallBacks; |
|
900 info.iCompletions=iCompletions; |
|
901 r=Kern::ThreadRawWrite(iThread,a1,&info,sizeof(info)); |
|
902 break; |
|
903 } |
|
904 case RMsTim::EControlGetIdleTime: |
|
905 { |
|
906 TInt irq=NKern::DisableAllInterrupts(); |
|
907 r=NTimerQ::IdleTime(); |
|
908 NKern::RestoreInterrupts(irq); |
|
909 break; |
|
910 } |
|
911 default: |
|
912 r=KErrNotSupported; |
|
913 break; |
|
914 } |
|
915 return r; |
|
916 } |
|
917 |
|
918 TInt DMsTim::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2) |
|
919 { |
|
920 TInt id=(TInt)a1; |
|
921 TMsTim& m=iMsTim[aFunction == RMsTim::ERequestIntCancel ? 7 : id]; |
|
922 TInt interval=(TInt)a2; |
|
923 TInt r=KErrNone; |
|
924 switch (aFunction) |
|
925 { |
|
926 case RMsTim::ERequestOneShotInt: |
|
927 r=m.Start(TMsTim::EIntAfter,interval,0); |
|
928 break; |
|
929 case RMsTim::ERequestOneShotDfc: |
|
930 r=m.Start(TMsTim::EDfcAfter,interval,0); |
|
931 break; |
|
932 case RMsTim::ERequestIntCancel: |
|
933 r=m.Start(TMsTim::EIntCancel,interval,id); |
|
934 break; |
|
935 case RMsTim::ERequestOneShotIntAgain: |
|
936 r=m.Start(TMsTim::EIntAgainOnce,interval,0); |
|
937 break; |
|
938 case RMsTim::ERequestOneShotUserDfc: |
|
939 r=m.Start(TMsTim::EUserDfcAfter,interval,0); |
|
940 break; |
|
941 case RMsTim::ERequestOneShotUserDfcAgain: |
|
942 r=m.Start(TMsTim::EUserDfcAgainOnce,interval,0); |
|
943 break; |
|
944 default: |
|
945 r=KErrNotSupported; |
|
946 break; |
|
947 } |
|
948 m.iRequest->SetStatus(aStatus); |
|
949 if (r!=KErrNone) |
|
950 Kern::QueueRequestComplete(iThread,m.iRequest,r); |
|
951 return r; |
|
952 } |
|
953 |
|
954 void DMsTim::TimerExpired(TInt anId) |
|
955 { |
|
956 TMsTim& m=iMsTim[anId]; |
|
957 switch (m.iMode) |
|
958 { |
|
959 case TMsTim::EIntAfter: |
|
960 case TMsTim::EDfcAfter: |
|
961 case TMsTim::EUserDfcAfter: |
|
962 m.CompleteClient(KErrNone); |
|
963 break; |
|
964 case TMsTim::EIntAgain: |
|
965 case TMsTim::EDfcAgain: |
|
966 break; |
|
967 case TMsTim::EIntCancel: |
|
968 case TMsTim::EDfcCancel: |
|
969 { |
|
970 TMsTim& cancelled=iMsTim[m.iParam]; |
|
971 cancelled.CompleteClient(KErrAbort); |
|
972 m.CompleteClient(KErrNone); |
|
973 break; |
|
974 } |
|
975 } |
|
976 } |
|
977 |