TOD vs noninteger ticks per second

Aaron J. Grier aaron at frye.com
Mon May 20 19:06:03 UTC 2002


attached is a patch for 4.5.0 that keeps a microsecond "slop count" for
the TOD, and pulls second scheduling forward or backward accordingly.
obviously if you have a nice power-of-ten scheduling tick, this is
unnecessary, but due to some hardware constraints, my tick length is
9.984ms instead of 10ms, and I figured the system should keep accurate
time without resorting to reading the hardware RTC and resetting the TOD
clock from that.

I just whipped this up in a few hours.  I doubt it's up to OAR
programming specs, and the implementation could be more elegant, but it
illustrates the idea.  it adds a tiny bit of overhead, and is only
tested for my case of 9.984ms, but I figured I'd throw it out to see if
anyone else might be interested.

and if something similar has already been implemented in the -snapshot
branch, feel free to smack me with a fish.  :)

-- 
  Aaron J. Grier  |   Frye Electronics, Tigard, OR   |  aaron at frye.com
-------------- next part --------------
Index: 0.31/c/src/exec/score/macros/rtems/score/tod.inl
--- 0.31/c/src/exec/score/macros/rtems/score/tod.inl Fri, 29 Sep 2000 20:11:24 -0700 kaben (rtems/L/b/27_tod.inl 1.1 664)
+++ 0.31(w)/c/src/exec/score/macros/rtems/score/tod.inl Mon, 20 May 2002 10:29:41 -0700 aaron (rtems/L/b/27_tod.inl 1.1 664)
@@ -24,7 +24,8 @@
 
 #define _TOD_Tickle_ticks() \
   _TOD_Current.ticks++; \
-  _Watchdog_Ticks_since_boot++
+  _Watchdog_Ticks_since_boot++; \
+  _TOD_Cumulative_slop += _TOD_Slop_per_tick;
 
 /*PAGE
  *
Index: 0.31/c/src/exec/score/inline/rtems/score/tod.inl
--- 0.31/c/src/exec/score/inline/rtems/score/tod.inl Fri, 29 Sep 2000 20:11:24 -0700 kaben (rtems/M/b/3_tod.inl 1.1 664)
+++ 0.31(w)/c/src/exec/score/inline/rtems/score/tod.inl Mon, 20 May 2002 10:09:11 -0700 aaron (rtems/M/b/3_tod.inl 1.1 664)
@@ -30,6 +30,7 @@
 {
   _TOD_Current.ticks += 1;
   _Watchdog_Ticks_since_boot += 1;
+  _TOD_Cumulative_slop += _TOD_Slop_per_tick;
 }
 
 /*PAGE
Index: 0.31/c/src/exec/score/include/rtems/score/tod.h
--- 0.31/c/src/exec/score/include/rtems/score/tod.h Fri, 29 Sep 2000 20:11:24 -0700 kaben (rtems/M/b/32_tod.h 1.1 664)
+++ 0.31(w)/c/src/exec/score/include/rtems/score/tod.h Mon, 20 May 2002 10:07:46 -0700 aaron (rtems/M/b/32_tod.h 1.1 664)
@@ -101,9 +101,15 @@
  *  per clock tick, this value will contain only the integer portion
  *  of the division.  This means that the interval between clock ticks
  *  can be a source of error in the current time of day.
+ *
+ *  To help alleviate this problem, we keep a running error (in
+ *  microseconds) and adjust the scheduling of the seconds watchdog
+ *  accordingly.
  */
 
 SCORE_EXTERN unsigned32 _TOD_Ticks_per_second;
+SCORE_EXTERN signed32 _TOD_Slop_per_tick;
+SCORE_EXTERN signed32 _TOD_Cumulative_slop;
 
 /*
  *  This is the control structure for the watchdog timer which
Index: 0.31/c/src/exec/score/src/coretodtickle.c
--- 0.31/c/src/exec/score/src/coretodtickle.c Fri, 29 Sep 2000 20:11:24 -0700 kaben (rtems/O/b/36_coretodtic 1.1 664)
+++ 0.31(w)/c/src/exec/score/src/coretodtickle.c Mon, 20 May 2002 10:19:27 -0700 aaron (rtems/O/b/36_coretodtic 1.1 664)
@@ -62,6 +62,31 @@
     }
   }
 
+  /* tickle the seconds timer */
   _Watchdog_Tickle_seconds();
-  _Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second );
+
+  /* prepare to schedule the next tick */
+  if (_TOD_Slop_per_tick == 0)
+    _Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second );
+  else if (_TOD_Slop_per_tick > 0) { /* running fast */
+    if (_TOD_Cumulative_slop > _TOD_Microseconds_per_tick) {
+      _TOD_Cumulative_slop%=_TOD_Microseconds_per_tick;
+      _Watchdog_Insert_ticks(
+         &_TOD_Seconds_watchdog, _TOD_Ticks_per_second + 1
+      );
+    } else _Watchdog_Insert_ticks(
+       &_TOD_Seconds_watchdog, _TOD_Ticks_per_second
+      );
+  } else { /* running slow */
+    if (_TOD_Cumulative_slop < (-1 * _TOD_Microseconds_per_tick)) {
+      /* C doesn't really do modular arithmetic, so we fake it */
+      _TOD_Cumulative_slop%=_TOD_Microseconds_per_tick;
+      _TOD_Cumulative_slop+=_TOD_Microseconds_per_tick;
+      _Watchdog_Insert_ticks(
+         &_TOD_Seconds_watchdog, _TOD_Ticks_per_second - 1
+      );
+    } else _Watchdog_Insert_ticks(
+       &_TOD_Seconds_watchdog, _TOD_Ticks_per_second
+      );
+  }
 }
Index: 0.31/c/src/exec/score/src/coretod.c
--- 0.31/c/src/exec/score/src/coretod.c Fri, 29 Sep 2000 20:11:24 -0700 kaben (rtems/O/b/38_coretod.c 1.1 664)
+++ 0.31(w)/c/src/exec/score/src/coretod.c Mon, 20 May 2002 10:12:53 -0700 aaron (rtems/O/b/38_coretod.c 1.1 664)
@@ -48,9 +48,14 @@
 
   if ( microseconds_per_tick == 0 )
     _TOD_Ticks_per_second = 0;
-  else
+  else {
     _TOD_Ticks_per_second =
        TOD_MICROSECONDS_PER_SECOND / microseconds_per_tick;
+    _TOD_Slop_per_tick =
+       TOD_MICROSECONDS_PER_SECOND / _TOD_Ticks_per_second
+       - microseconds_per_tick;
+    _TOD_Cumulative_slop = 0;
+  }
 
   _Watchdog_Initialize( &_TOD_Seconds_watchdog, _TOD_Tickle, 0, NULL );
 


More information about the users mailing list