[ntp:questions] Hints to write a clock driver

Frank Kardel kardel at ntp.org
Mon Jun 1 15:07:03 UTC 2009

Juergen Beisert wrote:
> Hi Frank,
> Frank Kardel wrote:
>>> currently I'm trying to write a clock driver for my selfmade USB
>>> based DCF77 receiver. Communication works trough the "usblib", there is
>>> no kernel driver involved. But now I'm in trouble how to forward the time
>>> to the NTPD. There are various DCF77 drivers in the ntp source tree. But
>>> they all are based on a serial device. I have no. I have to poll my USB
>>> device two times a second.
>> Hmmm, the basic heartbeat of ntpd is at once per sec. Going faster will
>> be requiring some work.
> I do not want ntpd to call my driver more than once a second. Polling my USB
> device is (currently) done in a separate thread.

Ok - the separate thread would be the first thread in ntpd in Unix (on 
Windows ntpd is running multithreaded). So you enter new terrain here 
especially since ntpd makes use of signals (SIGALM, SIGIO/SIGPOLL). You 
might want to insure that signals are only processed by the main thread.

>> Also we try to avoid any lengthy synchronous transactions where ntpd
>> processing is blocked for longer times. Thus an asynchronous programming
>> model has evolved where the request to the device are sent via the
>> transmit path or the periodic 1 sec call for refclocks.
> Who is called once a second? "struct refclock.clock_poll"?

struct refclock.clock_timer

clock_poll wants to collect a data sample.

>> Results are processed as they arrive via the input loop (in Unix-like
>> environments when the SIGIO/SIGPOLL signal arrives).
> Triggered by the serial device for the DCF77 clock drivers for example? Or
> triggered by the clock driver itself?

By the serial input or more precisely availability of input data on the 
file descriptor.

>> For this to work the communication library should provide means to
>> facilitate asynchronous notification or the interactions (request/reply)
>> need to be short and the timestamping problem (fetching the local time at
>> the second event) needs to be solved. 
> As the communication with the USB device is done in a asynchronous thread,
> reading the decoded time will be very short. Only someone must call a read
> function (and currently I guess it is struct refclock.clock_poll that gets
> called, right?)

clock_poll for collecting the data into refclock_receive(). Intermediate
measurements like the one that arrive every second can be collected with
refclock_process_offset() when the signal is deemed sane.

>>> My clock device generates a data set with a reference second pulse -
>>> synced to/by the DCF signal - and also provides the raw bit information
>>> sent via DCF in 59 bits for the next minute (one bit per second like the
>>> DCF77 signal does, but already filtered and converted to binary data). Is
>>> there a way to use anything from the libparse/ directory to let it decode
>>> the DCF bit stream, but _not_ registering and using a serial device?
>> You could extract that code. See libparse/clock_rawdcf.c.
>> cvt_rawdcf() converts serial 50 baud data to 1/0 sequences - You solved
>> that already. convert_rawdcf() converts the bit sequence to a time.
> I saw the code in libparse/clock_rawdcf.c. I wanted to avoid to copy it. But
> it seems to be the easiest way. :-(

The interface would change too much for you.

>> Another way to do it, is to use the shm driver. Create a program that
>> controls your device and does the timestamping. This program can feed
>> ntpd via shared memory with the data. No need to mess with ntpd at all.
>> See gpsd for an example of an implementation.
> I saw this code already. But when the ntpd calls one of my registered clock
> driver functions periodically I will be more happy.
> Thanks for your help.
> Juergen


More information about the questions mailing list