|
1 // Copyright (c) 2010 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 // |
|
15 // This test checks the accuracy if NKern::Timestamp (in SMP systems) or |
|
16 // NKern::Fastcounter (in unicore), when low power modes are being selected |
|
17 // during idle. |
|
18 // Platforms requiring this test need to provide a d_timestamp.pdd which |
|
19 // implements the functions required to test the accurary. If no pdd is |
|
20 // supplied the test is skipped and claims to succeed. |
|
21 // Overview: |
|
22 |
|
23 //------------------------------------------------------------------------------------------- |
|
24 //! @SYMTestCaseID KBASE-t_timestamp-2706 |
|
25 //! @SYMTestCaseDesc verifying that NKern::Timestamp/FastCounter works correctly |
|
26 //! accross low power modes |
|
27 //! @SYMPREQ 417-52765 |
|
28 //! @SYMTestPriority High |
|
29 //! @SYMTestActions |
|
30 //! 1. This test harness first gets information about NKern::Timestamp or |
|
31 //! NKern::FastCounter in particular its frequency. It also obtains |
|
32 //! the following constants: Number of timer to run the test, number |
|
33 //! of retries before giving up if no low power modes are detected, |
|
34 //! and acceptable error percent. Length in nanokernel ticks of each cycle |
|
35 //! 2. Then it measures the timestamp before and after a time interval |
|
36 //! controlled by NTimerIntervalInS (constant is in seconds) |
|
37 //! 2.1 If in period of KTimerInterval a low power mode was entered and |
|
38 //! the timer underlying NKern::Timestamp had to be restated then before |
|
39 //! and after time is stored. The cycle is considered successful. |
|
40 //! 3. If KNMaxentries occur with no successful entries the test fails |
|
41 //! 4. If any valid entry has an interval as measured with NKern::Timestamp that |
|
42 //! is outside KNErrPercent of the same interval as measured with nanokernel |
|
43 //! ticks then the test fails |
|
44 //! 5. If KNValidRuns valid cycles have an acceptable error the test succeeds |
|
45 //! |
|
46 //! @SYMTestExpectedResults |
|
47 //! test passed |
|
48 //------------------------------------------------------------------------------------------- |
|
49 |
|
50 #include <e32std.h> |
|
51 #include <e32base.h> |
|
52 #include <e32debug.h> |
|
53 #define __E32TEST_EXTENSION__ |
|
54 #include <e32test.h> |
|
55 #include <hal.h> |
|
56 #include <u32hal.h> |
|
57 #include <e32svr.h> |
|
58 #include "d_timestamp.h" |
|
59 |
|
60 _LIT(KTimestampTestLddFileName,"D_TIMESTAMP.LDD"); |
|
61 _LIT(KTimestampTestPddFileName,"D_TIMESTAMP.PDD"); |
|
62 |
|
63 RTest test(_L("T_TIMESTAMP")); |
|
64 |
|
65 LOCAL_C void UnloadDrivers() |
|
66 { |
|
67 test.Printf(_L("Unloading LDD\n")); |
|
68 |
|
69 TInt r=User::FreeLogicalDevice(RTimestampTest::Name()); |
|
70 test_KErrNone(r); |
|
71 |
|
72 TName pddName(RTimestampTest::Name()); |
|
73 _LIT(KPddWildcardExtension,".*"); |
|
74 pddName.Append(KPddWildcardExtension); |
|
75 TFindPhysicalDevice findPD(pddName); |
|
76 TFullName findResult; |
|
77 r=findPD.Next(findResult); |
|
78 while (r==KErrNone) |
|
79 { |
|
80 test.Printf(_L("Unloading PDD: %S\n"),&findResult); |
|
81 r=User::FreePhysicalDevice(findResult); |
|
82 test_KErrNone(r); |
|
83 findPD.Find(pddName); // Reset the find handle now that we have deleted something from the container. |
|
84 r=findPD.Next(findResult); |
|
85 } |
|
86 } |
|
87 |
|
88 |
|
89 GLDEF_C TInt E32Main() |
|
90 { |
|
91 |
|
92 TBool dontFail = (User::CommandLineLength()!=0); |
|
93 |
|
94 test.Title(); |
|
95 |
|
96 test.Start(_L("Timestamp accuracy test")); |
|
97 |
|
98 |
|
99 TInt r; |
|
100 TRequestStatus st; |
|
101 |
|
102 r = User::LoadPhysicalDevice(KTimestampTestPddFileName); |
|
103 if (KErrNotFound == r) |
|
104 { |
|
105 test.Printf(_L("No timestamp pdd, test skipped\n")); |
|
106 test.End(); // skip test if this platform does not supply a PDD |
|
107 return 0; |
|
108 } |
|
109 |
|
110 |
|
111 r=User::LoadLogicalDevice(KTimestampTestLddFileName); |
|
112 test(r==KErrNone || r==KErrAlreadyExists); |
|
113 |
|
114 RTimestampTest ldd; |
|
115 r = ldd.Open(); |
|
116 test_KErrNone(r); |
|
117 |
|
118 test.Next(_L("Get timestamp frequency")); |
|
119 STimestampTestConfig info; |
|
120 r = ldd.Config(info); |
|
121 test_KErrNone(r); |
|
122 |
|
123 |
|
124 TUint retries = 0; |
|
125 TUint validruns = 0; |
|
126 |
|
127 test.Next(_L("Get nanotick frequency")); |
|
128 TInt tickPeriod = 0; |
|
129 r = HAL::Get(HAL::ENanoTickPeriod, tickPeriod); |
|
130 test_KErrNone(r); |
|
131 test.Printf(_L(" tick period in uS== %d\n"), tickPeriod); |
|
132 |
|
133 TInt ticks = info.iTimerDurationS*1000000/tickPeriod; |
|
134 TUint64 expected = info.iTimerDurationS*info.iFreq; |
|
135 TUint64 acceptError = info.iErrorPercent*expected/100; |
|
136 |
|
137 test.Printf(_L("running at %dHz for %d interations, each lasting %d seconds and with %d retries\n"), |
|
138 info.iFreq, |
|
139 info.iIterations, |
|
140 info.iTimerDurationS, |
|
141 info.iRetries |
|
142 ); |
|
143 |
|
144 test.Printf(_L("expecting %lu with up to %lu error\n"),expected,acceptError); |
|
145 |
|
146 test.Next(_L("test timer interval")); |
|
147 STimestampResult result; |
|
148 STimestampResult* validResults = new STimestampResult[info.iIterations]; |
|
149 memset(&validResults[0],0,sizeof(validResults)); |
|
150 ldd.Start(st,ticks); |
|
151 User::WaitForRequest(st); |
|
152 test_KErrNone(st.Int()); |
|
153 |
|
154 FOREVER |
|
155 { |
|
156 ldd.WaitOnTimer(st,result); |
|
157 User::WaitForRequest(st); |
|
158 test_KErrNone(st.Int()); |
|
159 TUint64 error = (result.iDelta>expected) ? result.iDelta-expected : expected - result.iDelta; |
|
160 |
|
161 if (error < acceptError) |
|
162 { |
|
163 test.Printf(_L("Got %lu expected %lu, LPM Entered:%d, error %lu is OK \n"), |
|
164 result.iDelta,expected,result.iLPMEntered,error); |
|
165 } |
|
166 else |
|
167 { |
|
168 test.Printf(_L("Got %lu expected %lu, LPM Entered:%d, error %lu is BAD\n"), |
|
169 result.iDelta,expected,result.iLPMEntered,error); |
|
170 if (!dontFail) |
|
171 { |
|
172 delete [] validResults; |
|
173 ldd.Close(); |
|
174 UnloadDrivers(); |
|
175 test(error < acceptError); |
|
176 } |
|
177 } |
|
178 |
|
179 if (result.iLPMEntered) |
|
180 { |
|
181 retries = 0; |
|
182 validResults[validruns] = result; |
|
183 if (++validruns==info.iIterations) break; |
|
184 } |
|
185 else |
|
186 { |
|
187 retries++; |
|
188 if (retries==info.iRetries) |
|
189 { |
|
190 test.Printf(_L("several retries with no power mode entry ... aborting ...\n")); |
|
191 ldd.Close(); |
|
192 delete [] validResults; |
|
193 UnloadDrivers(); |
|
194 test_Compare(retries,<,info.iRetries); |
|
195 } |
|
196 |
|
197 } |
|
198 } |
|
199 |
|
200 delete [] validResults; |
|
201 ldd.Close(); |
|
202 UnloadDrivers(); |
|
203 test.End(); |
|
204 return(0); |
|
205 } |