kern.c | 105 +++++++++++++++++++++------------------------------------------ kern.dat | 62 ++++++++++++++++++++++--------------- nano.sh | 43 +++++++++++++++++++++++++ timex.h | 22 +++++-------- 4 files changed, 126 insertions(+), 106 deletions(-) Index: n/kern.c =================================================================== --- n.orig/kern.c 2005-12-21 19:03:04.000000000 +0100 +++ n/kern.c 2005-12-21 20:01:46.000000000 +0100 @@ -58,18 +58,10 @@ * 4000 0 2 64 100000 0 */ #include +#include #include #include -struct timeval { /* avoid sys/time.h name conflicts */ - long tv_sec; - long tv_usec; -}; -struct timespec { - long tv_sec; - long tv_nsec; -}; - #define PCCFREQ (-10) /* pcc offset frequency (ppm) */ #include "timex.h" /* vax: avoid sys/syscall.h include */ @@ -191,8 +183,8 @@ long time_offset = 0; /* time offset (u long time_constant = 0; /* pll time constant */ long time_tolerance = MAXFREQ; /* frequency tolerance (scaled ppm) */ long time_precision = 1; /* clock precision (us) */ -long time_maxerror = MAXPHASE; /* maximum error (us) */ -long time_esterror = MAXPHASE; /* estimated error (us) */ +long time_maxerror = MAXPHASE / 1000; /* maximum error (us) */ +long time_esterror = MAXPHASE / 1000; /* estimated error (us) */ /* * The following variables establish the state of the PLL/FLL and the @@ -290,13 +282,13 @@ int main() f += (t % hz) << (SHIFT_USEC - 3); f <<= 3; shift_hz = fls(hz - 1); - time.tv_sec = 0; + time.tv_sec = -1; time.tv_nsec = offset * 1000; - time_us = 0; + time_us = -1; cycles = 0; phi = 0; - poll_interval = 0; + poll_interval = -1; ppsusec = 0; time_state = TIME_OK; @@ -305,8 +297,8 @@ int main() time_constant = tau; time_tolerance = MAXFREQ; time_precision = 1; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; + time_maxerror = MAXPHASE / 1000; + time_esterror = MAXPHASE / 1000; time_phase = 0; time_freq = 0; @@ -365,11 +357,10 @@ kern() phi = (long)((time_us - (double)times.tv_sec) * 1e9 - (double)times.tv_nsec); - hardupdate(phi / 1000); + hardupdate(phi); (void)printf("%6ld.%09lu%11ld%9.3lf %08lx %08lx %11u %08lx\n", time.tv_sec, time.tv_nsec, phi, - (double)time_freq / (1L << - SHIFT_USEC), + (double)time_freq / (1L << SHIFT_NSEC) / 1000, time_offset & 0xffffffff, time_freq & 0xffffffff, tick, @@ -437,7 +428,7 @@ second_overflow() if (time.tv_nsec >= 1000000000) { time.tv_nsec -= 1000000000; time.tv_sec++; - time_maxerror += time_tolerance >> SHIFT_USEC; + time_maxerror += (time_tolerance / 1000) >> SHIFT_NSEC; /* * Leap second processing. If in leap-insert state at @@ -492,11 +483,7 @@ second_overflow() * seconds between updates. */ if (time_offset < 0) { - ltemp = -time_offset; - if (!(time_status & STA_FLL)) - ltemp >>= SHIFT_KG + time_constant; - if (ltemp > (((MAXPHASE * 1000 / hz) << shift_hz) / MINSEC)) - ltemp = ((MAXPHASE * 1000 / hz) << shift_hz) / MINSEC; + ltemp = -time_offset >> (SHIFT_PLL + time_constant); time_offset += ltemp; tick_curr -= ltemp >> shift_hz; time_adj_curr -= (ltemp << (SHIFT_SCALE - shift_hz)) & ((1 << SHIFT_SCALE) - 1); @@ -505,11 +492,7 @@ second_overflow() time_adj_curr += (1 << (SHIFT_SCALE)); } } else { - ltemp = time_offset; - if (!(time_status & STA_FLL)) - ltemp >>= SHIFT_KG + time_constant; - if (ltemp > (((MAXPHASE * 1000 / hz) << shift_hz) / MINSEC)) - ltemp = ((MAXPHASE * 1000 / hz) << shift_hz) / MINSEC; + ltemp = time_offset >> (SHIFT_PLL + time_constant); time_offset -= ltemp; tick_curr += ltemp >> shift_hz; time_adj_curr += (ltemp << (SHIFT_SCALE - shift_hz)) & ((1 << SHIFT_SCALE) - 1); @@ -569,6 +552,7 @@ hardupdate(offset) long offset; { long ltemp, mtemp; + int64_t freq_adj = 0; if (!(time_status & STA_PLL)) goto skip; @@ -593,53 +577,36 @@ hardupdate(offset) time_reftime = time.tv_sec; mtemp = time.tv_sec - time_reftime; time_reftime = time.tv_sec; - if (time_status & STA_FLL) { - if (mtemp >= MINSEC) { - ltemp = (((time_offset << SHIFT_UPDATE) / mtemp) << (SHIFT_USEC - SHIFT_UPDATE)); - if (ltemp < 0) - time_freq -= -ltemp >> SHIFT_KH; - else - time_freq += ltemp >> SHIFT_KH; - } - } else { - if (mtemp < MAXSEC) { - ltemp *= mtemp; - if (ltemp < 0) - time_freq -= -ltemp >> (time_constant + - time_constant + SHIFT_KF - - SHIFT_USEC); - else - time_freq += ltemp >> (time_constant + - time_constant + SHIFT_KF - - SHIFT_USEC); - } - } - time_offset = ((time_offset * 1000) / hz) << shift_hz; - if (time_freq > time_tolerance) + freq_adj = (int64_t)time_offset * mtemp; + if (freq_adj < 0) + freq_adj = -(-freq_adj >> + ((time_constant + SHIFT_PLL + 2) * 2 - SHIFT_NSEC)); + else + freq_adj = freq_adj >> + ((time_constant + SHIFT_PLL + 2) * 2 - SHIFT_NSEC); + if (mtemp >= MINSEC && (time_status & STA_FLL)) + freq_adj += ((int64_t)time_offset << (SHIFT_NSEC - SHIFT_FLL)) / mtemp; + + time_offset = (time_offset / hz) << shift_hz; + freq_adj += time_freq; + if (freq_adj > time_tolerance) time_freq = time_tolerance; - else if (time_freq < -time_tolerance) + else if (freq_adj < -time_tolerance) time_freq = -time_tolerance; + else + time_freq = freq_adj; skip: { - long t, f; + long t; - f = time_freq; - t = f >> 24; - if (t) { - f -= t << 24; - t *= 1000 << (24 - SHIFT_USEC); - } - f *= 125; - t += 1000000000 + (f >> (SHIFT_USEC - 3)); - f &= (1 << (SHIFT_USEC - 3)) - 1; + t = 1000000000 + (time_freq >> SHIFT_NSEC); tick = t / hz; - f += (t % hz) << (SHIFT_USEC - 3); - f <<= SHIFT_SCALE - (SHIFT_USEC - 3); - time_adj = f / hz; - //time_freq_adj = f % hz; - //time_freq = time_adj << shift_hz; + t = (t % hz) << SHIFT_NSEC; + t += time_freq & ((1 << SHIFT_NSEC) - 1); + t <<= SHIFT_SCALE - SHIFT_NSEC; + time_adj = t / hz; } } Index: n/kern.dat =================================================================== --- n.orig/kern.dat 2005-12-21 19:03:04.000000000 +0100 +++ n/kern.dat 2005-12-21 19:27:56.000000000 +0100 @@ -1,24 +1,38 @@ -4000 0 2 64 100000 0 -4000 0 2 64 -100000 0 -8000 0 2 64 0 100 -8000 0 2 64 0 -100 -20000 8 0 1024 100000 0 -20000 8 0 1024 -100000 0 -20000 8 0 1024 0 100 -20000 8 0 1024 0 -100 -10000 0 0 16 500 500 -10000 0 0 16 -500 -500 -10000 0 0 16 500 -500 -10000 0 0 16 -500 500 -10000 8 0 256 500 500 -10000 8 0 256 -500 -500 -10000 8 0 256 500 -500 -10000 8 0 256 -500 500 -4000 0 0 16 1000000 0 -4000 0 0 16 -1000000 0 -4000 0 0 16 0 1000 -4000 0 0 16 0 -1000 -10000 8 0 256 1000000 0 -10000 8 0 256 -1000000 0 -10000 8 0 256 100000 1000 -10000 8 0 256 0 -1000 +4000 0 6 64 100000 0 +4000 0 6 64 -100000 0 +8000 0 6 64 0 100 +8000 0 6 64 0 -100 +20000 8 10 1024 100000 0 +20000 8 10 1024 -100000 0 +20000 8 10 1024 0 100 +20000 8 10 1024 0 -100 +10000 0 4 16 500 500 +10000 0 4 16 -500 -500 +10000 0 4 16 500 -500 +10000 0 4 16 -500 500 +10000 8 8 256 500 500 +10000 8 8 256 -500 -500 +10000 8 8 256 500 -500 +10000 8 8 256 -500 500 +4000 0 4 16 1000000 0 +4000 0 4 16 -1000000 0 +4000 0 4 16 0 1000 +4000 0 4 16 0 -1000 +10000 8 8 256 1000000 0 +10000 8 8 256 -1000000 0 +10000 8 8 256 100000 1000 +10000 8 8 256 0 -1000 +4000 0 0 1 -500000 500 +4000 0 0 1 -500000 -500 +4000 0 0 1 500000 500 +4000 0 0 1 500000 -500 +1000 0 0 1 -500000 0 +3200 0 6 64 -500000 0 +50000 0 10 1024 -500000 0 +1000 8 0 256 -1000 0 +4000 8 0 1024 -1000 0 +10000 8 0 4096 -1000 0 +15000 8 0 256 -500000 500 +15000 8 0 256 -500000 -500 +15000 8 0 256 500000 500 +15000 8 0 256 500000 -500 Index: n/nano.sh =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ n/nano.sh 2005-12-21 19:28:11.000000000 +0100 @@ -0,0 +1,43 @@ +path=${1:-./nanokernel} +$path/kern -s 4000 -t 6 -p -100000 +$path/kern -s 4000 -t 6 -p 100000 +$path/kern -s 8000 -t 6 -f 100 +$path/kern -s 8000 -t 6 -f -100 +$path/kern -s 20000 -l 1024 -t 10 -p -100000 +$path/kern -s 20000 -l 1024 -t 10 -p 100000 +$path/kern -s 20000 -l 1024 -t 10 -f 100 +$path/kern -s 20000 -l 1024 -t 10 -f -100 +$path/kern -s 10000 -t 4 -p -500 -f 500 +$path/kern -s 10000 -t 4 -p 500 -f -500 +$path/kern -s 10000 -t 4 -p -500 -f -500 +$path/kern -s 10000 -t 4 -p 500 -f 500 +$path/kern -s 10000 -l 256 -t 8 -p -500 -f 500 +$path/kern -s 10000 -l 256 -t 8 -p 500 -f -500 +$path/kern -s 10000 -l 256 -t 8 -p -500 -f -500 +$path/kern -s 10000 -l 256 -t 8 -p 500 -f 500 +$path/kern -s 4000 -t 4 -p -1000000 +$path/kern -s 4000 -t 4 -p 1000000 +$path/kern -s 4000 -t 4 -f 1000 +$path/kern -s 4000 -t 4 -f -1000 +$path/kern -s 10000 -l 256 -t 8 -p -1000000 +$path/kern -s 10000 -l 256 -t 8 -p 1000000 +$path/kern -s 10000 -l 256 -t 8 -p -1000000 -f 1000 +$path/kern -s 10000 -l 256 -t 8 -f -1000 +# test extreme phase/frequency envelope +$path/kern -s 4000 -p 500000 -f 500 -t 0 +$path/kern -s 4000 -p 500000 -f -500 -t 0 +$path/kern -s 4000 -p -500000 -f 500 -t 0 +$path/kern -s 4000 -p -500000 -f -500 -t 0 +# test for overflow at different poll intervals +$path/kern -s 1000 -p 500000 -t 0 +$path/kern -s 3200 -p 500000 -t 6 +$path/kern -s 50000 -p 500000 -t 10 +# test fll at different poll intervals +$path/kern -s 1000 -p 1000 -f 0 -l 256 +$path/kern -s 4000 -p 1000 -f 0 -l 1024 +$path/kern -s 10000 -p 1000 -f 0 -l 4096 +test fll at extreme phase/frequency envelope +$path/kern -s 15000 -p 500000 -f 500 -l 256 +$path/kern -s 15000 -p 500000 -f -500 -l 256 +$path/kern -s 15000 -p -500000 -f 500 -l 256 +$path/kern -s 15000 -p -500000 -f -500 -l 256 Index: n/timex.h =================================================================== --- n.orig/timex.h 2005-12-21 19:03:04.000000000 +0100 +++ n/timex.h 2005-12-21 19:03:08.000000000 +0100 @@ -94,10 +94,11 @@ * respectively. */ #define SHIFT_HZ 7 /* log2(hz) */ -#define SHIFT_KG 6 /* phase factor (shift) */ -#define SHIFT_KF 16 /* PLL frequency factor (shift) */ #define SHIFT_KH 2 /* FLL frequency factor (shift) */ -#define MAXTC 6 /* maximum time constant (shift) */ + +#define SHIFT_PLL 4 +#define SHIFT_FLL 2 +#define MAXTC 10 /* maximum time constant (shift) */ /* * The following defines establish the scaling of the various variables @@ -119,9 +120,9 @@ * FINEUSEC is 1 us in SHIFT_UPDATE units of the time_phase variable. */ #define SHIFT_SCALE 22 /* phase scale (shift) */ -#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* time offset scale (shift) */ #define SHIFT_USEC 16 /* frequency offset scale (shift) */ #define FINEUSEC (1L << SHIFT_SCALE) /* 1 us in phase units */ +#define SHIFT_NSEC 12 /* * The following defines establish the performance envelope of the PLL. @@ -154,15 +155,10 @@ * MINSEC and MAXSEC define the lower and upper bounds on the interval * between protocol updates. */ -#define MAXPHASE 512000L /* max phase error (us) */ -#ifdef PPS_SYNC -#define MAXFREQ (512L << SHIFT_USEC) /* max freq error (100 ppm) */ -#define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */ -#else -#define MAXFREQ (512L << SHIFT_USEC) /* max freq error (200 ppm) */ -#endif /* PPS_SYNC */ -#define MINSEC 16L /* min interval between updates (s) */ -#define MAXSEC 1200L /* max interval between updates (s) */ +#define MAXPHASE 500000000L /* max phase error (ns) */ +#define MAXFREQ (500000L << SHIFT_NSEC) /* max freq error (100 ppm) */ +#define MINSEC 256 /* min interval between updates (s) */ +#define MAXSEC 2048 /* max interval between updates (s) */ #ifdef PPS_SYNC /*