Example #1
0
void
RTC_Initialise(int initial_set)
{
  char *file_name;

  /* Do an initial read of the RTC and set the system time to it.  This
     is analogous to what /sbin/hwclock -s would do on Linux.  If that fails
     or RTC is not supported, set the clock to the time of the last
     modification of driftfile, so we at least get closer to the truth. */
  if (initial_set) {
    if (!driver.time_pre_init || !driver.time_pre_init()) {
      fallback_time_init();
    }
  }

  driver_initialised = 0;

  /* This is how we tell whether the user wants to load the RTC
     driver, if he is on a machine where it is an option. */
  file_name = CNF_GetRtcFile();

  if (file_name) {
    if (CNF_GetRtcSync()) {
      LOG_FATAL(LOGF_Rtc, "rtcfile directive cannot be used with rtcsync");
    }

    if (driver.init) {
      if ((driver.init)()) {
        driver_initialised = 1;
      }
    } else {
      LOG(LOGS_ERR, LOGF_Rtc, "RTC not supported on this operating system");
    }
  }
}
Example #2
0
int
RTC_Linux_Initialise(void)
{
  rtc_sec = MallocArray(time_t, MAX_SAMPLES);
  rtc_trim = MallocArray(double, MAX_SAMPLES);
  system_times = MallocArray(struct timeval, MAX_SAMPLES);

  /* Setup details depending on configuration options */
  setup_config();

  /* In case it didn't get done by pre-init */
  coefs_file_name = CNF_GetRtcFile();

  /* Try to open device */

  fd = open (CNF_GetRtcDevice(), O_RDWR);
  if (fd < 0) {
    LOG(LOGS_ERR, LOGF_RtcLinux, "Could not open RTC device %s : %s",
        CNF_GetRtcDevice(), strerror(errno));
    return 0;
  }

  /* Close on exec */
  UTI_FdSetCloexec(fd);

  n_samples = 0;
  n_samples_since_regression = 0;
  n_runs = 0;
  coefs_valid = 0;

  measurement_period = LOWEST_MEASUREMENT_PERIOD;

  operating_mode = OM_NORMAL;

  /* Register file handler */
  SCH_AddInputFileHandler(fd, read_from_device, NULL);

  /* Register slew handler */
  LCL_AddParameterChangeHandler(slew_samples, NULL);

  logfileid = CNF_GetLogRtc() ? LOG_FileOpen("rtc",
      "   Date (UTC) Time   RTC fast (s) Val   Est fast (s)   Slope (ppm)  Ns  Nr Meas")
    : -1;
  return 1;
}
Example #3
0
int
RTC_Linux_TimePreInit(time_t driftfile_time)
{
  int fd, status;
  struct rtc_time rtc_raw, rtc_raw_retry;
  struct tm rtc_tm;
  time_t rtc_t;
  double accumulated_error, sys_offset;
  struct timeval new_sys_time, old_sys_time;

  coefs_file_name = CNF_GetRtcFile();

  setup_config();
  read_coefs_from_file();

  fd = open(CNF_GetRtcDevice(), O_RDONLY);

  if (fd < 0) {
    return 0; /* Can't open it, and won't be able to later */
  }

  /* Retry reading the rtc until both read attempts give the same sec value.
     This way the race condition is prevented that the RTC has updated itself
     during the first read operation. */
  do {
    status = ioctl(fd, RTC_RD_TIME, &rtc_raw);
    if (status >= 0) {
      status = ioctl(fd, RTC_RD_TIME, &rtc_raw_retry);
    }
  } while (status >= 0 && rtc_raw.tm_sec != rtc_raw_retry.tm_sec);

  /* Read system clock */
  LCL_ReadCookedTime(&old_sys_time, NULL);

  close(fd);

  if (status >= 0) {
    /* Convert to seconds since 1970 */
    rtc_tm.tm_sec = rtc_raw.tm_sec;
    rtc_tm.tm_min = rtc_raw.tm_min;
    rtc_tm.tm_hour = rtc_raw.tm_hour;
    rtc_tm.tm_mday = rtc_raw.tm_mday;
    rtc_tm.tm_mon = rtc_raw.tm_mon;
    rtc_tm.tm_year = rtc_raw.tm_year;
    
    rtc_t = t_from_rtc(&rtc_tm);

    if (rtc_t != (time_t)(-1)) {

      /* Work out approximatation to correct time (to about the
         nearest second) */
      if (valid_coefs_from_file) {
        accumulated_error = file_ref_offset +
          (rtc_t - file_ref_time) * 1.0e-6 * file_rate_ppm;
      } else {
        accumulated_error = 0.0;
      }

      /* Correct time */

      new_sys_time.tv_sec = rtc_t;
      /* Average error in the RTC reading */
      new_sys_time.tv_usec = 500000;

      UTI_AddDoubleToTimeval(&new_sys_time, -accumulated_error, &new_sys_time);

      if (new_sys_time.tv_sec < driftfile_time) {
        LOG(LOGS_WARN, LOGF_RtcLinux, "RTC time before last driftfile modification (ignored)");
        return 0;
      }

      UTI_DiffTimevalsToDouble(&sys_offset, &old_sys_time, &new_sys_time);

      /* Set system time only if the step is larger than 1 second */
      if (fabs(sys_offset) >= 1.0) {
        if (LCL_ApplyStepOffset(sys_offset))
          LOG(LOGS_INFO, LOGF_RtcLinux, "System time set from RTC");
      }
    } else {
      return 0;
    }
  } else {
    return 0;
  }

  return 1;
}
Example #4
0
void
RTC_Linux_TimePreInit(void)
{
  int fd, status;
  struct rtc_time rtc_raw;
  struct tm rtc_tm;
  time_t rtc_t, estimated_correct_rtc_t;
  long interval;
  double accumulated_error = 0.0;
  struct timeval new_sys_time, old_sys_time;

  coefs_file_name = CNF_GetRtcFile();

  setup_config();
  read_coefs_from_file();

  fd = open(CNF_GetRtcDevice(), O_RDONLY);

  if (fd < 0) {
    return; /* Can't open it, and won't be able to later */
  }

  status = ioctl(fd, RTC_RD_TIME, &rtc_raw);

  if (status >= 0) {
    /* Convert to seconds since 1970 */
    rtc_tm.tm_sec = rtc_raw.tm_sec;
    rtc_tm.tm_min = rtc_raw.tm_min;
    rtc_tm.tm_hour = rtc_raw.tm_hour;
    rtc_tm.tm_mday = rtc_raw.tm_mday;
    rtc_tm.tm_mon = rtc_raw.tm_mon;
    rtc_tm.tm_year = rtc_raw.tm_year;
    
    rtc_t = t_from_rtc(&rtc_tm);

    if (rtc_t != (time_t)(-1)) {

      /* Work out approximatation to correct time (to about the
         nearest second) */
      if (valid_coefs_from_file) {
        interval = rtc_t - file_ref_time;
        accumulated_error = file_ref_offset + (double)(interval) * 1.0e-6 * file_rate_ppm;

        /* Correct time */
        estimated_correct_rtc_t = rtc_t - (long)(0.5 + accumulated_error);
      } else {
        estimated_correct_rtc_t = rtc_t - (long)(0.5 + accumulated_error);
      }

      new_sys_time.tv_sec = estimated_correct_rtc_t;
      new_sys_time.tv_usec = 0;

      /* Set system time only if the step is larger than 1 second */
      if (!(gettimeofday(&old_sys_time, NULL) < 0) &&
          (old_sys_time.tv_sec - new_sys_time.tv_sec > 1 ||
           old_sys_time.tv_sec - new_sys_time.tv_sec < -1)) {

        LOG(LOGS_INFO, LOGF_RtcLinux, "Set system time, error in RTC = %f",
            accumulated_error);

        /* Tough luck if this fails */
        if (settimeofday(&new_sys_time, NULL) < 0) {
          LOG(LOGS_WARN, LOGF_RtcLinux, "Could not settimeofday");
        }
      }
    } else {
      LOG(LOGS_WARN, LOGF_RtcLinux, "Could not convert RTC reading to seconds since 1/1/1970");
    }
  }

  close(fd);
}