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