You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@nuttx.apache.org by Michal Lenc <mi...@seznam.cz> on 2023/03/20 22:20:38 UTC
RTC synchronization with system time
Hello all,
NuttX offers a function clock_synchronize() that synchronizes system clock
with clock from RTC (internal or external). The synchronization is done
during board initialization and I suppose this can also be called from an
application level if required. However I was not able to find any
implementation that would automatically synchronize system time with
(correct) values from RTC if system clock drifts from real time. It seems
the only possible option is to "force" the synchronization by calling the
mentioned clock_synchronize() function periodically from application level.
What is your view on adding some sort of automatic synchronization that
would ensure system clock stays in sync with RTC (or at least error is less
than some value) even when i drifts away from "real time"? Quite simple
solution is to let clock_gettime() to update base time after N reads however
this would add some computation complexity to gettime (I2C communication
delay for external RTC etc.) and I am not sure if we really want this inside
clock_gettime().
Best regards,
Michal Lenc
Re: RTC synchronization with system time
Posted by Gregory Nutt <sp...@gmail.com>.
>>> NuttX offers a function clock_synchronize() that synchronizes system clock with clock from RTC (internal or external). The synchronization is done
>>> during board initialization and I suppose this can also be called from an
>>> application level if required.
>> I think clock_synchronize() is okay for startup initialization, but
>> would be inappropriate at run time. That is because it could cause the
>> current time to apparently jump backward. That could be fatal under
>> certain circumstances as described for adjtime() in
>> https://github.com/apache/nuttx/issues/8858
>>
> I remember once reading about how FreeBSD handles this (I think it was
> FreeBSD; this was a long time ago):
>
> If there is a difference between the system clock and the reference clock,
> the system clock is _not_ assigned the reference clock's time, exactly
> because of the "clock running backwards" problem. Rather, when the clock is
> advanced, the advancement is adjusted by a small amount, so that the system
> clock always runs forwards, never backwards, and over time the system clock
> gradually comes into synchronization with the reference clock.
>
> We probably need something like that to avoid the same problem.
We have adjtime() in sched/clock/clock_timekeeping, but it has quite a
few problems. See https://github.com/apache/nuttx/issues/8858
This is the same API used by both Linux and FreeBSD:
* Linux: https://man7.org/linux/man-pages/man3/adjtime.3.html
* FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=adjtime&sektion=2&n=1
adjtime(), as specified, fixes the problem of time going backward to
modify the rate of the clock, not the time value of the clock. Both
Linux and FreeBSD specify that adjtime() controls the rate of the clock
source. since only the rate is adjusted, the time will not go backward,
only slow down until it is correct.
Greg
Re: RTC synchronization with system time
Posted by Tomek CEDRO <to...@cedro.info>.
On Tue, Mar 21, 2023 at 4:02 AM Nathan Hartman wrote:
> On Mon, Mar 20, 2023 at 10:36 PM Gregory Nutt wrote:
> > > NuttX offers a function clock_synchronize() that synchronizes system
> > clock
> > > with clock from RTC (internal or external). The synchronization is done
> > > during board initialization and I suppose this can also be called from an
> > > application level if required.
> > I think clock_synchronize() is okay for startup initialization, but
> > would be inappropriate at run time. That is because it could cause the
> > current time to apparently jump backward. That could be fatal under
> > certain circumstances as described for adjtime() in
> > https://github.com/apache/nuttx/issues/8858
> >
>
> I remember once reading about how FreeBSD handles this (I think it was
> FreeBSD; this was a long time ago):
>
> If there is a difference between the system clock and the reference clock,
> the system clock is _not_ assigned the reference clock's time, exactly
> because of the "clock running backwards" problem. Rather, when the clock is
> advanced, the advancement is adjusted by a small amount, so that the system
> clock always runs forwards, never backwards, and over time the system clock
> gradually comes into synchronization with the reference clock.
>
> We probably need something like that to avoid the same problem.
Here are some references :-)
https://github.com/freebsd/freebsd-src/blob/master/contrib/ntp/libntp/adjtime.c
https://github.com/freebsd/freebsd-src/blob/master/contrib/ntp/include/ntp_syscall.h
https://github.com/freebsd/freebsd-src/blob/main/sys/kern/kern_time.c
And the man page :-)
https://man.freebsd.org/cgi/man.cgi?query=adjtime&sektion=2&apropos=0&manpath=FreeBSD+13.1-RELEASE+and+Ports
The adjtime() system call makes small adjustments to the system time, as
returned by gettimeofday(2), advancing or retarding it by the
time speci-
fied by the timeval delta. If delta is negative, the clock is slowed
down by incrementing it more slowly than normal until the correction is
complete. If delta is positive, a larger increment than
normal is used.
The skew used to perform the correction is generally a
fraction of one
percent. Thus, the time is always a monotonically
increasing function.
A time correction from an earlier call to adjtime() may not be finished
when adjtime() is called again. If olddelta is not a null pointer, the
structure pointed to will contain, upon return, the number
of microsec-
onds still to be corrected from the earlier call.
This call may be used by time servers that synchronize the
clocks of com-
puters in a local area network. Such time servers would
slow down the
clocks of some machines and speed up the clocks of others to
bring them
to the average network time.
The adjtime() system call is restricted to the super-user.
Hope that helps :-)
--
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info
Re: RTC synchronization with system time
Posted by Nathan Hartman <ha...@gmail.com>.
On Mon, Mar 20, 2023 at 10:36 PM Gregory Nutt <sp...@gmail.com> wrote:
>
> > NuttX offers a function clock_synchronize() that synchronizes system
> clock
> > with clock from RTC (internal or external). The synchronization is done
> > during board initialization and I suppose this can also be called from an
> > application level if required.
> I think clock_synchronize() is okay for startup initialization, but
> would be inappropriate at run time. That is because it could cause the
> current time to apparently jump backward. That could be fatal under
> certain circumstances as described for adjtime() in
> https://github.com/apache/nuttx/issues/8858
>
I remember once reading about how FreeBSD handles this (I think it was
FreeBSD; this was a long time ago):
If there is a difference between the system clock and the reference clock,
the system clock is _not_ assigned the reference clock's time, exactly
because of the "clock running backwards" problem. Rather, when the clock is
advanced, the advancement is adjusted by a small amount, so that the system
clock always runs forwards, never backwards, and over time the system clock
gradually comes into synchronization with the reference clock.
We probably need something like that to avoid the same problem.
Cheers
Nathan
Re: RTC synchronization with system time
Posted by Gregory Nutt <sp...@gmail.com>.
> NuttX offers a function clock_synchronize() that synchronizes system clock
> with clock from RTC (internal or external). The synchronization is done
> during board initialization and I suppose this can also be called from an
> application level if required.
I think clock_synchronize() is okay for startup initialization, but
would be inappropriate at run time. That is because it could cause the
current time to apparently jump backward. That could be fatal under
certain circumstances as described for adjtime() in
https://github.com/apache/nuttx/issues/8858
Re: RTC synchronization with system time
Posted by "David S. Alessio" <da...@gmail.com>.
Hello, Michal,
You might want to take a look at PTP (Precision Time Protocol)
https://en.wikipedia.org/wiki/PTPd <https://en.wikipedia.org/wiki/PTPd>
and PTPd, a BSD-licensed implementation:
https://github.com/ptpd/ptpd <https://github.com/ptpd/ptpd>
PTP is designed to sync the system clock to IEEE 1588 time. This is overkill for what you’ve requested, but you could strip out the 1588 code, and use the shell to interface with the RTC.
Best regards,
-david
> On Mar 20, 2023, at 3:20 PM, Michal Lenc <mi...@seznam.cz> wrote:
>
> Hello all,
>
>
>
> NuttX offers a function clock_synchronize() that synchronizes system clock
> with clock from RTC (internal or external). The synchronization is done
> during board initialization and I suppose this can also be called from an
> application level if required. However I was not able to find any
> implementation that would automatically synchronize system time with
> (correct) values from RTC if system clock drifts from real time. It seems
> the only possible option is to "force" the synchronization by calling the
> mentioned clock_synchronize() function periodically from application level.
>
>
>
>
> What is your view on adding some sort of automatic synchronization that
> would ensure system clock stays in sync with RTC (or at least error is less
> than some value) even when i drifts away from "real time"? Quite simple
> solution is to let clock_gettime() to update base time after N reads however
> this would add some computation complexity to gettime (I2C communication
> delay for external RTC etc.) and I am not sure if we really want this inside
> clock_gettime().
>
>
>
>
> Best regards,
> Michal Lenc
Re: RTC synchronization with system time
Posted by Gregory Nutt <sp...@gmail.com>.
> No, I don't want to do this from application level hence why I am looking
> for an alternative. NuttX also has function clock_resynchronize() that
> should solve the problem with time going backwards but not sure if it has
> ever been tested and used.
There is an RTC timer driver in drivers/timers that you can use to read
to the RTC and receive alarms. That with adjtime() would support a
application level solution.
A problem with clock_synchronization() is that it depends on the
properties of the RTC so you probably could not make a general solution
with it. For example, different RTCs have different time
representations, different resolutions, and different behaviors. Many
have resolution only to 1 second. Some have sub-second resolution.
Different RTCs support different interrupts when events occur like the 1
second increment. Some RTCs support alarms.
Re: RTC synchronization with system time
Posted by Michal Lenc <mi...@seznam.cz>.
> You wouldn't really do this from application level, right?
No, I don't want to do this from application level hence why I am looking
for an alternative. NuttX also has function clock_resynchronize() that
should solve the problem with time going backwards but not sure if it has
ever been tested and used.
Thank you for the link and issue about adjtime(), that seems like a good
alternative and way to go.
Best regards,
Michal Lenc
---------- Původní e-mail ----------
Od: Gregory Nutt <sp...@gmail.com>
Komu: dev@nuttx.apache.org
Datum: 21. 3. 2023 0:20:43
Předmět: Re: RTC synchronization with system time
"You wouldn't really do this from application level, right? There is
currently no POSIX-compatible application interface to do that. But you
could implement a kernel thread that is started in your board
initialization logic that can call clock_synchronize() according to
whatever criteria you need.
I suppose a standard kernel thread could also be implemented in
sched/clock if such a one-size-fits-all solution can be imagined. You
might check out logic in sched/clock for CONFIG_CLOCK_TIMEKEEPING. That
is used primarily for adjusting the time to properly track time from
NTP. Seems to me that that is essentially the same issue: Keeping two
clocks in agreement.
On 3/20/2023 4:20 PM, Michal Lenc wrote:
> Hello all,
>
>
>
> NuttX offers a function clock_synchronize() that synchronizes system clock
> with clock from RTC (internal or external). The synchronization is done
> during board initialization and I suppose this can also be called from an
> application level if required. However I was not able to find any
> implementation that would automatically synchronize system time with
> (correct) values from RTC if system clock drifts from real time. It seems
> the only possible option is to "force" the synchronization by calling the
> mentioned clock_synchronize() function periodically from application
level.
>
>
>
>
> What is your view on adding some sort of automatic synchronization that
> would ensure system clock stays in sync with RTC (or at least error is
less
> than some value) even when i drifts away from "real time"? Quite simple
> solution is to let clock_gettime() to update base time after N reads
however
> this would add some computation complexity to gettime (I2C communication
> delay for external RTC etc.) and I am not sure if we really want this
inside
> clock_gettime().
>
>
>
>
> Best regards,
> Michal Lenc
>
"
Re: RTC synchronization with system time
Posted by Gregory Nutt <sp...@gmail.com>.
> .... adjtime() is not properly configured as an OS interface; it
> would need system call hooks in syscall/ and include/sys in order to
> be usable in all build configurations.
>
I see a few other issues with adjtime() that I documented here:
https://github.com/apache/nuttx/issues/8858
Re: RTC synchronization with system time
Posted by Gregory Nutt <sp...@gmail.com>.
On 3/20/2023 5:15 PM, Gregory Nutt wrote:
> You wouldn't really do this from application level, right? There is
> currently no POSIX-compatible application interface to do that.
There is no /POSIX /interface to do this, but the Linux interface
adjtime() -- see https://man7.org/linux/man-pages/man3/adjtime.3.html --
is implemented in sched/clock/clock_timekeeping.c
https://github.com/apache/nuttx/blob/master/sched/clock/clock_timekeeping.c#L142
Linux application interfaces are acceptiable. adjtime() is not properly
configured as an OS interface; it would need system call hooks in
syscall/ and include/sys in order to be usable in all build configurations.
It is not very sophisticated and could do so much more. Currently it
calculates a clock adjustment that gets added to the system time.
Re: RTC synchronization with system time
Posted by Gregory Nutt <sp...@gmail.com>.
You wouldn't really do this from application level, right? There is
currently no POSIX-compatible application interface to do that. But you
could implement a kernel thread that is started in your board
initialization logic that can call clock_synchronize() according to
whatever criteria you need.
I suppose a standard kernel thread could also be implemented in
sched/clock if such a one-size-fits-all solution can be imagined. You
might check out logic in sched/clock for CONFIG_CLOCK_TIMEKEEPING. That
is used primarily for adjusting the time to properly track time from
NTP. Seems to me that that is essentially the same issue: Keeping two
clocks in agreement.
On 3/20/2023 4:20 PM, Michal Lenc wrote:
> Hello all,
>
>
>
> NuttX offers a function clock_synchronize() that synchronizes system clock
> with clock from RTC (internal or external). The synchronization is done
> during board initialization and I suppose this can also be called from an
> application level if required. However I was not able to find any
> implementation that would automatically synchronize system time with
> (correct) values from RTC if system clock drifts from real time. It seems
> the only possible option is to "force" the synchronization by calling the
> mentioned clock_synchronize() function periodically from application level.
>
>
>
>
> What is your view on adding some sort of automatic synchronization that
> would ensure system clock stays in sync with RTC (or at least error is less
> than some value) even when i drifts away from "real time"? Quite simple
> solution is to let clock_gettime() to update base time after N reads however
> this would add some computation complexity to gettime (I2C communication
> delay for external RTC etc.) and I am not sure if we really want this inside
> clock_gettime().
>
>
>
>
> Best regards,
> Michal Lenc
>
Re: RTC synchronization with system time
Posted by Gregory Nutt <sp...@gmail.com>.
> What is your view on adding some sort of automatic synchronization that
> would ensure system clock stays in sync with RTC (or at least error is less
> than some value) even when i drifts away from "real time"? Quite simple
> solution is to let clock_gettime() to update base time after N reads however
> this would add some computation complexity to gettime (I2C communication
> delay for external RTC etc.) and I am not sure if we really want this inside
> clock_gettime().
>
I didn't respond to this.
I don't know if a system solution makes sense. This is a user function
that is supported by all common OS via adjtime(). We should implement
the solution in the same way that other systems do.
I suspect that the properties of RTCs are too variable and that any
solution has to be hardware specific, at least in some aspects.
clock_synchronize() or clock_resynchronize() are totally inappropriate
for this and would clearly break system timing. But adjtime() as
specified (but not as currently implemented ) would be a very good
solution to do this and is already exposed to applications. See
https://github.com/apache/nuttx/issues/8858
Waiting for N reads is arbitrary. It would be better to get an event
from the RTC, like when the second timer rolls over or an alarm
expires. An application should be able to get that from
drivers/timer/rtc.c. Sampling an RTC asynchronous does not give you
good times due to the limited resolution of most RTC time. But sampling
the RTC at well known points in time (like incrementing the second)
would be synchronous and accurate.
I'm sure the solution does not belong in clock_gettime(). That would be
mixing functionality and not in the spirit of good modular design. And
would not support the most common use case for adjtime():
The most common way of adjusting time via adjtime() is as part of the
use of NTP (I see PTP also uses adjtime). Certainly any system solution
cannot prohibit that most common use of adjtime(). Certainly
clock_gettime() cannot get involved with NTP which is an application
space protocol.
There are lots of examples of adjtime implementations. And examples of
NTP clients on the internet using adjtime().
https://github.com/openntpd-portable/openntpd-portable,
https://github.com/ntp-project/ntp.
Here is an NTP adjtime() call:
https://github.com/ntp-project/ntp/blob/master-no-authorname/ntpdate/ntpdate.c#L2039