18c2ecf20Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci======================
48c2ecf20Sopenharmony_ciPPS - Pulse Per Second
58c2ecf20Sopenharmony_ci======================
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciCopyright (C) 2007 Rodolfo Giometti <giometti@enneenne.com>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciThis program is free software; you can redistribute it and/or modify
108c2ecf20Sopenharmony_ciit under the terms of the GNU General Public License as published by
118c2ecf20Sopenharmony_cithe Free Software Foundation; either version 2 of the License, or
128c2ecf20Sopenharmony_ci(at your option) any later version.
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciThis program is distributed in the hope that it will be useful,
158c2ecf20Sopenharmony_cibut WITHOUT ANY WARRANTY; without even the implied warranty of
168c2ecf20Sopenharmony_ciMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
178c2ecf20Sopenharmony_ciGNU General Public License for more details.
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciOverview
228c2ecf20Sopenharmony_ci--------
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciLinuxPPS provides a programming interface (API) to define in the
258c2ecf20Sopenharmony_cisystem several PPS sources.
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciPPS means "pulse per second" and a PPS source is just a device which
288c2ecf20Sopenharmony_ciprovides a high precision signal each second so that an application
298c2ecf20Sopenharmony_cican use it to adjust system clock time.
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ciA PPS source can be connected to a serial port (usually to the Data
328c2ecf20Sopenharmony_ciCarrier Detect pin) or to a parallel port (ACK-pin) or to a special
338c2ecf20Sopenharmony_ciCPU's GPIOs (this is the common case in embedded systems) but in each
348c2ecf20Sopenharmony_cicase when a new pulse arrives the system must apply to it a timestamp
358c2ecf20Sopenharmony_ciand record it for userland.
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ciCommon use is the combination of the NTPD as userland program, with a
388c2ecf20Sopenharmony_ciGPS receiver as PPS source, to obtain a wallclock-time with
398c2ecf20Sopenharmony_cisub-millisecond synchronisation to UTC.
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ciRFC considerations
438c2ecf20Sopenharmony_ci------------------
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ciWhile implementing a PPS API as RFC 2783 defines and using an embedded
468c2ecf20Sopenharmony_ciCPU GPIO-Pin as physical link to the signal, I encountered a deeper
478c2ecf20Sopenharmony_ciproblem:
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci   At startup it needs a file descriptor as argument for the function
508c2ecf20Sopenharmony_ci   time_pps_create().
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciThis implies that the source has a /dev/... entry. This assumption is
538c2ecf20Sopenharmony_ciOK for the serial and parallel port, where you can do something
548c2ecf20Sopenharmony_ciuseful besides(!) the gathering of timestamps as it is the central
558c2ecf20Sopenharmony_citask for a PPS API. But this assumption does not work for a single
568c2ecf20Sopenharmony_cipurpose GPIO line. In this case even basic file-related functionality
578c2ecf20Sopenharmony_ci(like read() and write()) makes no sense at all and should not be a
588c2ecf20Sopenharmony_ciprecondition for the use of a PPS API.
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ciThe problem can be simply solved if you consider that a PPS source is
618c2ecf20Sopenharmony_cinot always connected with a GPS data source.
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ciSo your programs should check if the GPS data source (the serial port
648c2ecf20Sopenharmony_cifor instance) is a PPS source too, and if not they should provide the
658c2ecf20Sopenharmony_cipossibility to open another device as PPS source.
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ciIn LinuxPPS the PPS sources are simply char devices usually mapped
688c2ecf20Sopenharmony_ciinto files /dev/pps0, /dev/pps1, etc.
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciPPS with USB to serial devices
728c2ecf20Sopenharmony_ci------------------------------
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ciIt is possible to grab the PPS from an USB to serial device. However,
758c2ecf20Sopenharmony_ciyou should take into account the latencies and jitter introduced by
768c2ecf20Sopenharmony_cithe USB stack. Users have reported clock instability around +-1ms when
778c2ecf20Sopenharmony_cisynchronized with PPS through USB. With USB 2.0, jitter may decrease
788c2ecf20Sopenharmony_cidown to the order of 125 microseconds.
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ciThis may be suitable for time server synchronization with NTP because
818c2ecf20Sopenharmony_ciof its undersampling and algorithms.
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciIf your device doesn't report PPS, you can check that the feature is
848c2ecf20Sopenharmony_cisupported by its driver. Most of the time, you only need to add a call
858c2ecf20Sopenharmony_cito usb_serial_handle_dcd_change after checking the DCD status (see
868c2ecf20Sopenharmony_cich341 and pl2303 examples).
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciCoding example
908c2ecf20Sopenharmony_ci--------------
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciTo register a PPS source into the kernel you should define a struct
938c2ecf20Sopenharmony_cipps_source_info as follows::
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci    static struct pps_source_info pps_ktimer_info = {
968c2ecf20Sopenharmony_ci	    .name         = "ktimer",
978c2ecf20Sopenharmony_ci	    .path         = "",
988c2ecf20Sopenharmony_ci	    .mode         = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
998c2ecf20Sopenharmony_ci			    PPS_ECHOASSERT |
1008c2ecf20Sopenharmony_ci			    PPS_CANWAIT | PPS_TSFMT_TSPEC,
1018c2ecf20Sopenharmony_ci	    .echo         = pps_ktimer_echo,
1028c2ecf20Sopenharmony_ci	    .owner        = THIS_MODULE,
1038c2ecf20Sopenharmony_ci    };
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciand then calling the function pps_register_source() in your
1068c2ecf20Sopenharmony_ciinitialization routine as follows::
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci    source = pps_register_source(&pps_ktimer_info,
1098c2ecf20Sopenharmony_ci			PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ciThe pps_register_source() prototype is::
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci  int pps_register_source(struct pps_source_info *info, int default_params)
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciwhere "info" is a pointer to a structure that describes a particular
1168c2ecf20Sopenharmony_ciPPS source, "default_params" tells the system what the initial default
1178c2ecf20Sopenharmony_ciparameters for the device should be (it is obvious that these parameters
1188c2ecf20Sopenharmony_cimust be a subset of ones defined in the struct
1198c2ecf20Sopenharmony_cipps_source_info which describe the capabilities of the driver).
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ciOnce you have registered a new PPS source into the system you can
1228c2ecf20Sopenharmony_cisignal an assert event (for example in the interrupt handler routine)
1238c2ecf20Sopenharmony_cijust using::
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci    pps_event(source, &ts, PPS_CAPTUREASSERT, ptr)
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ciwhere "ts" is the event's timestamp.
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ciThe same function may also run the defined echo function
1308c2ecf20Sopenharmony_ci(pps_ktimer_echo(), passing to it the "ptr" pointer) if the user
1318c2ecf20Sopenharmony_ciasked for that... etc..
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ciPlease see the file drivers/pps/clients/pps-ktimer.c for example code.
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ciSYSFS support
1378c2ecf20Sopenharmony_ci-------------
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ciIf the SYSFS filesystem is enabled in the kernel it provides a new class::
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci   $ ls /sys/class/pps/
1428c2ecf20Sopenharmony_ci   pps0/  pps1/  pps2/
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ciEvery directory is the ID of a PPS sources defined in the system and
1458c2ecf20Sopenharmony_ciinside you find several files::
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci   $ ls -F /sys/class/pps/pps0/
1488c2ecf20Sopenharmony_ci   assert     dev        mode       path       subsystem@
1498c2ecf20Sopenharmony_ci   clear      echo       name       power/     uevent
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ciInside each "assert" and "clear" file you can find the timestamp and a
1538c2ecf20Sopenharmony_cisequence number::
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci   $ cat /sys/class/pps/pps0/assert
1568c2ecf20Sopenharmony_ci   1170026870.983207967#8
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ciWhere before the "#" is the timestamp in seconds; after it is the
1598c2ecf20Sopenharmony_cisequence number. Other files are:
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci * echo: reports if the PPS source has an echo function or not;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci * mode: reports available PPS functioning modes;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci * name: reports the PPS source's name;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci * path: reports the PPS source's device path, that is the device the
1688c2ecf20Sopenharmony_ci   PPS source is connected to (if it exists).
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ciTesting the PPS support
1728c2ecf20Sopenharmony_ci-----------------------
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ciIn order to test the PPS support even without specific hardware you can use
1758c2ecf20Sopenharmony_cithe pps-ktimer driver (see the client subsection in the PPS configuration menu)
1768c2ecf20Sopenharmony_ciand the userland tools available in your distribution's pps-tools package,
1778c2ecf20Sopenharmony_cihttp://linuxpps.org , or https://github.com/redlab-i/pps-tools.
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ciOnce you have enabled the compilation of pps-ktimer just modprobe it (if
1808c2ecf20Sopenharmony_cinot statically compiled)::
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci   # modprobe pps-ktimer
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ciand the run ppstest as follow::
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci   $ ./ppstest /dev/pps1
1878c2ecf20Sopenharmony_ci   trying PPS source "/dev/pps1"
1888c2ecf20Sopenharmony_ci   found PPS source "/dev/pps1"
1898c2ecf20Sopenharmony_ci   ok, found 1 source(s), now start fetching data...
1908c2ecf20Sopenharmony_ci   source 0 - assert 1186592699.388832443, sequence: 364 - clear  0.000000000, sequence: 0
1918c2ecf20Sopenharmony_ci   source 0 - assert 1186592700.388931295, sequence: 365 - clear  0.000000000, sequence: 0
1928c2ecf20Sopenharmony_ci   source 0 - assert 1186592701.389032765, sequence: 366 - clear  0.000000000, sequence: 0
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ciPlease note that to compile userland programs, you need the file timepps.h.
1958c2ecf20Sopenharmony_ciThis is available in the pps-tools repository mentioned above.
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ciGenerators
1998c2ecf20Sopenharmony_ci----------
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ciSometimes one needs to be able not only to catch PPS signals but to produce
2028c2ecf20Sopenharmony_cithem also. For example, running a distributed simulation, which requires
2038c2ecf20Sopenharmony_cicomputers' clock to be synchronized very tightly. One way to do this is to
2048c2ecf20Sopenharmony_ciinvent some complicated hardware solutions but it may be neither necessary
2058c2ecf20Sopenharmony_cinor affordable. The cheap way is to load a PPS generator on one of the
2068c2ecf20Sopenharmony_cicomputers (master) and PPS clients on others (slaves), and use very simple
2078c2ecf20Sopenharmony_cicables to deliver signals using parallel ports, for example.
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ciParallel port cable pinout::
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	pin	name	master      slave
2128c2ecf20Sopenharmony_ci	1	STROBE	  *------     *
2138c2ecf20Sopenharmony_ci	2	D0	  *     |     *
2148c2ecf20Sopenharmony_ci	3	D1	  *     |     *
2158c2ecf20Sopenharmony_ci	4	D2	  *     |     *
2168c2ecf20Sopenharmony_ci	5	D3	  *     |     *
2178c2ecf20Sopenharmony_ci	6	D4	  *     |     *
2188c2ecf20Sopenharmony_ci	7	D5	  *     |     *
2198c2ecf20Sopenharmony_ci	8	D6	  *     |     *
2208c2ecf20Sopenharmony_ci	9	D7	  *     |     *
2218c2ecf20Sopenharmony_ci	10	ACK	  *     ------*
2228c2ecf20Sopenharmony_ci	11	BUSY	  *           *
2238c2ecf20Sopenharmony_ci	12	PE	  *           *
2248c2ecf20Sopenharmony_ci	13	SEL	  *           *
2258c2ecf20Sopenharmony_ci	14	AUTOFD	  *           *
2268c2ecf20Sopenharmony_ci	15	ERROR	  *           *
2278c2ecf20Sopenharmony_ci	16	INIT	  *           *
2288c2ecf20Sopenharmony_ci	17	SELIN	  *           *
2298c2ecf20Sopenharmony_ci	18-25	GND	  *-----------*
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ciPlease note that parallel port interrupt occurs only on high->low transition,
2328c2ecf20Sopenharmony_ciso it is used for PPS assert edge. PPS clear edge can be determined only
2338c2ecf20Sopenharmony_ciusing polling in the interrupt handler which actually can be done way more
2348c2ecf20Sopenharmony_ciprecisely because interrupt handling delays can be quite big and random. So
2358c2ecf20Sopenharmony_cicurrent parport PPS generator implementation (pps_gen_parport module) is
2368c2ecf20Sopenharmony_cigeared towards using the clear edge for time synchronization.
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ciClear edge polling is done with disabled interrupts so it's better to select
2398c2ecf20Sopenharmony_cidelay between assert and clear edge as small as possible to reduce system
2408c2ecf20Sopenharmony_cilatencies. But if it is too small slave won't be able to capture clear edge
2418c2ecf20Sopenharmony_citransition. The default of 30us should be good enough in most situations.
2428c2ecf20Sopenharmony_ciThe delay can be selected using 'delay' pps_gen_parport module parameter.
243