xref: /freebsd/contrib/ntp/html/howto.html (revision 416ba5c74546f32a993436a99516d35008e9f384)
19c2daa00SOllivier Robert<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
29c2daa00SOllivier Robert<html>
39c2daa00SOllivier Robert<head>
4ea906c41SOllivier Robert<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
59c2daa00SOllivier Robert<meta name="generator" content="HTML Tidy, see www.w3.org">
69c2daa00SOllivier Robert<title>How to Write a Reference Clock Driver</title>
79c2daa00SOllivier Robert<link href="scripts/style.css" type="text/css" rel="stylesheet">
89c2daa00SOllivier Robert</head>
99c2daa00SOllivier Robert<body>
109c2daa00SOllivier Robert<h3>How to Write a Reference Clock Driver</h3>
11ea906c41SOllivier Robert<img src="pic/pogo4.gif" alt="gif" align="left"><a href="http://www.eecis.udel.edu/%7emills/pictures.html">from <i>Pogo</i>, Walt Kelly</a>
129c2daa00SOllivier Robert<p>You need a little magic.</p>
13*2b15cb3dSCy Schubert<p>Last update:
14*2b15cb3dSCy Schubert  <!-- #BeginDate format:En2m -->10-Mar-2014  05:08<!-- #EndDate -->
15*2b15cb3dSCy Schubert    UTC</p>
169c2daa00SOllivier Robert<br clear="left">
179c2daa00SOllivier Robert<h4>Related Links</h4>
18*2b15cb3dSCy Schubert<script type="text/javascript" language="javascript" src="scripts/misc.txt"></script>
199c2daa00SOllivier Robert<h4>Table of Contents</h4>
209c2daa00SOllivier Robert<ul>
21*2b15cb3dSCy Schubert  <li class="inline"><a href="#desc">Description</a></li>
22*2b15cb3dSCy Schubert  <li class="inline"><a href="#file">Files Which Need to be Changed</a></li>
23*2b15cb3dSCy Schubert  <li class="inline"><a href="#intf">Interface Routine Overview</a></li>
24*2b15cb3dSCy Schubert  <li class="inline"><a href="#pps">Pulse-per-Second Interface</a></li>
259c2daa00SOllivier Robert</ul>
269c2daa00SOllivier Robert<hr>
279c2daa00SOllivier Robert<h4 id="desc">Description</h4>
28*2b15cb3dSCy Schubert<p>NTP reference clock support maintains the fiction that the clock is actually an ordinary server in the NTP tradition, but operating at a synthetic stratum of zero. The entire suite of algorithms filter the received data and select the best sources to correct the system clock. No packets are exchanged with a reference clock; however, the transmit, receive and packet procedures are replaced with code to simulate them.</p>
29*2b15cb3dSCy Schubert<p>The driver assumes three timescales: standard time maintained by a distant laboratory such as USNO or NIST, reference time maintained by the external radio and the system time maintained by NTP. The radio synchronizes reference time via radio, satellite or modem. As the transmission means may not always be reliable, most radios continue to provide clock updates for some time after signal loss using an internal reference oscillator. In such cases the radio may or may not reveal the time since last synchronized or the estimated time error.</p>
30*2b15cb3dSCy Schubert<p>All three timescales run only in Coordinated Universal Time (UTC) and are not adjusted for local timezone or standard/daylight time. The local timezone, standard/daylight indicator and year, if provided, are ignored. However, it is important to determine whether a leap second is to be inserted in the UTC timescale in the near future so NTP can insert it in the system timescale at the appropriate epoch.</p>
31*2b15cb3dSCy Schubert<p>The interface routines in the <tt>ntp_refclock.c</tt> source file call the following driver routines via a transfer vector:</p>
329c2daa00SOllivier Robert<dl>
33*2b15cb3dSCy Schubert  <dt><tt>startup</tt></dt>
34*2b15cb3dSCy Schubert  <dd>The association has just been mobilized. The driver may allocate a private structure and open the device(s) required.</dd>
35*2b15cb3dSCy Schubert  <dt><tt>shutdown</tt></dt>
36*2b15cb3dSCy Schubert  <dd>The association is about to be demobilized. The driver should close all device(s) and free private structures.</dd>
37*2b15cb3dSCy Schubert  <dt><tt>receive</tt></dt>
38*2b15cb3dSCy Schubert  <dd>A timecode string is ready for retrieval using the <tt>refclock_gtlin()</tt> or <tt>refclock_gtraw()</tt> routines and provide clock updates.</dd>
39*2b15cb3dSCy Schubert  <dt><tt>poll</tt></dt>
40*2b15cb3dSCy Schubert  <dd>Called at poll timeout, by default 64 s. Ordinarily, the driver will send a poll sequence to the radio as required.</dd>
41*2b15cb3dSCy Schubert  <dt><tt>timer</tt></dt>
42*2b15cb3dSCy Schubert  <dd>Called once per second. This can be used for housekeeping functions. In the case with pulse-per-second (PPS) signals, this can be used to process the signals and provide clock updates.</dd>
43*2b15cb3dSCy Schubert</dl>
44*2b15cb3dSCy Schubert<p>The receive routine retrieves a timecode string via serial or parallel port, PPS signal or other means. It decodes the timecode in days, hours, minutes, seconds and nanoseconds and checks for errors. It provides these data along with the on-time timestamp to the <tt>refclock_process</tt> routine, which saves the computed offset in a 60-sample circular buffer. On occasion, either by timeout, sample count or call to the poll routine, the driver calls <tt>refclock_receive</tt> to process the circular buffer samples and update the system clock.</p>
45*2b15cb3dSCy Schubert<p>The best way to understand how the clock drivers work is to study one of the drivers already implemented, such as <tt>refclock_wwvb.c</tt>. The main interface is the <tt>refclockproc</tt> structure, which contains for most drivers the decoded timecode, on-time timestamp, reference timestamp, exception reports and statistics tallies, etc. The support routines are passed a pointer to the <tt>peer</tt> structure, which contains a pointer to the <tt>refclockproc</tt> structure, which in turn contains a pointer to the unit structure, if used. For legacy purposes, a table <tt>typeunit[type][unit]</tt> contains the peer structure pointer for each configured clock type and unit. This structure should not be used for new implementations.</p>
46*2b15cb3dSCy Schubert<p>Radio and modem reference clocks by convention have addresses of the form <tt>127.127.<i>t</i>.<i>u</i></tt>, where <i>t</i> is the clock type and <i>u</i> in the range 0-3 is used to distinguish multiple instances of clocks of the same type. Most clocks require a serial or parallel port or special bus peripheral. The particular device is normally specified by adding a soft link <tt>/dev/device<i>u</i></tt> to the particular hardware device.</p>
47*2b15cb3dSCy Schubert<p>By convention, reference clock drivers are named in the form <tt>refclock_<i>xxxx</i>.c</tt>, where <tt><i>xxxx</i></tt> is a unique string. Each driver is assigned a unique type number, long-form driver name, short-form driver name and device name. The existing assignments are in the <a href="refclock.html">Reference Clock Drivers</a> page and its dependencies. All drivers supported by the particular hardware and operating system are automatically detected in the autoconfigure phase and conditionally compiled.</p>
48*2b15cb3dSCy Schubert<h4>Conventions, Fudge Factors and Flags</h4>
49*2b15cb3dSCy Schubert<p>Most drivers support manual or automatic calibration for systematic offset bias using values encoded in the <tt>fudge</tt> configuration command. By convention, the <tt>time1</tt> value defines the calibration offset in seconds. For those drivers that support statistics collection using the <tt>filegen</tt> utility and the <tt>clockstats</tt> file, the <tt>flag4</tt> switch enables the utility.</p>
50*2b15cb3dSCy Schubert<p>If the calibration feature has been enabled, the <tt>flag1</tt> switch is set and the PPS signal is actively disciplining the system time, the <tt>time1</tt> value is automatically adjusted to maintain a residual offset of zero. Once the its value has stabilized, the value can be inserted in the configuration file and the calibration feature disabled.</p>
51*2b15cb3dSCy Schubert<h4 id="file">Files Which Need to be Changed</h4>
52*2b15cb3dSCy Schubert<p>When a new reference clock driver is installed, the following files need to be edited. Note that changes are also necessary to properly integrate the driver in the configuration and makefile scripts, but these are decidedly beyond the scope of this page.</p>
53*2b15cb3dSCy Schubert<dl>
54*2b15cb3dSCy Schubert  <dt><tt>./include/ntp.h</tt></dt>
55*2b15cb3dSCy Schubert  <dd>The reference clock type defines are used in many places. Each driver is assigned a unique type number. Unused numbers are clearly marked in the list. A unique <tt>REFCLK_<i>xxxx</i></tt> identification code should be recorded in the list opposite its assigned type number.</dd>
56*2b15cb3dSCy Schubert  <dt><tt>./libntp/clocktypes.c</tt></dt>
57*2b15cb3dSCy Schubert  <dd>The <tt>./libntp/clktype</tt> array is used by certain display functions. A unique short-form name of the driver should be entered together with its assigned identification code.</dd>
58*2b15cb3dSCy Schubert  <dt><tt>./ntpd/ntp_control.c</tt></dt>
59*2b15cb3dSCy Schubert  <dd>The <tt>clocktypes</tt> array is used for certain control message displays functions. It should be initialized with the reference clock class assigned to the driver, as per the NTP specification RFC-1305. See the <tt>./include/ntp_control.h</tt> header file for the assigned classes.</dd>
60*2b15cb3dSCy Schubert  <dt><tt>./ntpd/refclock_conf.c</tt></dt>
61*2b15cb3dSCy Schubert  <dd>This file contains a list of external structure definitions which are conditionally defined. A new set of entries should be installed similar to those already in the table. The <tt>refclock_conf</tt> array is a set of pointers to transfer vectors in the individual drivers. The external name of the transfer vector should be initialized in correspondence with the type number.</dd>
629c2daa00SOllivier Robert</dl>
639c2daa00SOllivier Robert<h4 id="intf">Interface Routine Overview</h4>
649c2daa00SOllivier Robert<dl>
65*2b15cb3dSCy Schubert  <dt><tt>refclock_newpeer</tt> - initialize and start a reference clock.</dt>
66*2b15cb3dSCy Schubert  <dd>This routine allocates and initializes the interface structure which supports a reference clock in the form of an ordinary NTP peer. A driver-specific support routine completes the initialization, if used. Default peer variables which identify the clock and establish its reference ID and stratum are set here. It returns one if success and zero if the clock address is invalid or already running, insufficient resources are available or the driver declares a bum rap.</dd>
67*2b15cb3dSCy Schubert  <dt><tt>refclock_unpeer</tt> - shut down a clock</dt>
68*2b15cb3dSCy Schubert  <dd>This routine is used to shut down a clock and return its resources to the system.</dd>
69*2b15cb3dSCy Schubert  <dt><tt>refclock_transmit</tt> - simulate the transmit procedure</dt>
70*2b15cb3dSCy Schubert  <dd>This routine implements the NTP transmit procedure for a reference clock. This provides a mechanism to call the driver at the NTP poll interval, as well as provides a reachability mechanism to detect a broken radio or other madness.</dd>
71*2b15cb3dSCy Schubert  <dt><tt>refclock_process</tt> - insert a sample in the circular buffer</dt>
72*2b15cb3dSCy Schubert  <dd>This routine saves the offset computed from the on-time timestamp and the days, hours, minutes, seconds and nanoseconds in the circular buffer. Note that no provision is included for the year, as provided by some (but not all) radio clocks. Ordinarily, the year is implicit in the Unix file system and hardware/software clock support, so this is ordinarily not a problem.</dd>
73*2b15cb3dSCy Schubert  <dt><tt>refclock_receive</tt> - simulate the receive and packet procedures</dt>
74*2b15cb3dSCy Schubert  <dd>This routine simulates the NTP receive and packet procedures for a reference clock. This provides a mechanism in which the ordinary NTP filter, selection and combining algorithms can be used to suppress misbehaving radios and to mitigate between them when more than one is available for backup.</dd>
75*2b15cb3dSCy Schubert  <dt><tt>refclock_gtraw</tt>, <tt>refclock_gtlin</tt> - read the buffer and on-time timestamp</dt>
76*2b15cb3dSCy Schubert  <dd>These routines return the data received from the clock and the on-time timestamp. The <tt>refclock_gtraw</tt> routine returns a batch of one or more characters returned by the Unix terminal routines in raw mode. The <tt>refclock_gtlin</tt> routine removes the parity bit and control characters and returns all the characters up to and including the line terminator. Either routine returns the number of characters delivered.</dd>
77*2b15cb3dSCy Schubert  <dt><tt>refclock_open</tt> - open a serial port for reference clock</dt>
78*2b15cb3dSCy Schubert  <dd>This routine opens a serial port for I/O and sets default options. It returns the file descriptor if success and zero if failure.</dd>
79*2b15cb3dSCy Schubert  <dt><tt>refclock_ioctl</tt> - set serial port control functions</dt>
80*2b15cb3dSCy Schubert  <dd>This routine attempts to hide the internal, system-specific details of serial ports. It can handle POSIX (<tt>termios</tt>), SYSV (<tt>termio</tt>) and BSD (<tt>sgtty</tt>) interfaces with varying degrees of success. The routine returns one if success and zero if failure.</dd>
81*2b15cb3dSCy Schubert  <dt><tt>refclock_ppsapi</tt></dt>
82*2b15cb3dSCy Schubert  <dd>This routine initializes the Pulse-per-Second interface (see below).</dd>
83*2b15cb3dSCy Schubert  <dt><tt>refclock_pps</tt></dt>
84*2b15cb3dSCy Schubert  <dd>This routine is called once per second to read the latest PPS offset and save it in the circular buffer (see below).</dd>
859c2daa00SOllivier Robert</dl>
86*2b15cb3dSCy Schubert<h4 id="pps">Pulse-per-Second Interface</h4>
87*2b15cb3dSCy Schubert<p>When the Pulse-per-Second Application Interface (RFC 2783) is present, a
88*2b15cb3dSCy Schubert  compact PPS interface is available to all drivers. See the <a href="prefer.html">Mitigation
89*2b15cb3dSCy Schubert  Rules and the Prefer Peer</a> page for further information. To use this interface,
90*2b15cb3dSCy Schubert  include the <tt>timeppps.h</tt> and <tt>refclock_atom.h</tt> header files
91*2b15cb3dSCy Schubert  and define the <tt>refclock_atom</tt> structure in the driver private storage.
92*2b15cb3dSCy Schubert  The <tt>timepps.h</tt> file is specific to each operating system and may not
93*2b15cb3dSCy Schubert  be available for some systems.</p>
94*2b15cb3dSCy Schubert<p>To use the interface, call <tt>refclock_ppsapi</tt> from the startup routine
95*2b15cb3dSCy Schubert  passing the device file descriptor and <tt>refclock_atom</tt> structure pointer.
96*2b15cb3dSCy Schubert  Then, call <tt>refclock_pps</tt> from the timer routine passing the association
97*2b15cb3dSCy Schubert  pointer and <tt>refclock_atom</tt> structure pointer. See the <tt>refclock_atom.c</tt> file
98*2b15cb3dSCy Schubert  for examples and calling sequences. If the PPS signal is valid, the offset
99*2b15cb3dSCy Schubert  sample will be save in the circular buffer and a bit set in the association
100*2b15cb3dSCy Schubert  flags word indicating the sample is valid and the driver an be selected as
101*2b15cb3dSCy Schubert  a PPS peer. If this bit is set when the poll routine is called, the driver
102*2b15cb3dSCy Schubert  calls the <tt>refclock_receive</tt> routine to process the samples in the
103*2b15cb3dSCy Schubert  circular buffer and update the system clock.</p>
1049c2daa00SOllivier Robert<hr>
105*2b15cb3dSCy Schubert<div align="center"> <img src="pic/pogo1a.gif" alt="gif"> </div>
1069c2daa00SOllivier Robert<br>
1079c2daa00SOllivier Robert<script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
1089c2daa00SOllivier Robert</body>
1099c2daa00SOllivier Robert</html>
110