1c92992fcSMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0 228aedd7eSMauro Carvalho Chehab 328aedd7eSMauro Carvalho Chehab====================== 428aedd7eSMauro Carvalho ChehabPPS - Pulse Per Second 528aedd7eSMauro Carvalho Chehab====================== 628aedd7eSMauro Carvalho Chehab 728aedd7eSMauro Carvalho ChehabCopyright (C) 2007 Rodolfo Giometti <giometti@enneenne.com> 828aedd7eSMauro Carvalho Chehab 928aedd7eSMauro Carvalho ChehabThis program is free software; you can redistribute it and/or modify 1028aedd7eSMauro Carvalho Chehabit under the terms of the GNU General Public License as published by 1128aedd7eSMauro Carvalho Chehabthe Free Software Foundation; either version 2 of the License, or 1228aedd7eSMauro Carvalho Chehab(at your option) any later version. 1328aedd7eSMauro Carvalho Chehab 1428aedd7eSMauro Carvalho ChehabThis program is distributed in the hope that it will be useful, 1528aedd7eSMauro Carvalho Chehabbut WITHOUT ANY WARRANTY; without even the implied warranty of 1628aedd7eSMauro Carvalho ChehabMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1728aedd7eSMauro Carvalho ChehabGNU General Public License for more details. 1828aedd7eSMauro Carvalho Chehab 1928aedd7eSMauro Carvalho Chehab 2028aedd7eSMauro Carvalho Chehab 2128aedd7eSMauro Carvalho ChehabOverview 2228aedd7eSMauro Carvalho Chehab-------- 2328aedd7eSMauro Carvalho Chehab 2428aedd7eSMauro Carvalho ChehabLinuxPPS provides a programming interface (API) to define in the 2528aedd7eSMauro Carvalho Chehabsystem several PPS sources. 2628aedd7eSMauro Carvalho Chehab 2728aedd7eSMauro Carvalho ChehabPPS means "pulse per second" and a PPS source is just a device which 2828aedd7eSMauro Carvalho Chehabprovides a high precision signal each second so that an application 2928aedd7eSMauro Carvalho Chehabcan use it to adjust system clock time. 3028aedd7eSMauro Carvalho Chehab 3128aedd7eSMauro Carvalho ChehabA PPS source can be connected to a serial port (usually to the Data 3228aedd7eSMauro Carvalho ChehabCarrier Detect pin) or to a parallel port (ACK-pin) or to a special 3328aedd7eSMauro Carvalho ChehabCPU's GPIOs (this is the common case in embedded systems) but in each 3428aedd7eSMauro Carvalho Chehabcase when a new pulse arrives the system must apply to it a timestamp 3528aedd7eSMauro Carvalho Chehaband record it for userland. 3628aedd7eSMauro Carvalho Chehab 3728aedd7eSMauro Carvalho ChehabCommon use is the combination of the NTPD as userland program, with a 3828aedd7eSMauro Carvalho ChehabGPS receiver as PPS source, to obtain a wallclock-time with 3928aedd7eSMauro Carvalho Chehabsub-millisecond synchronisation to UTC. 4028aedd7eSMauro Carvalho Chehab 4128aedd7eSMauro Carvalho Chehab 4228aedd7eSMauro Carvalho ChehabRFC considerations 4328aedd7eSMauro Carvalho Chehab------------------ 4428aedd7eSMauro Carvalho Chehab 4528aedd7eSMauro Carvalho ChehabWhile implementing a PPS API as RFC 2783 defines and using an embedded 4628aedd7eSMauro Carvalho ChehabCPU GPIO-Pin as physical link to the signal, I encountered a deeper 4728aedd7eSMauro Carvalho Chehabproblem: 4828aedd7eSMauro Carvalho Chehab 4928aedd7eSMauro Carvalho Chehab At startup it needs a file descriptor as argument for the function 5028aedd7eSMauro Carvalho Chehab time_pps_create(). 5128aedd7eSMauro Carvalho Chehab 5228aedd7eSMauro Carvalho ChehabThis implies that the source has a /dev/... entry. This assumption is 5328aedd7eSMauro Carvalho ChehabOK for the serial and parallel port, where you can do something 5428aedd7eSMauro Carvalho Chehabuseful besides(!) the gathering of timestamps as it is the central 5528aedd7eSMauro Carvalho Chehabtask for a PPS API. But this assumption does not work for a single 5628aedd7eSMauro Carvalho Chehabpurpose GPIO line. In this case even basic file-related functionality 5728aedd7eSMauro Carvalho Chehab(like read() and write()) makes no sense at all and should not be a 5828aedd7eSMauro Carvalho Chehabprecondition for the use of a PPS API. 5928aedd7eSMauro Carvalho Chehab 6028aedd7eSMauro Carvalho ChehabThe problem can be simply solved if you consider that a PPS source is 6128aedd7eSMauro Carvalho Chehabnot always connected with a GPS data source. 6228aedd7eSMauro Carvalho Chehab 6328aedd7eSMauro Carvalho ChehabSo your programs should check if the GPS data source (the serial port 6428aedd7eSMauro Carvalho Chehabfor instance) is a PPS source too, and if not they should provide the 6528aedd7eSMauro Carvalho Chehabpossibility to open another device as PPS source. 6628aedd7eSMauro Carvalho Chehab 6728aedd7eSMauro Carvalho ChehabIn LinuxPPS the PPS sources are simply char devices usually mapped 6828aedd7eSMauro Carvalho Chehabinto files /dev/pps0, /dev/pps1, etc. 6928aedd7eSMauro Carvalho Chehab 7028aedd7eSMauro Carvalho Chehab 7128aedd7eSMauro Carvalho ChehabPPS with USB to serial devices 7228aedd7eSMauro Carvalho Chehab------------------------------ 7328aedd7eSMauro Carvalho Chehab 7428aedd7eSMauro Carvalho ChehabIt is possible to grab the PPS from an USB to serial device. However, 7528aedd7eSMauro Carvalho Chehabyou should take into account the latencies and jitter introduced by 7628aedd7eSMauro Carvalho Chehabthe USB stack. Users have reported clock instability around +-1ms when 7728aedd7eSMauro Carvalho Chehabsynchronized with PPS through USB. With USB 2.0, jitter may decrease 7828aedd7eSMauro Carvalho Chehabdown to the order of 125 microseconds. 7928aedd7eSMauro Carvalho Chehab 8028aedd7eSMauro Carvalho ChehabThis may be suitable for time server synchronization with NTP because 8128aedd7eSMauro Carvalho Chehabof its undersampling and algorithms. 8228aedd7eSMauro Carvalho Chehab 8328aedd7eSMauro Carvalho ChehabIf your device doesn't report PPS, you can check that the feature is 8428aedd7eSMauro Carvalho Chehabsupported by its driver. Most of the time, you only need to add a call 8528aedd7eSMauro Carvalho Chehabto usb_serial_handle_dcd_change after checking the DCD status (see 8628aedd7eSMauro Carvalho Chehabch341 and pl2303 examples). 8728aedd7eSMauro Carvalho Chehab 8828aedd7eSMauro Carvalho Chehab 8928aedd7eSMauro Carvalho ChehabCoding example 9028aedd7eSMauro Carvalho Chehab-------------- 9128aedd7eSMauro Carvalho Chehab 9228aedd7eSMauro Carvalho ChehabTo register a PPS source into the kernel you should define a struct 9328aedd7eSMauro Carvalho Chehabpps_source_info as follows:: 9428aedd7eSMauro Carvalho Chehab 9528aedd7eSMauro Carvalho Chehab static struct pps_source_info pps_ktimer_info = { 9628aedd7eSMauro Carvalho Chehab .name = "ktimer", 9728aedd7eSMauro Carvalho Chehab .path = "", 9828aedd7eSMauro Carvalho Chehab .mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | 9928aedd7eSMauro Carvalho Chehab PPS_ECHOASSERT | 10028aedd7eSMauro Carvalho Chehab PPS_CANWAIT | PPS_TSFMT_TSPEC, 10128aedd7eSMauro Carvalho Chehab .echo = pps_ktimer_echo, 10228aedd7eSMauro Carvalho Chehab .owner = THIS_MODULE, 10328aedd7eSMauro Carvalho Chehab }; 10428aedd7eSMauro Carvalho Chehab 10528aedd7eSMauro Carvalho Chehaband then calling the function pps_register_source() in your 10628aedd7eSMauro Carvalho Chehabinitialization routine as follows:: 10728aedd7eSMauro Carvalho Chehab 10828aedd7eSMauro Carvalho Chehab source = pps_register_source(&pps_ktimer_info, 10928aedd7eSMauro Carvalho Chehab PPS_CAPTUREASSERT | PPS_OFFSETASSERT); 11028aedd7eSMauro Carvalho Chehab 11128aedd7eSMauro Carvalho ChehabThe pps_register_source() prototype is:: 11228aedd7eSMauro Carvalho Chehab 11328aedd7eSMauro Carvalho Chehab int pps_register_source(struct pps_source_info *info, int default_params) 11428aedd7eSMauro Carvalho Chehab 11528aedd7eSMauro Carvalho Chehabwhere "info" is a pointer to a structure that describes a particular 11628aedd7eSMauro Carvalho ChehabPPS source, "default_params" tells the system what the initial default 11728aedd7eSMauro Carvalho Chehabparameters for the device should be (it is obvious that these parameters 11828aedd7eSMauro Carvalho Chehabmust be a subset of ones defined in the struct 11928aedd7eSMauro Carvalho Chehabpps_source_info which describe the capabilities of the driver). 12028aedd7eSMauro Carvalho Chehab 12128aedd7eSMauro Carvalho ChehabOnce you have registered a new PPS source into the system you can 12228aedd7eSMauro Carvalho Chehabsignal an assert event (for example in the interrupt handler routine) 12328aedd7eSMauro Carvalho Chehabjust using:: 12428aedd7eSMauro Carvalho Chehab 12528aedd7eSMauro Carvalho Chehab pps_event(source, &ts, PPS_CAPTUREASSERT, ptr) 12628aedd7eSMauro Carvalho Chehab 12728aedd7eSMauro Carvalho Chehabwhere "ts" is the event's timestamp. 12828aedd7eSMauro Carvalho Chehab 12928aedd7eSMauro Carvalho ChehabThe same function may also run the defined echo function 13028aedd7eSMauro Carvalho Chehab(pps_ktimer_echo(), passing to it the "ptr" pointer) if the user 13128aedd7eSMauro Carvalho Chehabasked for that... etc.. 13228aedd7eSMauro Carvalho Chehab 13328aedd7eSMauro Carvalho ChehabPlease see the file drivers/pps/clients/pps-ktimer.c for example code. 13428aedd7eSMauro Carvalho Chehab 13528aedd7eSMauro Carvalho Chehab 13628aedd7eSMauro Carvalho ChehabSYSFS support 13728aedd7eSMauro Carvalho Chehab------------- 13828aedd7eSMauro Carvalho Chehab 13928aedd7eSMauro Carvalho ChehabIf the SYSFS filesystem is enabled in the kernel it provides a new class:: 14028aedd7eSMauro Carvalho Chehab 14128aedd7eSMauro Carvalho Chehab $ ls /sys/class/pps/ 14228aedd7eSMauro Carvalho Chehab pps0/ pps1/ pps2/ 14328aedd7eSMauro Carvalho Chehab 14428aedd7eSMauro Carvalho ChehabEvery directory is the ID of a PPS sources defined in the system and 14528aedd7eSMauro Carvalho Chehabinside you find several files:: 14628aedd7eSMauro Carvalho Chehab 14728aedd7eSMauro Carvalho Chehab $ ls -F /sys/class/pps/pps0/ 14828aedd7eSMauro Carvalho Chehab assert dev mode path subsystem@ 14928aedd7eSMauro Carvalho Chehab clear echo name power/ uevent 15028aedd7eSMauro Carvalho Chehab 15128aedd7eSMauro Carvalho Chehab 15228aedd7eSMauro Carvalho ChehabInside each "assert" and "clear" file you can find the timestamp and a 15328aedd7eSMauro Carvalho Chehabsequence number:: 15428aedd7eSMauro Carvalho Chehab 15528aedd7eSMauro Carvalho Chehab $ cat /sys/class/pps/pps0/assert 15628aedd7eSMauro Carvalho Chehab 1170026870.983207967#8 15728aedd7eSMauro Carvalho Chehab 15828aedd7eSMauro Carvalho ChehabWhere before the "#" is the timestamp in seconds; after it is the 15928aedd7eSMauro Carvalho Chehabsequence number. Other files are: 16028aedd7eSMauro Carvalho Chehab 16128aedd7eSMauro Carvalho Chehab * echo: reports if the PPS source has an echo function or not; 16228aedd7eSMauro Carvalho Chehab 16328aedd7eSMauro Carvalho Chehab * mode: reports available PPS functioning modes; 16428aedd7eSMauro Carvalho Chehab 16528aedd7eSMauro Carvalho Chehab * name: reports the PPS source's name; 16628aedd7eSMauro Carvalho Chehab 16728aedd7eSMauro Carvalho Chehab * path: reports the PPS source's device path, that is the device the 16828aedd7eSMauro Carvalho Chehab PPS source is connected to (if it exists). 16928aedd7eSMauro Carvalho Chehab 17028aedd7eSMauro Carvalho Chehab 17128aedd7eSMauro Carvalho ChehabTesting the PPS support 17228aedd7eSMauro Carvalho Chehab----------------------- 17328aedd7eSMauro Carvalho Chehab 17428aedd7eSMauro Carvalho ChehabIn order to test the PPS support even without specific hardware you can use 17528aedd7eSMauro Carvalho Chehabthe pps-ktimer driver (see the client subsection in the PPS configuration menu) 17628aedd7eSMauro Carvalho Chehaband the userland tools available in your distribution's pps-tools package, 17728aedd7eSMauro Carvalho Chehabhttp://linuxpps.org , or https://github.com/redlab-i/pps-tools. 17828aedd7eSMauro Carvalho Chehab 17928aedd7eSMauro Carvalho ChehabOnce you have enabled the compilation of pps-ktimer just modprobe it (if 18028aedd7eSMauro Carvalho Chehabnot statically compiled):: 18128aedd7eSMauro Carvalho Chehab 18228aedd7eSMauro Carvalho Chehab # modprobe pps-ktimer 18328aedd7eSMauro Carvalho Chehab 18428aedd7eSMauro Carvalho Chehaband the run ppstest as follow:: 18528aedd7eSMauro Carvalho Chehab 18628aedd7eSMauro Carvalho Chehab $ ./ppstest /dev/pps1 18728aedd7eSMauro Carvalho Chehab trying PPS source "/dev/pps1" 18828aedd7eSMauro Carvalho Chehab found PPS source "/dev/pps1" 18928aedd7eSMauro Carvalho Chehab ok, found 1 source(s), now start fetching data... 19028aedd7eSMauro Carvalho Chehab source 0 - assert 1186592699.388832443, sequence: 364 - clear 0.000000000, sequence: 0 19128aedd7eSMauro Carvalho Chehab source 0 - assert 1186592700.388931295, sequence: 365 - clear 0.000000000, sequence: 0 19228aedd7eSMauro Carvalho Chehab source 0 - assert 1186592701.389032765, sequence: 366 - clear 0.000000000, sequence: 0 19328aedd7eSMauro Carvalho Chehab 19428aedd7eSMauro Carvalho ChehabPlease note that to compile userland programs, you need the file timepps.h. 19528aedd7eSMauro Carvalho ChehabThis is available in the pps-tools repository mentioned above. 19628aedd7eSMauro Carvalho Chehab 19728aedd7eSMauro Carvalho Chehab 19828aedd7eSMauro Carvalho ChehabGenerators 19928aedd7eSMauro Carvalho Chehab---------- 20028aedd7eSMauro Carvalho Chehab 20128aedd7eSMauro Carvalho ChehabSometimes one needs to be able not only to catch PPS signals but to produce 20228aedd7eSMauro Carvalho Chehabthem also. For example, running a distributed simulation, which requires 203*55ed837dSPandith Ncomputers' clock to be synchronized very tightly. 204*55ed837dSPandith N 205*55ed837dSPandith N 206*55ed837dSPandith NParallel port generator 207*55ed837dSPandith N------------------------ 208*55ed837dSPandith N 209*55ed837dSPandith NOne way to do this is to invent some complicated hardware solutions but it 210*55ed837dSPandith Nmay be neither necessary nor affordable. The cheap way is to load a PPS 211*55ed837dSPandith Ngenerator on one of the computers (master) and PPS clients on others 212*55ed837dSPandith N(slaves), and use very simple cables to deliver signals using parallel 213*55ed837dSPandith Nports, for example. 21428aedd7eSMauro Carvalho Chehab 21528aedd7eSMauro Carvalho ChehabParallel port cable pinout:: 21628aedd7eSMauro Carvalho Chehab 21728aedd7eSMauro Carvalho Chehab pin name master slave 21828aedd7eSMauro Carvalho Chehab 1 STROBE *------ * 21928aedd7eSMauro Carvalho Chehab 2 D0 * | * 22028aedd7eSMauro Carvalho Chehab 3 D1 * | * 22128aedd7eSMauro Carvalho Chehab 4 D2 * | * 22228aedd7eSMauro Carvalho Chehab 5 D3 * | * 22328aedd7eSMauro Carvalho Chehab 6 D4 * | * 22428aedd7eSMauro Carvalho Chehab 7 D5 * | * 22528aedd7eSMauro Carvalho Chehab 8 D6 * | * 22628aedd7eSMauro Carvalho Chehab 9 D7 * | * 22728aedd7eSMauro Carvalho Chehab 10 ACK * ------* 22828aedd7eSMauro Carvalho Chehab 11 BUSY * * 22928aedd7eSMauro Carvalho Chehab 12 PE * * 23028aedd7eSMauro Carvalho Chehab 13 SEL * * 23128aedd7eSMauro Carvalho Chehab 14 AUTOFD * * 23228aedd7eSMauro Carvalho Chehab 15 ERROR * * 23328aedd7eSMauro Carvalho Chehab 16 INIT * * 23428aedd7eSMauro Carvalho Chehab 17 SELIN * * 23528aedd7eSMauro Carvalho Chehab 18-25 GND *-----------* 23628aedd7eSMauro Carvalho Chehab 23728aedd7eSMauro Carvalho ChehabPlease note that parallel port interrupt occurs only on high->low transition, 23828aedd7eSMauro Carvalho Chehabso it is used for PPS assert edge. PPS clear edge can be determined only 23928aedd7eSMauro Carvalho Chehabusing polling in the interrupt handler which actually can be done way more 24028aedd7eSMauro Carvalho Chehabprecisely because interrupt handling delays can be quite big and random. So 24128aedd7eSMauro Carvalho Chehabcurrent parport PPS generator implementation (pps_gen_parport module) is 24228aedd7eSMauro Carvalho Chehabgeared towards using the clear edge for time synchronization. 24328aedd7eSMauro Carvalho Chehab 24428aedd7eSMauro Carvalho ChehabClear edge polling is done with disabled interrupts so it's better to select 24528aedd7eSMauro Carvalho Chehabdelay between assert and clear edge as small as possible to reduce system 24628aedd7eSMauro Carvalho Chehablatencies. But if it is too small slave won't be able to capture clear edge 24728aedd7eSMauro Carvalho Chehabtransition. The default of 30us should be good enough in most situations. 24828aedd7eSMauro Carvalho ChehabThe delay can be selected using 'delay' pps_gen_parport module parameter. 249