Makefile | 3 kern.c | 473 --------------------------------------------------------------- 2 files changed, 5 insertions(+), 471 deletions(-) Index: org/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ org/Makefile 2005-10-02 04:15:28.000000000 +0200 @@ -0,0 +1,3 @@ +CFLAGS := -O1 -g -Wall + +kern: kern.c Index: org/kern.c =================================================================== --- org.orig/kern.c 2005-08-17 23:11:17.000000000 +0200 +++ org/kern.c 2005-10-02 04:15:11.000000000 +0200 @@ -66,10 +66,7 @@ struct timeval { /* avoid sys/time.h na long tv_usec; }; -/* #define PPS_SYNC /* PPS frequency discipline option */ -/* #define EXT_CLOCK /* external clock option */ #define PCCFREQ (-10) /* pcc offset frequency (ppm) */ -#define PPSFREQ (-100) /* PPS offset frequency (ppm) */ #include "timex.h" /* vax: avoid sys/syscall.h include */ @@ -191,110 +188,9 @@ long time_freq = 0; /* frequency offset long time_adj = 0; /* tick adjust (scaled 1 / hz) */ long time_reftime = 0; /* time at last adjustment (s) */ -#ifdef PPS_SYNC -/* - * The following variables are used only if the kernel PPS discipline - * code is configured (PPS_SYNC). The scale factors are defined in the - * timex.h header file. - * - * pps_time contains the time at each calibration interval, as read by - * microtime(). pps_count counts the seconds of the calibration - * interval, the duration of which is nominally pps_shift in powers of - * two. - * - * pps_offset is the time offset produced by the time median filter - * pps_tf[], while pps_jitter is the dispersion (jitter) measured by - * this filter. - * - * pps_freq is the frequency offset produced by the frequency median - * filter pps_ff[], while pps_stabil is the dispersion (wander) measured - * by this filter. - * - * pps_usec is latched from a high resolution counter or external clock - * at pps_time. Here we want the hardware counter contents only, not the - * contents plus the time_tv.usec as usual. - * - * pps_valid counts the number of seconds since the last PPS update. It - * is used as a watchdog timer to disable the PPS discipline should the - * PPS signal be lost. - * - * pps_glitch counts the number of seconds since the beginning of an - * offset burst more than tick/2 from current nominal offset. It is used - * mainly to suppress error bursts due to priority conflicts between the - * PPS interrupt and timer interrupt. - * - * pps_intcnt counts the calibration intervals for use in the interval- - * adaptation algorithm. It's just too complicated for words. - */ -struct timeval pps_time; /* kernel time at last interval */ -long pps_tf[] = {0, 0, 0}; /* pps time offset median filter (us) */ -long pps_offset = 0; /* pps time offset (us) */ -long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */ -long pps_ff[] = {0, 0, 0}; /* pps frequency offset median filter */ -long pps_freq = 0; /* frequency offset (scaled ppm) */ -long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */ -long pps_usec = 0; /* microsec counter at last interval */ -long pps_valid = PPS_VALID; /* pps signal watchdog counter */ -int pps_glitch = 0; /* pps signal glitch counter */ -int pps_count = 0; /* calibration interval counter (s) */ -int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */ -int pps_intcnt = 0; /* intervals at current duration */ - -/* - * PPS signal quality monitors - * - * pps_jitcnt counts the seconds that have been discarded because the - * jitter measured by the time median filter exceeds the limit MAXTIME - * (100 us). - * - * pps_calcnt counts the frequency calibration intervals, which are - * variable from 4 s to 256 s. - * - * pps_errcnt counts the calibration intervals which have been discarded - * because the wander exceeds the limit MAXFREQ (100 ppm) or where the - * calibration interval jitter exceeds two ticks. - * - * pps_stbcnt counts the calibration intervals that have been discarded - * because the frequency wander exceeds the limit MAXFREQ / 4 (25 us). - */ -long pps_jitcnt = 0; /* jitter limit exceeded */ -long pps_calcnt = 0; /* calibration intervals */ -long pps_errcnt = 0; /* calibration errors */ -long pps_stbcnt = 0; /* stability limit exceeded */ -#endif /* PPS_SYNC */ - -#ifdef EXT_CLOCK -/* - * External clock definitions - * - * The following definitions and declarations are used only if an - * external clock is configured on the system. - */ -#define CLOCK_INTERVAL 30 /* CPU clock update interval (s) */ - -/* - * The clock_count variable is set to CLOCK_INTERVAL at each PPS - * interrupt and decremented once each second. - */ -int clock_count = 0; /* CPU clock counter */ - -#ifdef HIGHBALL -/* - * The clock_offset and clock_cpu variables are used by the HIGHBALL - * interface. The clock_offset variable defines the offset between - * system time and the HIGBALL counters. The clock_cpu variable contains - * the offset between the system clock and the HIGHBALL clock for use in - * disciplining the kernel time variable. - */ -extern struct timeval clock_offset; /* Highball clock offset */ -long clock_cpu = 0; /* CPU clock adjust */ -#endif /* HIGHBALL */ -#endif /* EXT_CLOCK */ - /* * Function declarations */ -#if defined(__GNUC__) || defined(MSDOS) /* for gcc and Microsoft C */ void hardupdate(long); void hardclock(void); void second_overflow(void); @@ -302,15 +198,6 @@ void hardpps(struct timeval *, long); void microtime(struct timeval *); void microset(void); void kern(void); -#else /* __GNUC__ */ /* for cc */ -void hardupdate(); -void hardclock(); -void second_overflow(); -void hardpps(); -void microtime(); -void microset(); -void kern(); -#endif /* __GNUC__ */ /* * Kernel variables @@ -343,8 +230,7 @@ static long ppsusec; /* pps microsecond * KSI/Odetics TPRO IRIG-B interface), but do not fully test the * functionality of the PPS signal or external clock interfaces. */ -void -main() +int main() { int i; while (scanf("%ld %d %d %d %ld %ld", &simtime, &time_status, @@ -388,13 +274,10 @@ main() simtime, time_status, tau, time.tv_usec, pllfreq); (void)printf("tick %d us, fixtick %d us\n", tick, fixtick); -#ifdef PPS_SYNC - (void)printf(" time offset freq ppsofs ppsfrq cal _offset _freq _adj\n"); -#else /* PPS_SYNC */ (void)printf(" time offset freq _offset _freq _adj\n"); -#endif /* PPS_SYNC */ kern(); } + return 0; } /* @@ -419,14 +302,6 @@ kern() #ifdef MICRO microset(); #endif /* MICRO */ -#ifdef PPS_SYNC - ppsusec += PPSFREQ; - if (ppsusec >= tick) - ppsusec -= tick; - if (ppsusec < 0) - ppsusec += tick; - hardpps(&time, ppsusec); -#endif /* PPS_SYNC */ poll_interval++; if (!(poll_interval % poll)) { microtime(×); @@ -434,17 +309,6 @@ kern() (double)times.tv_sec) * 1e6 - (double)times.tv_usec); hardupdate(phi); -#ifdef PPS_SYNC - (void)printf("%6ld%8ld%9.3lf%8li%8.3lf %4i %08lx %08lx %08lx\n", - time.tv_sec, phi, - (double)time_freq / (1L << - SHIFT_USEC), pps_offset, - (double)pps_freq / (1L << - SHIFT_USEC), 1 << pps_shift, - time_offset & 0xffffffff, - time_freq & 0xffffffff, - time_adj & 0xffffffff); -#else /* PPS_SYNC */ (void)printf("%6ld%8ld%9.3lf %08lx %08lx %08lx\n", time.tv_sec, phi, (double)time_freq / (1L << @@ -452,7 +316,6 @@ kern() time_offset & 0xffffffff, time_freq & 0xffffffff, time_adj & 0xffffffff); -#endif /* PPS_SYNC */ } } } @@ -488,34 +351,7 @@ hardclock() time_update += ltemp; } -#ifdef HIGHBALL - /* - * If the HIGHBALL board is installed, we need to adjust the - * external clock offset in order to close the hardware feedback - * loop. This will adjust the external clock phase and frequency - * in small amounts. The additional phase noise and frequency - * wander this causes should be minimal. We also need to - * discipline the kernel time variable, since the PLL is used to - * discipline the external clock. If the Highball board is not - * present, we discipline kernel time with the PLL as usual. We - * assume that the external clock phase adjustment (time_update) - * and kernel phase adjustment (clock_cpu) are less than the - * value of tick. - */ - clock_offset.tv_usec += time_update; - if (clock_offset.tv_usec >= 1000000) { - clock_offset.tv_sec++; - clock_offset.tv_usec -= 1000000; - } - if (clock_offset.tv_usec < 0) { - clock_offset.tv_sec--; - clock_offset.tv_usec += 1000000; - } - time.tv_usec += clock_cpu; - clock_cpu = 0; -#else time.tv_usec += time_update; -#endif /* HIGHBALL */ /* * End of precision-kernel code fragment @@ -530,9 +366,6 @@ void second_overflow() { long ltemp; -#ifdef EXT_CLOCK - struct timeval delta, clock_ext; -#endif /* EXT_CLOCK */ /* * Beginning of precision-kernel code fragment @@ -632,18 +465,7 @@ second_overflow() * watchdog counter and update the frequency computed by * the pll and the PPS signal. */ -#ifdef PPS_SYNC - pps_valid++; - if (pps_valid == PPS_VALID) { - pps_jitter = MAXTIME; - pps_stabil = MAXFREQ; - time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | - STA_PPSWANDER | STA_PPSERROR); - } - ltemp = time_freq + pps_freq; -#else ltemp = time_freq; -#endif /* PPS_SYNC */ if (ltemp < 0) time_adj -= -ltemp >> (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); @@ -669,47 +491,6 @@ second_overflow() time_adj += time_adj >> 2; } #endif /* SHIFT_HZ */ - -#ifdef EXT_CLOCK - /* - * If an external clock is present, it is necessary to - * discipline the kernel time variable anyway, since not - * all system components use the microtime() interface. - * Here, the time offset between the external clock and - * kernel time variable is computed every so often. - */ - clock_count++; - if (clock_count > CLOCK_INTERVAL) { - clock_count = 0; - microtime(&clock_ext); - delta.tv_sec = clock_ext.tv_sec - time.tv_sec; - delta.tv_usec = clock_ext.tv_usec - - time.tv_usec; - if (delta.tv_usec < 0) - delta.tv_sec--; - if (delta.tv_usec >= 500000) { - delta.tv_usec -= 1000000; - delta.tv_sec++; - } - if (delta.tv_usec < -500000) { - delta.tv_usec += 1000000; - delta.tv_sec--; - } - if (delta.tv_sec > 0 || (delta.tv_sec == 0 && - delta.tv_usec > MAXPHASE) || - delta.tv_sec < -1 || (delta.tv_sec == -1 && - delta.tv_usec < -MAXPHASE)) { - time = clock_ext; - delta.tv_sec = 0; - delta.tv_usec = 0; - } -#ifdef HIGHBALL - clock_cpu = delta.tv_usec; -#else /* HIGHBALL */ - hardupdate(delta.tv_usec); -#endif /* HIGHBALL */ - } -#endif /* EXT_CLOCK */ } /* @@ -748,10 +529,6 @@ hardupdate(offset) if (!(time_status & STA_PLL) && !(time_status & STA_PPSTIME)) return; ltemp = offset; -#ifdef PPS_SYNC - if (time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL) - ltemp = pps_offset; -#endif /* PPS_SYNC */ /* * Scale the phase adjustment and clamp to the operating range. @@ -800,252 +577,6 @@ hardupdate(offset) time_freq = -time_tolerance; } -#ifdef PPS_SYNC -/* - * hardpps() - discipline CPU clock oscillator to external PPS signal - * - * This routine is called at each PPS interrupt in order to discipline - * the CPU clock oscillator to the PPS signal. It measures the PPS phase - * and leaves it in a handy spot for the hardclock() routine. It - * integrates successive PPS phase differences and calculates the - * frequency offset. This is used in hardclock() to discipline the CPU - * clock oscillator so that intrinsic frequency error is cancelled out. - * The code requires the caller to capture the time and hardware counter - * value at the on-time PPS signal transition. - * - * Note that, on some Unix systems, this routine runs at an interrupt - * priority level higher than the timer interrupt routine hardclock(). - * Therefore, the variables used are distinct from the hardclock() - * variables, except for certain exceptions: The PPS frequency pps_freq - * and phase pps_offset variables are determined by this routine and - * updated atomically. The time_tolerance variable can be considered a - * constant, since it is infrequently changed, and then only when the - * PPS signal is disabled. The watchdog counter pps_valid is updated - * once per second by hardclock() and is atomically cleared in this - * routine. - */ -void -hardpps(tvp, usec) - struct timeval *tvp; /* time at PPS */ - long usec; /* hardware counter at PPS */ -{ - long u_usec, v_usec, bigtick; - long cal_sec, cal_usec; - - /* - * An occasional glitch can be produced when the PPS interrupt - * occurs in the hardclock() routine before the time variable is - * updated. Here the offset is discarded when the difference - * between it and the last one is greater than tick/2, but not - * if the interval since the first discard exceeds 30 s. - */ - time_status |= STA_PPSSIGNAL; - time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); - pps_valid = 0; - u_usec = -tvp->tv_usec; - if (u_usec < -500000) - u_usec += 1000000; - v_usec = pps_offset - u_usec; - if (v_usec < 0) - v_usec = -v_usec; - if (v_usec > (tick >> 1)) { - if (pps_glitch > MAXGLITCH) { - pps_glitch = 0; - pps_tf[2] = u_usec; - pps_tf[1] = u_usec; - } else { - pps_glitch++; - u_usec = pps_offset; - } - } else - pps_glitch = 0; - - /* - * A three-stage median filter is used to help deglitch the pps - * time. The median sample becomes the time offset estimate; the - * difference between the other two samples becomes the time - * dispersion (jitter) estimate. - */ - pps_tf[2] = pps_tf[1]; - pps_tf[1] = pps_tf[0]; - pps_tf[0] = u_usec; - if (pps_tf[0] > pps_tf[1]) { - if (pps_tf[1] > pps_tf[2]) { - pps_offset = pps_tf[1]; /* 0 1 2 */ - v_usec = pps_tf[0] - pps_tf[2]; - } else if (pps_tf[2] > pps_tf[0]) { - pps_offset = pps_tf[0]; /* 2 0 1 */ - v_usec = pps_tf[2] - pps_tf[1]; - } else { - pps_offset = pps_tf[2]; /* 0 2 1 */ - v_usec = pps_tf[0] - pps_tf[1]; - } - } else { - if (pps_tf[1] < pps_tf[2]) { - pps_offset = pps_tf[1]; /* 2 1 0 */ - v_usec = pps_tf[2] - pps_tf[0]; - } else if (pps_tf[2] < pps_tf[0]) { - pps_offset = pps_tf[0]; /* 1 0 2 */ - v_usec = pps_tf[1] - pps_tf[2]; - } else { - pps_offset = pps_tf[2]; /* 1 2 0 */ - v_usec = pps_tf[1] - pps_tf[0]; - } - } - if (v_usec > MAXTIME) - pps_jitcnt++; - v_usec = (v_usec << PPS_AVG) - pps_jitter; - if (v_usec < 0) - pps_jitter -= -v_usec >> PPS_AVG; - else - pps_jitter += v_usec >> PPS_AVG; - if (pps_jitter > (MAXTIME >> 1)) - time_status |= STA_PPSJITTER; - - /* - * During the calibration interval adjust the starting time when - * the tick overflows. At the end of the interval compute the - * duration of the interval and the difference of the hardware - * counters at the beginning and end of the interval. This code - * is deliciously complicated by the fact valid differences may - * exceed the value of tick when using long calibration - * intervals and small ticks. Note that the counter can be - * greater than tick if caught at just the wrong instant, but - * the values returned and used here are correct. - */ - bigtick = (long)tick << SHIFT_USEC; - pps_usec -= pps_freq; - if (pps_usec >= bigtick) - pps_usec -= bigtick; - if (pps_usec < 0) - pps_usec += bigtick; - pps_time.tv_sec++; - pps_count++; - if (pps_count < (1 << pps_shift)) - return; - pps_count = 0; - pps_calcnt++; - u_usec = usec << SHIFT_USEC; - v_usec = pps_usec - u_usec; - if (v_usec >= bigtick >> 1) - v_usec -= bigtick; - if (v_usec < -(bigtick >> 1)) - v_usec += bigtick; - if (v_usec < 0) - v_usec = -(-v_usec >> pps_shift); - else - v_usec = v_usec >> pps_shift; - pps_usec = u_usec; - cal_sec = tvp->tv_sec; - cal_usec = tvp->tv_usec; - cal_sec -= pps_time.tv_sec; - cal_usec -= pps_time.tv_usec; - if (cal_usec < 0) { - cal_usec += 1000000; - cal_sec--; - } - pps_time = *tvp; - - /* - * Check for lost interrupts, noise, excessive jitter and - * excessive frequency error. The number of timer ticks during - * the interval may vary +-1 tick. Add to this a margin of one - * tick for the PPS signal jitter and maximum frequency - * deviation. If the limits are exceeded, the calibration - * interval is reset to the minimum and we start over. - */ - u_usec = (long)tick << 1; - if (!((cal_sec == -1 && cal_usec > (1000000 - u_usec)) - || (cal_sec == 0 && cal_usec < u_usec)) - || v_usec > time_tolerance || v_usec < -time_tolerance) { - pps_errcnt++; - pps_shift = PPS_SHIFT; - pps_intcnt = 0; - time_status |= STA_PPSERROR; - return; - } - - /* - * A three-stage median filter is used to help deglitch the pps - * frequency. The median sample becomes the frequency offset - * estimate; the difference between the other two samples - * becomes the frequency dispersion (stability) estimate. - */ - pps_ff[2] = pps_ff[1]; - pps_ff[1] = pps_ff[0]; - pps_ff[0] = v_usec; - if (pps_ff[0] > pps_ff[1]) { - if (pps_ff[1] > pps_ff[2]) { - u_usec = pps_ff[1]; /* 0 1 2 */ - v_usec = pps_ff[0] - pps_ff[2]; - } else if (pps_ff[2] > pps_ff[0]) { - u_usec = pps_ff[0]; /* 2 0 1 */ - v_usec = pps_ff[2] - pps_ff[1]; - } else { - u_usec = pps_ff[2]; /* 0 2 1 */ - v_usec = pps_ff[0] - pps_ff[1]; - } - } else { - if (pps_ff[1] < pps_ff[2]) { - u_usec = pps_ff[1]; /* 2 1 0 */ - v_usec = pps_ff[2] - pps_ff[0]; - } else if (pps_ff[2] < pps_ff[0]) { - u_usec = pps_ff[0]; /* 1 0 2 */ - v_usec = pps_ff[1] - pps_ff[2]; - } else { - u_usec = pps_ff[2]; /* 1 2 0 */ - v_usec = pps_ff[1] - pps_ff[0]; - } - } - - /* - * Here the frequency dispersion (stability) is updated. If it - * is less than one-fourth the maximum (MAXFREQ), the frequency - * offset is updated as well, but clamped to the tolerance. It - * will be processed later by the hardclock() routine. - */ - v_usec = (v_usec >> 1) - pps_stabil; - if (v_usec < 0) - pps_stabil -= -v_usec >> PPS_AVG; - else - pps_stabil += v_usec >> PPS_AVG; - if (pps_stabil > MAXFREQ >> 2) { - pps_stbcnt++; - time_status |= STA_PPSWANDER; - return; - } - if (time_status & STA_PPSFREQ) { - if (u_usec < 0) { - pps_freq -= -u_usec >> PPS_AVG; - if (pps_freq < -time_tolerance) - pps_freq = -time_tolerance; - u_usec = -u_usec; - } else { - pps_freq += u_usec >> PPS_AVG; - if (pps_freq > time_tolerance) - pps_freq = time_tolerance; - } - } - - /* - * Here the calibration interval is adjusted. If the maximum - * time difference is greater than tick / 4, reduce the interval - * by half. If this is not the case for four consecutive - * intervals, double the interval. - */ - if (u_usec << pps_shift > bigtick >> 2) { - pps_intcnt = 0; - if (pps_shift > PPS_SHIFT) - pps_shift--; - } else if (pps_intcnt >= 4) { - pps_intcnt = 0; - if (pps_shift < PPS_SHIFTMAX) - pps_shift++; - } else - pps_intcnt++; -} -#endif /* PPS_SYNC */ - /* * The following routines are used to interpolate the microseconds * between timer interrupts. This is done using the process cycle