adjtime(): Improve configuration and math

1) Previously adjustments less than 1 microsecond per tick would be
   completely ignored. Now they are applied over a shorter period at
   a rate of 1 us per tick.

2) Previously CLOCK_ADJTIME_PERIOD was in units of 1/100th of second.
   Change to milliseconds to be more generally useful unit.
   Change setting name to CLOCK_ADJTIME_PERIOD_MS to make the unit change
   easier to notice.

3) Previously CLOCK_ADJTIME_SLEWLIMIT was in percentage.
   Most clock crystals have better accuracy than 1%, so the minimum slew
   rate was excessive. Change to CLOCK_ADJTIME_SLEWLIMIT_PPM with setting
   value in parts per million.

4) No need to use floating point math in clock_adjtime.c.
This commit is contained in:
Petteri Aimonen 2023-09-28 10:52:15 +03:00 committed by Xiang Xiao
parent 76f6d340ee
commit 0611f39cdc
2 changed files with 30 additions and 36 deletions

View File

@ -217,28 +217,24 @@ config CLOCK_ADJTIME
if CLOCK_ADJTIME
config CLOCK_ADJTIME_SLEWLIMIT
config CLOCK_ADJTIME_SLEWLIMIT_PPM
int "Adjtime slew limit"
default 2
range 0 100
default 20000
range 1 1000000
---help---
Set limit of adjtime() clock slewing as parts per million.
In real time systems we do not want the time to adjust too quickly.
CLOCK_ADJTIME_SLEWLIMIT defines how many seconds can time change
during each clock.
For example CLOCK_ADJTIME_SLEWLIMIT=1000 will slow or speed the timer
tick period by at most 0.1 percent of the nominal value.
Note that CLOCK_ADJTIME_SLEWLIMIT is divided by 100 in source code,
therefore CLOCK_ADJTIME_SLEWLIMIT=2 will result in possible 0.02 second
adjustment.
config CLOCK_ADJTIME_PERIOD
config CLOCK_ADJTIME_PERIOD_MS
int "Adjtime period"
default 97
range 0 100
default 970
range 1 3600000
---help---
Define system clock adjustment period. Should be between 0.95 and 0.99.
Note that CLOCK_ADJTIME_PERIOD is divided by 100 in source code,
therefore CLOCK_ADJTIME_PERIOD=97 will result in 0.97.
Define system clock adjustment period in milliseconds.
The adjustment commanded by adjtime() call is applied over this time period.
endif

View File

@ -51,17 +51,6 @@
is enabled!
#endif
/* Set slew limit. In real time systems we don't want the time to adjust
* too quickly. ADJTIME_SLEWLIMIT defines how many seconds can time change
* during each clock.
*/
#define ADJTIME_SLEWLIMIT (CONFIG_CLOCK_ADJTIME_SLEWLIMIT * 0.01)
/* Define system clock adjustment period. */
#define ADJTIME_PERIOD (CONFIG_CLOCK_ADJTIME_PERIOD * 0.01)
/****************************************************************************
* Private Data
****************************************************************************/
@ -158,7 +147,7 @@ int adjtime(FAR const struct timeval *delta, FAR struct timeval *olddelta)
* of cycles over which we want to do the adjustment.
*/
count = (USEC_PER_SEC * ADJTIME_PERIOD) / period_usec;
count = (USEC_PER_MSEC * CONFIG_CLOCK_ADJTIME_PERIOD_MS) / period_usec;
incr = adjust_usec / count;
/* Compute maximum possible period increase and check
@ -166,7 +155,8 @@ int adjtime(FAR const struct timeval *delta, FAR struct timeval *olddelta)
* one.
*/
incr_limit = ADJTIME_SLEWLIMIT * period_usec;
incr_limit = CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM
/ (USEC_PER_SEC / period_usec);
if (incr > incr_limit)
{
/* It does... limit computed increase and increment count. */
@ -175,6 +165,21 @@ int adjtime(FAR const struct timeval *delta, FAR struct timeval *olddelta)
count = adjust_usec / incr;
}
/* If requested adjustment is smaller than 1 microsecond per tick,
* adjust the count instead.
*/
if (adjust_usec == 0)
{
incr = 0;
count = 0;
}
else if (incr == 0)
{
incr = 1;
count = adjust_usec / incr;
}
if (is_negative == 1)
{
/* Positive or negative? */
@ -182,13 +187,6 @@ int adjtime(FAR const struct timeval *delta, FAR struct timeval *olddelta)
incr = -incr;
}
/* Ignore small differences. */
if (incr == 0)
{
count = 0;
}
leave_critical_section(flags);
/* Initialize clock adjustment and get old adjust values. */