1 |
786 |
skrzyp |
//==========================================================================
|
2 |
|
|
//
|
3 |
|
|
// clockcnv.cxx
|
4 |
|
|
//
|
5 |
|
|
// Clock Converter test
|
6 |
|
|
//
|
7 |
|
|
//==========================================================================
|
8 |
|
|
// ####ECOSGPLCOPYRIGHTBEGIN####
|
9 |
|
|
// -------------------------------------------
|
10 |
|
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
11 |
|
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
12 |
|
|
//
|
13 |
|
|
// eCos is free software; you can redistribute it and/or modify it under
|
14 |
|
|
// the terms of the GNU General Public License as published by the Free
|
15 |
|
|
// Software Foundation; either version 2 or (at your option) any later
|
16 |
|
|
// version.
|
17 |
|
|
//
|
18 |
|
|
// eCos is distributed in the hope that it will be useful, but WITHOUT
|
19 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
20 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
21 |
|
|
// for more details.
|
22 |
|
|
//
|
23 |
|
|
// You should have received a copy of the GNU General Public License
|
24 |
|
|
// along with eCos; if not, write to the Free Software Foundation, Inc.,
|
25 |
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
26 |
|
|
//
|
27 |
|
|
// As a special exception, if other files instantiate templates or use
|
28 |
|
|
// macros or inline functions from this file, or you compile this file
|
29 |
|
|
// and link it with other works to produce a work based on this file,
|
30 |
|
|
// this file does not by itself cause the resulting work to be covered by
|
31 |
|
|
// the GNU General Public License. However the source code for this file
|
32 |
|
|
// must still be made available in accordance with section (3) of the GNU
|
33 |
|
|
// General Public License v2.
|
34 |
|
|
//
|
35 |
|
|
// This exception does not invalidate any other reasons why a work based
|
36 |
|
|
// on this file might be covered by the GNU General Public License.
|
37 |
|
|
// -------------------------------------------
|
38 |
|
|
// ####ECOSGPLCOPYRIGHTEND####
|
39 |
|
|
//==========================================================================
|
40 |
|
|
//#####DESCRIPTIONBEGIN####
|
41 |
|
|
//
|
42 |
|
|
// Author(s): hmt
|
43 |
|
|
// Contributors: hmt
|
44 |
|
|
// Date: 2000-01-24
|
45 |
|
|
// Description: Tests the Kernel Real Time Clock Converter subsystem
|
46 |
|
|
//
|
47 |
|
|
//####DESCRIPTIONEND####
|
48 |
|
|
|
49 |
|
|
#include <pkgconf/kernel.h>
|
50 |
|
|
|
51 |
|
|
#include <cyg/kernel/clock.hxx>
|
52 |
|
|
#include <cyg/kernel/thread.hxx>
|
53 |
|
|
|
54 |
|
|
#include <cyg/infra/testcase.h>
|
55 |
|
|
|
56 |
|
|
#include <cyg/kernel/clock.inl>
|
57 |
|
|
#include <cyg/kernel/thread.inl>
|
58 |
|
|
|
59 |
|
|
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
|
60 |
|
|
|
61 |
|
|
#include <cyg/infra/diag.h>
|
62 |
|
|
|
63 |
|
|
static void null_printf(const char *, ...)
|
64 |
|
|
{ /* nothing */ }
|
65 |
|
|
|
66 |
|
|
#define PRINTF0 diag_printf
|
67 |
|
|
#define nPRINTF0 null_printf
|
68 |
|
|
|
69 |
|
|
#define nPRINTF1 diag_printf
|
70 |
|
|
#define PRINTF1 null_printf
|
71 |
|
|
|
72 |
|
|
#define nPRINTF2 diag_printf
|
73 |
|
|
#define PRINTF2 null_printf
|
74 |
|
|
|
75 |
|
|
|
76 |
|
|
#define NTHREADS 1
|
77 |
|
|
#include "testaux.hxx"
|
78 |
|
|
|
79 |
|
|
static struct { cyg_uint32 ns; double scale; } ns_tickers[] = {
|
80 |
|
|
{ 70000000, 7.0 }, // 7cS
|
81 |
|
|
{ 50000000, 5.0 }, // 5cS
|
82 |
|
|
{ 45000000, 4.5 }, // 4.5cS
|
83 |
|
|
{ 30000000, 3.0 }, // 3cS
|
84 |
|
|
{ 20000000, 2.0 }, // 2cS
|
85 |
|
|
{ 10000000, 1.0 }, // 1cS - no change
|
86 |
|
|
{ 5000000, 0.5 }, // 1/2 a cS
|
87 |
|
|
{ 4900000, 0.49 }, // a bit below
|
88 |
|
|
{ 3333333, 0.3333333 }, // 1/3 cS
|
89 |
|
|
{ 1250000, 0.125 }, // 800Hz
|
90 |
|
|
{ 1000000, 0.1 }, // 1000Hz
|
91 |
|
|
{ 909090, 0.0909090 }, // 1100Hz
|
92 |
|
|
{ 490000, 0.049 }, // 490uS
|
93 |
|
|
{ 333333, 0.0333333 }, // 1/30 cS, 1/3mS
|
94 |
|
|
{ 49000, 0.0049 }, // 49uS
|
95 |
|
|
{ 33333, 0.0033333 }, // 1/30 mS
|
96 |
|
|
{ 4900, 0.00049 }, // 4.9uS
|
97 |
|
|
// now some outlandish ones
|
98 |
|
|
{ 170, 0.000017 }, // 170nS
|
99 |
|
|
{ 11, 0.0000011 }, // 11nS
|
100 |
|
|
{ 1000000000u, 100.0 }, // one second
|
101 |
|
|
{ 1234567777u, 123.4567777 }, // 1.234... seconds
|
102 |
|
|
{ 4294967291u, 429.4967291 }, // 4.3 seconds, nearly maxint.
|
103 |
|
|
// now some which are prime in the nS per tick field
|
104 |
|
|
{ 909091, 0.0909091 }, // also 1100Hz - but 909091 is a prime!
|
105 |
|
|
// and some eye-pleasing primes from the www - if they're not actually
|
106 |
|
|
// prime, don't blame me. http://www.rsok.com/~jrm/printprimes.html
|
107 |
|
|
{ 1000003, 0.1000003 },
|
108 |
|
|
{ 1477771, 0.1477771 },
|
109 |
|
|
{ 2000003, 0.2000003 },
|
110 |
|
|
{ 2382001, 0.2382001 },
|
111 |
|
|
{ 3333133, 0.3333133 },
|
112 |
|
|
{ 3999971, 0.3999971 },
|
113 |
|
|
{ 5555591, 0.5555591 },
|
114 |
|
|
{ 6013919, 0.6013919 },
|
115 |
|
|
// That's enough
|
116 |
|
|
};
|
117 |
|
|
|
118 |
|
|
static void entry0( CYG_ADDRWORD data )
|
119 |
|
|
{
|
120 |
|
|
// First just try it with the clock as default:
|
121 |
|
|
Cyg_Clock *rtc = Cyg_Clock::real_time_clock;
|
122 |
|
|
|
123 |
|
|
Cyg_Clock::converter cv, rcv;
|
124 |
|
|
Cyg_Clock::cyg_resolution res;
|
125 |
|
|
|
126 |
|
|
unsigned int counter = 0;
|
127 |
|
|
unsigned int skipped = 0;
|
128 |
|
|
|
129 |
|
|
unsigned int i;
|
130 |
|
|
for ( i = 0; i < sizeof( ns_tickers )/sizeof( ns_tickers[0] ); i++ ) {
|
131 |
|
|
|
132 |
|
|
unsigned int lcounter = 0;
|
133 |
|
|
unsigned int lskipped = 0;
|
134 |
|
|
|
135 |
|
|
rtc->get_other_to_clock_converter( ns_tickers[i].ns, &cv );
|
136 |
|
|
rtc->get_clock_to_other_converter( ns_tickers[i].ns, &rcv );
|
137 |
|
|
|
138 |
|
|
PRINTF1( "ns per tick: %d\n", ns_tickers[i].ns );
|
139 |
|
|
PRINTF1( " converter: * %d / %d * %d / %d\n",
|
140 |
|
|
(int)cv.mul1, (int)cv.div1, (int)cv.mul2,(int) cv.div2 );
|
141 |
|
|
PRINTF1( " reverser: * %d / %d * %d / %d\n",
|
142 |
|
|
(int)rcv.mul1, (int)rcv.div1, (int)rcv.mul2, (int)rcv.div2 );
|
143 |
|
|
|
144 |
|
|
double d = 1.0;
|
145 |
|
|
d *= (double)cv.mul1;
|
146 |
|
|
d /= (double)cv.div1;
|
147 |
|
|
d *= (double)cv.mul2;
|
148 |
|
|
d /= (double)cv.div2;
|
149 |
|
|
d *= (double)rcv.mul1;
|
150 |
|
|
d /= (double)rcv.div1;
|
151 |
|
|
d *= (double)rcv.mul2;
|
152 |
|
|
d /= (double)rcv.div2;
|
153 |
|
|
PRINTF1( " composite product %d.%d\n",
|
154 |
|
|
(int)d, ((int)(d * 1000000) % 1000000 ) );
|
155 |
|
|
d -= 1.0;
|
156 |
|
|
CYG_TEST_CHECK( d < +0.0001, "Overflow in composite product" );
|
157 |
|
|
CYG_TEST_CHECK( d > -0.0001, "Underflow in composite product" );
|
158 |
|
|
|
159 |
|
|
res = rtc->get_resolution();
|
160 |
|
|
|
161 |
|
|
double factor_other_to_clock;
|
162 |
|
|
double factor_clock_to_other;
|
163 |
|
|
|
164 |
|
|
// res.dividend/res.divisor is the number of nS in a system
|
165 |
|
|
// clock tick. So:
|
166 |
|
|
d = (double)res.dividend/(double)res.divisor;
|
167 |
|
|
|
168 |
|
|
factor_other_to_clock = ns_tickers[i].scale * 1.0e7 / d ;
|
169 |
|
|
factor_clock_to_other = d / (ns_tickers[i].scale * 1.0e7);
|
170 |
|
|
|
171 |
|
|
unsigned int j;
|
172 |
|
|
for ( j = 1; j < 100; j++ ) {
|
173 |
|
|
cyg_uint64 delay;
|
174 |
|
|
if (cyg_test_is_simulator)
|
175 |
|
|
j += 30; // test fewer values
|
176 |
|
|
/* tr.b..m..k.. */
|
177 |
|
|
|
178 |
|
|
#ifdef CYGPKG_HAL_V85X_V850_CEB
|
179 |
|
|
j += 30; // test fewer values
|
180 |
|
|
#endif
|
181 |
|
|
|
182 |
|
|
for ( delay = j; delay < 1000000000000ll; delay *= 10 ) {
|
183 |
|
|
// get the converted result
|
184 |
|
|
cyg_uint64 result = Cyg_Clock::convert( delay, &cv );
|
185 |
|
|
|
186 |
|
|
counter++; lcounter++;
|
187 |
|
|
if ( (double)delay * (double)cv.mul1 > 1.6e+19 ||
|
188 |
|
|
(double)delay * (double)rcv.mul1 > 1.6e+19 ) {
|
189 |
|
|
// in silly territory now, give up.
|
190 |
|
|
// (that's MAXINT squared, approx.)
|
191 |
|
|
skipped++; lskipped++;
|
192 |
|
|
continue; // so the counter is accurate
|
193 |
|
|
}
|
194 |
|
|
|
195 |
|
|
PRINTF2( "delay %x%08x to result %x%08x\n",
|
196 |
|
|
(int)(delay >> 32), (int)delay,
|
197 |
|
|
(int)(result >> 32), (int)result );
|
198 |
|
|
|
199 |
|
|
// get what it should be in double maths
|
200 |
|
|
double delta = factor_other_to_clock * (double)delay;
|
201 |
|
|
if ( delta > 1000.0 ) {
|
202 |
|
|
delta = (double)result - delta;
|
203 |
|
|
delta /= (double)result;
|
204 |
|
|
CYG_TEST_CHECK( delta <= +0.01,
|
205 |
|
|
"Proportional overflow in conversion to" );
|
206 |
|
|
CYG_TEST_CHECK( delta >= -0.01,
|
207 |
|
|
"Proportional underflow in conversion to" );
|
208 |
|
|
}
|
209 |
|
|
else {
|
210 |
|
|
cyg_uint64 lo = (cyg_uint64)(delta); // assume TRUNCATION
|
211 |
|
|
cyg_uint64 hi = lo + 1;
|
212 |
|
|
CYG_TEST_CHECK( hi >= result,
|
213 |
|
|
"Range overflow in conversion to" );
|
214 |
|
|
CYG_TEST_CHECK( lo <= result,
|
215 |
|
|
"Range underflow in conversion to" );
|
216 |
|
|
}
|
217 |
|
|
|
218 |
|
|
// get the converted result
|
219 |
|
|
result = Cyg_Clock::convert( delay, &rcv );
|
220 |
|
|
|
221 |
|
|
PRINTF2( "delay %x%08x from result %x%08x\n",
|
222 |
|
|
(int)(delay >> 32), (int)delay,
|
223 |
|
|
(int)(result >> 32), (int)result );
|
224 |
|
|
|
225 |
|
|
// get what it should be in double maths
|
226 |
|
|
delta = factor_clock_to_other * (double)delay;
|
227 |
|
|
if ( delta > 1000.0 ) {
|
228 |
|
|
delta = (double)result - delta;
|
229 |
|
|
delta /= (double)result;
|
230 |
|
|
CYG_TEST_CHECK( delta <= +0.01,
|
231 |
|
|
"Proportional overflow in conversion from" );
|
232 |
|
|
CYG_TEST_CHECK( delta >= -0.01,
|
233 |
|
|
"Proportional underflow in conversion from" );
|
234 |
|
|
}
|
235 |
|
|
else {
|
236 |
|
|
cyg_uint64 lo = (cyg_uint64)(delta); // assume TRUNCATION
|
237 |
|
|
cyg_uint64 hi = lo + 1;
|
238 |
|
|
CYG_TEST_CHECK( hi >= result,
|
239 |
|
|
"Range overflow in conversion from" );
|
240 |
|
|
CYG_TEST_CHECK( lo <= result,
|
241 |
|
|
"Range underflow in conversion from" );
|
242 |
|
|
}
|
243 |
|
|
|
244 |
|
|
if (cyg_test_is_simulator)
|
245 |
|
|
break;
|
246 |
|
|
}
|
247 |
|
|
}
|
248 |
|
|
PRINTF0( "INFO:<%d nS/tick: tested %d values, skipped %d because of overflow>\n",
|
249 |
|
|
ns_tickers[i].ns, lcounter, lskipped );
|
250 |
|
|
}
|
251 |
|
|
|
252 |
|
|
PRINTF0( "INFO:<tested %d values, total skipped %d because of overflow>\n",
|
253 |
|
|
counter, skipped );
|
254 |
|
|
|
255 |
|
|
CYG_TEST_PASS_FINISH("ClockCnv OK");
|
256 |
|
|
}
|
257 |
|
|
|
258 |
|
|
void clockcnv_main( void )
|
259 |
|
|
{
|
260 |
|
|
CYG_TEST_INIT();
|
261 |
|
|
new_thread(entry0, (CYG_ADDRWORD)&thread_obj[0]);
|
262 |
|
|
Cyg_Scheduler::start();
|
263 |
|
|
}
|
264 |
|
|
|
265 |
|
|
externC void
|
266 |
|
|
cyg_start( void )
|
267 |
|
|
{
|
268 |
|
|
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
|
269 |
|
|
cyg_hal_invoke_constructors();
|
270 |
|
|
#endif
|
271 |
|
|
clockcnv_main();
|
272 |
|
|
}
|
273 |
|
|
|
274 |
|
|
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
|
275 |
|
|
|
276 |
|
|
externC void
|
277 |
|
|
cyg_start( void )
|
278 |
|
|
{
|
279 |
|
|
CYG_TEST_INIT();
|
280 |
|
|
CYG_TEST_NA( "Kernel real-time clock disabled");
|
281 |
|
|
}
|
282 |
|
|
|
283 |
|
|
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
|
284 |
|
|
|
285 |
|
|
// EOF clockcnv.cxx
|