how to synchronize the system clock

ChibiOS public support forum for all topics not covered by a specific support forum.

Moderators: RoccoMarco, lbednarz, utzig, tfAteba, barthess

sntnjrg
Posts: 65
Joined: Mon Jul 22, 2019 2:19 pm
Has thanked: 18 times
Been thanked: 3 times

how to synchronize the system clock

Postby sntnjrg » Thu Jul 02, 2020 9:00 am

Hi,

I am studying how to synchronize the system clock from the date and time of a GNSS receiver.

RTC is synchronized it using this function from the IRQ:

Code: Select all

/**
 * @brief   Set current time.
 * @note    This function can be called from any context but limitations
 *          could be imposed by the low level implementation. It is
 *          guaranteed that the function can be called from thread
 *          context.
 * @note    The function can be reentrant or not reentrant depending on
 *          the low level implementation.
 *
 * @param[in] rtcp      pointer to RTC driver structure
 * @param[in] timespec  pointer to a @p RTCDateTime structure
 *
 * @special
 */
void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec)


The system clock is based on ticks. I'm a newbie. How can I synchronize it or estimate the correction factor to be applied to it?

Thanks you.

User avatar
Giovanni
Site Admin
Posts: 14461
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: how to synchronize the system clock

Postby Giovanni » Thu Jul 02, 2020 10:01 am

Hi,

Note that RTC and system clock are two separate things, system clock cannot be modified, it is meant to be a monotonic counter. What you may adjust is the RTC using that function you mentioned (better do that from a thread, not an ISR).

Giovanni

sntnjrg
Posts: 65
Joined: Mon Jul 22, 2019 2:19 pm
Has thanked: 18 times
Been thanked: 3 times

Re: how to synchronize the system clock

Postby sntnjrg » Thu Jul 02, 2020 2:30 pm

Hi Giovanni

If I use shared variables, to atomically access those variables:

- I use chSysLockFromISR()/chSysUnlockFromISR() in ISR.
- I use chSysLock()/chSysUnlock()) in thread.

Is that right?

I'm trying to calculate the factor based on the system clock ticks. In the GNSS receiver, I use the PPS signal output. This signal is generated every second. I define the following callback:

Code: Select all

static volatile system_t tp;
static volatile float Tp;

static void pps_cb(void *arg) {
  (void)arg;

  chSysLockFromISR();

  // --------------------------------------------------------------------------
  // Calculate the previous
  // --------------------------------------------------------------------------
  tp = chVTGetSystemTimeX();

  struct tm timp;
  RTCDateTime rtc_dateTime;
  uint32_t tv_msec;
  rtcGetTime(&RTCD1, &rtc_dateTime);
  rtcConvertDateTimeToStructTm(&rtc_dateTime, &timp, &tv_msec);
  Tp = static_cast<float>(mktime(&timp)) + (static_cast<float>(tv_msec) / 1000);

  chSysUnlockFromISR();
} // pps_cb


In the thread, I calculate the current time provided by the GNSS receiver, update the system clock and try to calculate the correction based on the current ticks:

T' = Tc + ((current_ticks - tc) * ((Tc-Tp)/(tc-tp)));

where:
Tc = timestamp in seconds when RTC was updated
tc = ticks when RTC was updated.

I have observed that Tc and Tp are always of the same value.

Could it be that I'm not atomically reading the values?

Thanks you.

steved
Posts: 825
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 135 times

Re: how to synchronize the system clock

Postby steved » Thu Jul 02, 2020 6:25 pm

Firstly, it appears you haven't registered Giovanni's point that the system clock and the RTC are two different things, and that you cannot adjust the system clock (it's derived from the CPU crystal, if any, and I'm pretty certain there's no method to fine tune the frequency).

So you can only adjust the RTC; it has an internal calibration register. And dependent on the device, the RTC often has a resolution of 1 second, although it may be possible to access a higher frequency internally.
The PPS tick is making life rather difficult for you, when compared with a time server which actually gives time of day; in the simplest system you could just update the RTC with the time.
So what you probably need to do is count input pulses over an extended period, compare it with the elapsed time according to the RTC over that period, then both update the current time on the RTC, and adjust the calibration register to slow down or speed up the RTC. The measurement period will need to be long enough to give a meaningful time difference - thousands of seconds, I would think.

The system clock should be a pretty stable frequency, so you could use it to measure the pulse input and the RTC timing.

User avatar
Giovanni
Site Admin
Posts: 14461
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: how to synchronize the system clock

Postby Giovanni » Thu Jul 02, 2020 7:53 pm

sntnjrg wrote:Hi Giovanni

If I use shared variables, to atomically access those variables:

- I use chSysLockFromISR()/chSysUnlockFromISR() in ISR.
- I use chSysLock()/chSysUnlock()) in thread.

Is that right?


This is correct however note that from a critical section you can only call those functions with names terminated with X, I or S, this is an important point, see "function classes" in the documentation or in the book. rtcGetTime() is a special case and is allowed but it is not guaranteed to be allowed in any possible implementation, there is a note in the function docs.

In chconf.h you can enable assertions and the "state checker" it will catch invalid function calls and find a lot of possible problems.

Giovanni


Return to “General Support”

Who is online

Users browsing this forum: No registered users and 6 guests