cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pps.rst (8641B)


      1.. SPDX-License-Identifier: GPL-2.0
      2
      3======================
      4PPS - Pulse Per Second
      5======================
      6
      7Copyright (C) 2007 Rodolfo Giometti <giometti@enneenne.com>
      8
      9This program is free software; you can redistribute it and/or modify
     10it under the terms of the GNU General Public License as published by
     11the Free Software Foundation; either version 2 of the License, or
     12(at your option) any later version.
     13
     14This program is distributed in the hope that it will be useful,
     15but WITHOUT ANY WARRANTY; without even the implied warranty of
     16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17GNU General Public License for more details.
     18
     19
     20
     21Overview
     22--------
     23
     24LinuxPPS provides a programming interface (API) to define in the
     25system several PPS sources.
     26
     27PPS means "pulse per second" and a PPS source is just a device which
     28provides a high precision signal each second so that an application
     29can use it to adjust system clock time.
     30
     31A PPS source can be connected to a serial port (usually to the Data
     32Carrier Detect pin) or to a parallel port (ACK-pin) or to a special
     33CPU's GPIOs (this is the common case in embedded systems) but in each
     34case when a new pulse arrives the system must apply to it a timestamp
     35and record it for userland.
     36
     37Common use is the combination of the NTPD as userland program, with a
     38GPS receiver as PPS source, to obtain a wallclock-time with
     39sub-millisecond synchronisation to UTC.
     40
     41
     42RFC considerations
     43------------------
     44
     45While implementing a PPS API as RFC 2783 defines and using an embedded
     46CPU GPIO-Pin as physical link to the signal, I encountered a deeper
     47problem:
     48
     49   At startup it needs a file descriptor as argument for the function
     50   time_pps_create().
     51
     52This implies that the source has a /dev/... entry. This assumption is
     53OK for the serial and parallel port, where you can do something
     54useful besides(!) the gathering of timestamps as it is the central
     55task for a PPS API. But this assumption does not work for a single
     56purpose GPIO line. In this case even basic file-related functionality
     57(like read() and write()) makes no sense at all and should not be a
     58precondition for the use of a PPS API.
     59
     60The problem can be simply solved if you consider that a PPS source is
     61not always connected with a GPS data source.
     62
     63So your programs should check if the GPS data source (the serial port
     64for instance) is a PPS source too, and if not they should provide the
     65possibility to open another device as PPS source.
     66
     67In LinuxPPS the PPS sources are simply char devices usually mapped
     68into files /dev/pps0, /dev/pps1, etc.
     69
     70
     71PPS with USB to serial devices
     72------------------------------
     73
     74It is possible to grab the PPS from an USB to serial device. However,
     75you should take into account the latencies and jitter introduced by
     76the USB stack. Users have reported clock instability around +-1ms when
     77synchronized with PPS through USB. With USB 2.0, jitter may decrease
     78down to the order of 125 microseconds.
     79
     80This may be suitable for time server synchronization with NTP because
     81of its undersampling and algorithms.
     82
     83If your device doesn't report PPS, you can check that the feature is
     84supported by its driver. Most of the time, you only need to add a call
     85to usb_serial_handle_dcd_change after checking the DCD status (see
     86ch341 and pl2303 examples).
     87
     88
     89Coding example
     90--------------
     91
     92To register a PPS source into the kernel you should define a struct
     93pps_source_info as follows::
     94
     95    static struct pps_source_info pps_ktimer_info = {
     96	    .name         = "ktimer",
     97	    .path         = "",
     98	    .mode         = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
     99			    PPS_ECHOASSERT |
    100			    PPS_CANWAIT | PPS_TSFMT_TSPEC,
    101	    .echo         = pps_ktimer_echo,
    102	    .owner        = THIS_MODULE,
    103    };
    104
    105and then calling the function pps_register_source() in your
    106initialization routine as follows::
    107
    108    source = pps_register_source(&pps_ktimer_info,
    109			PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
    110
    111The pps_register_source() prototype is::
    112
    113  int pps_register_source(struct pps_source_info *info, int default_params)
    114
    115where "info" is a pointer to a structure that describes a particular
    116PPS source, "default_params" tells the system what the initial default
    117parameters for the device should be (it is obvious that these parameters
    118must be a subset of ones defined in the struct
    119pps_source_info which describe the capabilities of the driver).
    120
    121Once you have registered a new PPS source into the system you can
    122signal an assert event (for example in the interrupt handler routine)
    123just using::
    124
    125    pps_event(source, &ts, PPS_CAPTUREASSERT, ptr)
    126
    127where "ts" is the event's timestamp.
    128
    129The same function may also run the defined echo function
    130(pps_ktimer_echo(), passing to it the "ptr" pointer) if the user
    131asked for that... etc..
    132
    133Please see the file drivers/pps/clients/pps-ktimer.c for example code.
    134
    135
    136SYSFS support
    137-------------
    138
    139If the SYSFS filesystem is enabled in the kernel it provides a new class::
    140
    141   $ ls /sys/class/pps/
    142   pps0/  pps1/  pps2/
    143
    144Every directory is the ID of a PPS sources defined in the system and
    145inside you find several files::
    146
    147   $ ls -F /sys/class/pps/pps0/
    148   assert     dev        mode       path       subsystem@
    149   clear      echo       name       power/     uevent
    150
    151
    152Inside each "assert" and "clear" file you can find the timestamp and a
    153sequence number::
    154
    155   $ cat /sys/class/pps/pps0/assert
    156   1170026870.983207967#8
    157
    158Where before the "#" is the timestamp in seconds; after it is the
    159sequence number. Other files are:
    160
    161 * echo: reports if the PPS source has an echo function or not;
    162
    163 * mode: reports available PPS functioning modes;
    164
    165 * name: reports the PPS source's name;
    166
    167 * path: reports the PPS source's device path, that is the device the
    168   PPS source is connected to (if it exists).
    169
    170
    171Testing the PPS support
    172-----------------------
    173
    174In order to test the PPS support even without specific hardware you can use
    175the pps-ktimer driver (see the client subsection in the PPS configuration menu)
    176and the userland tools available in your distribution's pps-tools package,
    177http://linuxpps.org , or https://github.com/redlab-i/pps-tools.
    178
    179Once you have enabled the compilation of pps-ktimer just modprobe it (if
    180not statically compiled)::
    181
    182   # modprobe pps-ktimer
    183
    184and the run ppstest as follow::
    185
    186   $ ./ppstest /dev/pps1
    187   trying PPS source "/dev/pps1"
    188   found PPS source "/dev/pps1"
    189   ok, found 1 source(s), now start fetching data...
    190   source 0 - assert 1186592699.388832443, sequence: 364 - clear  0.000000000, sequence: 0
    191   source 0 - assert 1186592700.388931295, sequence: 365 - clear  0.000000000, sequence: 0
    192   source 0 - assert 1186592701.389032765, sequence: 366 - clear  0.000000000, sequence: 0
    193
    194Please note that to compile userland programs, you need the file timepps.h.
    195This is available in the pps-tools repository mentioned above.
    196
    197
    198Generators
    199----------
    200
    201Sometimes one needs to be able not only to catch PPS signals but to produce
    202them also. For example, running a distributed simulation, which requires
    203computers' clock to be synchronized very tightly. One way to do this is to
    204invent some complicated hardware solutions but it may be neither necessary
    205nor affordable. The cheap way is to load a PPS generator on one of the
    206computers (master) and PPS clients on others (slaves), and use very simple
    207cables to deliver signals using parallel ports, for example.
    208
    209Parallel port cable pinout::
    210
    211	pin	name	master      slave
    212	1	STROBE	  *------     *
    213	2	D0	  *     |     *
    214	3	D1	  *     |     *
    215	4	D2	  *     |     *
    216	5	D3	  *     |     *
    217	6	D4	  *     |     *
    218	7	D5	  *     |     *
    219	8	D6	  *     |     *
    220	9	D7	  *     |     *
    221	10	ACK	  *     ------*
    222	11	BUSY	  *           *
    223	12	PE	  *           *
    224	13	SEL	  *           *
    225	14	AUTOFD	  *           *
    226	15	ERROR	  *           *
    227	16	INIT	  *           *
    228	17	SELIN	  *           *
    229	18-25	GND	  *-----------*
    230
    231Please note that parallel port interrupt occurs only on high->low transition,
    232so it is used for PPS assert edge. PPS clear edge can be determined only
    233using polling in the interrupt handler which actually can be done way more
    234precisely because interrupt handling delays can be quite big and random. So
    235current parport PPS generator implementation (pps_gen_parport module) is
    236geared towards using the clear edge for time synchronization.
    237
    238Clear edge polling is done with disabled interrupts so it's better to select
    239delay between assert and clear edge as small as possible to reduce system
    240latencies. But if it is too small slave won't be able to capture clear edge
    241transition. The default of 30us should be good enough in most situations.
    242The delay can be selected using 'delay' pps_gen_parport module parameter.