summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2023-02-27 14:49:09 -0700
committerSebastian Huber <sebastian.huber@embedded-brains.de>2023-03-07 07:30:44 +0100
commitd9f5345df6e6c37d6fbe2aafa85f40e6bfb8cd0b (patch)
tree6a6aa014c2ef25d4923f85f4d5a6274b662efc86
parentpps: Directly assign the timestamps in pps_event() (diff)
downloadrtems-d9f5345df6e6c37d6fbe2aafa85f40e6bfb8cd0b.tar.bz2
pps: Simplify the nsec calculation in pps_event()
Let A be the current calculation of the frequency accumulator (pps_fcount) update in pps_event() scale = (uint64_t)1 << 63; scale /= captc->tc_frequency; scale *= 2; bt.sec = 0; bt.frac = 0; bintime_addx(&bt, scale * tcount); bintime2timespec(&bt, &ts); hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); and hardpps(..., delta_nsec): u_nsec = delta_nsec; if (u_nsec > (NANOSECOND >> 1)) u_nsec -= NANOSECOND; else if (u_nsec < -(NANOSECOND >> 1)) u_nsec += NANOSECOND; pps_fcount += u_nsec; This change introduces a new calculation which is slightly simpler and more straight forward. Name it B. Consider the following sample values with a tcount of 2000000100 and a tc_frequency of 2000000000 (2GHz). For A, the scale is 9223372036. Then scale * tcount is 18446744994337203600 which is larger than UINT64_MAX (= 18446744073709551615). The result is 920627651984 == 18446744994337203600 % UINT64_MAX. Since all operands are unsigned the result is well defined through modulo arithmetic. The result of bintime2timespec(&bt, &ts) is 49. This is equal to the correct result 1000000049 % NANOSECOND. In hardpps(), both conditional statements are not executed and pps_fcount is incremented by 49. For the new calculation B, we have 1000000000 * tcount is 2000000100000000000 which is less than UINT64_MAX. This yields after the division with tc_frequency the correct result of 1000000050 for delta_nsec. In hardpps(), the first conditional statement is executed and pps_fcount is incremented by 50. This shows that both methods yield roughly the same results. However, method B is easier to understand and requires fewer conditional statements. Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/604
-rw-r--r--cpukit/score/src/kern_ntptime.c12
-rw-r--r--cpukit/score/src/kern_tc.c16
2 files changed, 9 insertions, 19 deletions
diff --git a/cpukit/score/src/kern_ntptime.c b/cpukit/score/src/kern_ntptime.c
index 44d56cf59e..c6f70079b3 100644
--- a/cpukit/score/src/kern_ntptime.c
+++ b/cpukit/score/src/kern_ntptime.c
@@ -900,16 +900,10 @@ hardpps(struct timespec *tsp, long delta_nsec)
pps_tf[0].tv_nsec = u_nsec;
/*
- * Compute the difference between the current and previous
- * counter values. If the difference exceeds 0.5 s, assume it
- * has wrapped around, so correct 1.0 s.
+ * Update the frequency accumulator using the difference between the
+ * current and previous PPS event measured directly by the timecounter.
*/
- u_nsec = delta_nsec;
- if (u_nsec > (NANOSECOND >> 1))
- u_nsec -= NANOSECOND;
- else if (u_nsec < -(NANOSECOND >> 1))
- u_nsec += NANOSECOND;
- pps_fcount += u_nsec;
+ pps_fcount += delta_nsec - NANOSECOND;
if (v_nsec > MAXFREQ || v_nsec < -MAXFREQ)
goto out;
time_status &= ~STA_PPSJITTER;
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index 5e43964bf4..0aa0fdd393 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -2161,7 +2161,7 @@ pps_event(struct pps_state *pps, int event)
struct timecounter *captc;
uint64_t capth_scale;
struct bintime bt;
- struct timespec ts, *tsp, *osp;
+ struct timespec *tsp, *osp;
uint32_t tcount, *pcount;
int foff;
pps_seq_t *pseq;
@@ -2265,7 +2265,7 @@ pps_event(struct pps_state *pps, int event)
#ifdef PPS_SYNC
if (fhard) {
- uint64_t scale;
+ uint64_t delta_nsec;
/*
* Feed the NTP PLL/FLL.
@@ -2275,14 +2275,10 @@ pps_event(struct pps_state *pps, int event)
tcount = pps->capcount - pps->ppscount[2];
pps->ppscount[2] = pps->capcount;
tcount &= captc->tc_counter_mask;
- scale = (uint64_t)1 << 63;
- scale /= captc->tc_frequency;
- scale *= 2;
- bt.sec = 0;
- bt.frac = 0;
- bintime_addx(&bt, scale * tcount);
- bintime2timespec(&bt, &ts);
- hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);
+ delta_nsec = 1000000000;
+ delta_nsec *= tcount;
+ delta_nsec /= captc->tc_frequency;
+ hardpps(tsp, (long)delta_nsec);
}
#endif