Documentation/driver-api/pps.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

PPS - Pulse Per Second

LinuxPPS source capture, RFC API, sysfs·test, PPS generator와 parallel/Intel output의 전문 번역입니다.

Source pathDocumentation/driver-api/pps.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

pps.rst:1-311

LinuxPPS는 serial DCD, parallel ACK, GPIO 등의 매초 edge에 kernel timestamp를 붙여 `/dev/ppsN`과 sysfs로 제공하고 NTP 같은 userland가 system clock을 discipline하게 합니다. 반대 방향의 pps-gen은 system 또는 peripheral clock으로 output pulse를 만들며 parallel port와 Intel Timed I/O 구현을 제공합니다.

문서 구성
원문 줄내용
1-88PPS 개념, RFC file descriptor, USB latency
89-170source 등록·event·sysfs
171-197pps-ktimer와 ppstest
198-244generator 등록과 sysfs
245-311parallel port와 Intel Timed I/O generator

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ======================
4 PPS - Pulse Per Second
5 ======================
6
7 Copyright (C) 2007 Rodolfo Giometti <[email protected]>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19
20
21 Overview
22 --------
23
24 LinuxPPS provides a programming interface (API) to define in the
25 system several PPS sources.
26
27 PPS means "pulse per second" and a PPS source is just a device which
28 provides a high precision signal each second so that an application
29 can use it to adjust system clock time.
30
31 A PPS source can be connected to a serial port (usually to the Data
32 Carrier Detect pin) or to a parallel port (ACK-pin) or to a special
33 CPU's GPIOs (this is the common case in embedded systems) but in each
34 case when a new pulse arrives the system must apply to it a timestamp
35 and record it for userland.
36
37 Common use is the combination of the NTPD as userland program, with a
38 GPS receiver as PPS source, to obtain a wallclock-time with
39 sub-millisecond synchronisation to UTC.
40
41
42 RFC considerations
43 ------------------
44
45 While implementing a PPS API as RFC 2783 defines and using an embedded
46 CPU GPIO-Pin as physical link to the signal, I encountered a deeper
47 problem:
48
49 At startup it needs a file descriptor as argument for the function
50 time_pps_create().
51
52 This implies that the source has a /dev/... entry. This assumption is
53 OK for the serial and parallel port, where you can do something
54 useful besides(!) the gathering of timestamps as it is the central
55 task for a PPS API. But this assumption does not work for a single
56 purpose 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
58 precondition for the use of a PPS API.
59
60 The problem can be simply solved if you consider that a PPS source is
61 not always connected with a GPS data source.
62
63 So your programs should check if the GPS data source (the serial port
64 for instance) is a PPS source too, and if not they should provide the
65 possibility to open another device as PPS source.
66
67 In LinuxPPS the PPS sources are simply char devices usually mapped
68 into files /dev/pps0, /dev/pps1, etc.
69
70
71 PPS with USB to serial devices
72 ------------------------------
73
74 It is possible to grab the PPS from an USB to serial device. However,
75 you should take into account the latencies and jitter introduced by
76 the USB stack. Users have reported clock instability around +-1ms when
77 synchronized with PPS through USB. With USB 2.0, jitter may decrease
78 down to the order of 125 microseconds.
79
80 This may be suitable for time server synchronization with NTP because
81 of its undersampling and algorithms.
82
83 If your device doesn't report PPS, you can check that the feature is
84 supported by its driver. Most of the time, you only need to add a call
85 to usb_serial_handle_dcd_change after checking the DCD status (see
86 ch341 and pl2303 examples).
87
88
89 Coding example
90 --------------
91
92 To register a PPS source into the kernel you should define a struct
93 pps_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
105 and then calling the function pps_register_source() in your
106 initialization routine as follows::
107
108 source = pps_register_source(&pps_ktimer_info,
109 PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
110
111 The pps_register_source() prototype is::
112
113 int pps_register_source(struct pps_source_info *info, int default_params)
114
115 where "info" is a pointer to a structure that describes a particular
116 PPS source, "default_params" tells the system what the initial default
117 parameters for the device should be (it is obvious that these parameters
118 must be a subset of ones defined in the struct
119 pps_source_info which describe the capabilities of the driver).
120
121 Once you have registered a new PPS source into the system you can
122 signal an assert event (for example in the interrupt handler routine)
123 just using::
124
125 pps_event(source, &ts, PPS_CAPTUREASSERT, ptr)
126
127 where "ts" is the event's timestamp.
128
129 The same function may also run the defined echo function
130 (pps_ktimer_echo(), passing to it the "ptr" pointer) if the user
131 asked for that... etc..
132
133 Please see the file drivers/pps/clients/pps-ktimer.c for example code.
134
135
136 SYSFS support
137 -------------
138
139 If the SYSFS filesystem is enabled in the kernel it provides a new class::
140
141 $ ls /sys/class/pps/
142 pps0/ pps1/ pps2/
143
144 Every directory is the ID of a PPS sources defined in the system and
145 inside 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
152 Inside each "assert" and "clear" file you can find the timestamp and a
153 sequence number::
154
155 $ cat /sys/class/pps/pps0/assert
156 1170026870.983207967#8
157
158 Where before the "#" is the timestamp in seconds; after it is the
159 sequence 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
171 Testing the PPS support
172 -----------------------
173
174 In order to test the PPS support even without specific hardware you can use
175 the pps-ktimer driver (see the client subsection in the PPS configuration menu)
176 and the userland tools available in your distribution's pps-tools package,
177 http://linuxpps.org , or https://github.com/redlab-i/pps-tools.
178
179 Once you have enabled the compilation of pps-ktimer just modprobe it (if
180 not statically compiled)::
181
182 # modprobe pps-ktimer
183
184 and 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
194 Please note that to compile userland programs, you need the file timepps.h.
195 This is available in the pps-tools repository mentioned above.
196
197
198 Generators
199 ----------
200
201 Sometimes one needs to be able not only to catch PPS signals but to produce
202 them also. For example, running a distributed simulation, which requires
203 computers' clock to be synchronized very tightly.
204
205 To do so the class pps-gen has been added. PPS generators can be
206 registered in the kernel by defining a struct pps_gen_source_info as
207 follows::
208
209 static const struct pps_gen_source_info pps_gen_dummy_info = {
210 .use_system_clock = true,
211 .get_time = pps_gen_dummy_get_time,
212 .enable = pps_gen_dummy_enable,
213 };
214
215 Where the use_system_clock states if the generator uses the system
216 clock to generate its pulses, or they are from a peripheral device
217 clock. Method get_time() is used to query the time stored into the
218 generator clock, while the method enable() is used to enable or
219 disable the PPS pulse generation.
220
221 Then calling the function pps_gen_register_source() in your
222 initialization routine as follows creates a new generator in the
223 system::
224
225 pps_gen = pps_gen_register_source(&pps_gen_dummy_info);
226
227 Generators SYSFS support
228 ------------------------
229
230 If the SYSFS filesystem is enabled in the kernel it provides a new class::
231
232 $ ls /sys/class/pps-gen/
233 pps-gen0/ pps-gen1/ pps-gen2/
234
235 Every directory is the ID of a PPS generator defined in the system and
236 inside of it you find several files::
237
238 $ ls -F /sys/class/pps-gen/pps-gen0/
239 dev enable name power/ subsystem@ system time uevent
240
241 To enable the PPS signal generation you can use the command below::
242
243 $ echo 1 > /sys/class/pps-gen/pps-gen0/enable
244
245 Parallel port generator
246 ------------------------
247
248 One way to do this is to invent some complicated hardware solutions but it
249 may be neither necessary nor affordable. The cheap way is to load a PPS
250 generator on one of the computers (master) and PPS clients on others
251 (slaves), and use very simple cables to deliver signals using parallel
252 ports, for example.
253
254 Parallel port cable pinout::
255
256 pin name master slave
257 1 STROBE *------ *
258 2 D0 * | *
259 3 D1 * | *
260 4 D2 * | *
261 5 D3 * | *
262 6 D4 * | *
263 7 D5 * | *
264 8 D6 * | *
265 9 D7 * | *
266 10 ACK * ------*
267 11 BUSY * *
268 12 PE * *
269 13 SEL * *
270 14 AUTOFD * *
271 15 ERROR * *
272 16 INIT * *
273 17 SELIN * *
274 18-25 GND *-----------*
275
276 Please note that parallel port interrupt occurs only on high->low transition,
277 so it is used for PPS assert edge. PPS clear edge can be determined only
278 using polling in the interrupt handler which actually can be done way more
279 precisely because interrupt handling delays can be quite big and random. So
280 current parport PPS generator implementation (pps_gen_parport module) is
281 geared towards using the clear edge for time synchronization.
282
283 Clear edge polling is done with disabled interrupts so it's better to select
284 delay between assert and clear edge as small as possible to reduce system
285 latencies. But if it is too small slave won't be able to capture clear edge
286 transition. The default of 30us should be good enough in most situations.
287 The delay can be selected using 'delay' pps_gen_parport module parameter.
288
289
290 Intel Timed I/O PPS signal generator
291 ------------------------------------
292
293 Intel Timed I/O is a high precision device, present on 2019 and newer Intel
294 CPUs, that can generate PPS signals.
295
296 Timed I/O and system time are both driven by same hardware clock. The signal
297 is generated with a precision of ~20 nanoseconds. The generated PPS signal
298 is used to synchronize an external device with system clock. For example,
299 it can be used to share your clock with a device that receives PPS signal,
300 generated by Timed I/O device. There are dedicated Timed I/O pins to deliver
301 the PPS signal to an external device.
302
303 Usage of Intel Timed I/O as PPS generator:
304
305 Start generating PPS signal::
306
307 $echo 1 > /sys/class/pps-gen/pps-genx/enable
308
309 Stop generating PPS signal::
310
311 $echo 0 > /sys/class/pps-gen/pps-genx/enable
312

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

LinuxPPS와 pulse-per-second source

1-41

LinuxPPS는 system 안에 여러 PPS source를 정의하는 programming API입니다. PPS는 pulse per second를 뜻하며 source는 매초 high-precision signal을 제공해 application이 system clock을 보정할 수 있게 합니다.

PPS source는 보통 serial port의 Data Carrier Detect pin, parallel port의 ACK pin, 또는 embedded system의 CPU GPIO에 연결됩니다. 어느 연결이든 새 pulse가 도착하면 kernel이 즉시 timestamp를 붙이고 userland가 읽을 수 있도록 기록해야 합니다.

대표 구성은 GPS receiver를 PPS source로 사용하고 userland NTPD가 이를 처리해 wall-clock time을 UTC에 sub-millisecond 수준으로 동기화하는 방식입니다.

PPS time synchronization
GPS / serial DCD / parallel ACK / GPIOPPS edgeKernel timestampLinuxPPS sourceNTPDSystem clock synchronized to UTC

매초 발생한 hardware edge에 kernel timestamp를 붙여 user-space clock discipline에 제공합니다.

.. SPDX-License-Identifier: GPL-2.0

======================
PPS - Pulse Per Second
======================

Copyright (C) 2007 Rodolfo Giometti <[email protected]>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.



Overview
--------

LinuxPPS provides a programming interface (API) to define in the
system several PPS sources.

PPS means "pulse per second" and a PPS source is just a device which
provides a high precision signal each second so that an application
can use it to adjust system clock time.

A PPS source can be connected to a serial port (usually to the Data
Carrier Detect pin) or to a parallel port (ACK-pin) or to a special
CPU's GPIOs (this is the common case in embedded systems) but in each
case when a new pulse arrives the system must apply to it a timestamp
and record it for userland.

Common use is the combination of the NTPD as userland program, with a
GPS receiver as PPS source, to obtain a wallclock-time with
sub-millisecond synchronisation to UTC.

RFC 2783 file descriptor 가정과 Linux char device

42-70

RFC 2783 PPS API의 `time_pps_create()`는 시작할 때 file descriptor를 요구하므로 source에 `/dev/...` entry가 있다고 가정합니다. serial·parallel port는 timestamp capture 외에도 read/write 기능이 있어 자연스럽지만, single-purpose GPIO line에는 file operation 자체가 의미 없으므로 이 가정이 맞지 않습니다.

PPS source가 GPS data source와 항상 같은 device는 아닙니다. application은 GPS serial port 자체가 PPS source인지 확인하고, 아니라면 별도 PPS device를 열 수 있게 해야 합니다.

LinuxPPS는 source를 `/dev/pps0`, `/dev/pps1` 같은 char device로 mapping해 RFC API가 요구하는 descriptor와 실제 signal source를 분리합니다.

RFC API와 LinuxPPS mapping
대상문제 또는 역할Linux 처리
`time_pps_create()`file descriptor 필요`/dev/ppsN` char device 제공
serial/paralleldata I/O와 PPS를 함께 제공 가능같은 physical source 사용 가능
single-purpose GPIOread/write 의미 없음별도 PPS char device로 노출
GPS data sourcePPS source와 다를 수 있음application이 별도 device 선택

RFC considerations
------------------

While implementing a PPS API as RFC 2783 defines and using an embedded
CPU GPIO-Pin as physical link to the signal, I encountered a deeper
problem:

   At startup it needs a file descriptor as argument for the function
   time_pps_create().

This implies that the source has a /dev/... entry. This assumption is
OK for the serial and parallel port, where you can do something
useful besides(!) the gathering of timestamps as it is the central
task for a PPS API. But this assumption does not work for a single
purpose GPIO line. In this case even basic file-related functionality
(like read() and write()) makes no sense at all and should not be a
precondition for the use of a PPS API.

The problem can be simply solved if you consider that a PPS source is
not always connected with a GPS data source.

So your programs should check if the GPS data source (the serial port
for instance) is a PPS source too, and if not they should provide the
possibility to open another device as PPS source.

In LinuxPPS the PPS sources are simply char devices usually mapped
into files /dev/pps0, /dev/pps1, etc.

USB-to-serial PPS의 latency와 driver 지원

71-88

USB-to-serial device에서도 PPS를 capture할 수 있지만 USB stack이 latency와 jitter를 추가합니다. user report에서는 USB PPS 동기화의 clock instability가 약 ±1ms였고 USB 2.0에서는 jitter가 약 125 microseconds 수준까지 줄 수 있습니다.

NTP의 undersampling과 filtering algorithm을 사용한 time server에는 이 정확도가 충분할 수 있습니다. device가 PPS를 report하지 않으면 driver 지원 여부를 확인해야 하며, 많은 경우 DCD status 확인 뒤 `usb_serial_handle_dcd_change()` 호출을 추가하면 됩니다. `ch341`과 `pl2303` driver가 예입니다.

USB serial PPS 특성
경로관측 jitter구현 확인
일반 USB PPS약 ±1 msUSB stack latency 고려
USB 2.0약 125 µs 수준 가능NTP filtering에 적합할 수 있음
driver DCD handling`usb_serial_handle_dcd_change()``ch341`, `pl2303` 참고

PPS with USB to serial devices
------------------------------

It is possible to grab the PPS from an USB to serial device. However,
you should take into account the latencies and jitter introduced by
the USB stack. Users have reported clock instability around +-1ms when
synchronized with PPS through USB. With USB 2.0, jitter may decrease
down to the order of 125 microseconds.

This may be suitable for time server synchronization with NTP because
of its undersampling and algorithms.

If your device doesn't report PPS, you can check that the feature is
supported by its driver. Most of the time, you only need to add a call
to usb_serial_handle_dcd_change after checking the DCD status (see
ch341 and pl2303 examples).

PPS source 등록과 event 전달

89-135

kernel에 PPS source를 등록하려면 `struct pps_source_info`를 정의합니다. 예제 `pps_ktimer_info`는 name, path, 지원 mode, echo callback, owner를 지정하며 mode에는 `PPS_CAPTUREASSERT`, `PPS_OFFSETASSERT`, `PPS_ECHOASSERT`, `PPS_CANWAIT`, `PPS_TSFMT_TSPEC` capability가 포함됩니다.

initialization routine에서 `pps_register_source(&pps_ktimer_info, default_params)`를 호출합니다. `info`는 source capability를 설명하고 `default_params`는 초기 device parameter이므로 반드시 capability mode의 subset이어야 합니다.

등록 뒤 interrupt handler 같은 pulse 처리 지점에서 `pps_event(source, &ts, PPS_CAPTUREASSERT, ptr)`를 호출해 assert event와 timestamp를 기록합니다. user가 echo를 요청했다면 같은 함수가 `ptr`을 넘겨 `pps_ktimer_echo()`도 실행할 수 있습니다. 전체 예제는 `drivers/pps/clients/pps-ktimer.c`에 있습니다.

PPS source lifecycle
`struct pps_source_info``pps_register_source()``/dev/ppsN`Hardware assert edge`pps_event()`Timestamp + optional echo

capability를 등록한 뒤 각 hardware edge를 timestamp event로 전달합니다.

Coding example
--------------

To register a PPS source into the kernel you should define a struct
pps_source_info as follows::

    static struct pps_source_info pps_ktimer_info = {
            .name         = "ktimer",
            .path         = "",
            .mode         = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
                            PPS_ECHOASSERT |
                            PPS_CANWAIT | PPS_TSFMT_TSPEC,
            .echo         = pps_ktimer_echo,
            .owner        = THIS_MODULE,
    };

and then calling the function pps_register_source() in your
initialization routine as follows::

    source = pps_register_source(&pps_ktimer_info,
                        PPS_CAPTUREASSERT | PPS_OFFSETASSERT);

The pps_register_source() prototype is::

  int pps_register_source(struct pps_source_info *info, int default_params)

where "info" is a pointer to a structure that describes a particular
PPS source, "default_params" tells the system what the initial default
parameters for the device should be (it is obvious that these parameters
must be a subset of ones defined in the struct
pps_source_info which describe the capabilities of the driver).

Once you have registered a new PPS source into the system you can
signal an assert event (for example in the interrupt handler routine)
just using::

    pps_event(source, &ts, PPS_CAPTUREASSERT, ptr)

where "ts" is the event's timestamp.

The same function may also run the defined echo function
(pps_ktimer_echo(), passing to it the "ptr" pointer) if the user
asked for that... etc..

Please see the file drivers/pps/clients/pps-ktimer.c for example code.

PPS source sysfs interface

136-170

SYSFS를 enable한 kernel은 `/sys/class/pps/` 아래에 `pps0`, `pps1`처럼 등록 source별 directory를 만듭니다. 각 directory에는 `assert`, `clear`, `dev`, `echo`, `mode`, `name`, `path`, `power`, `subsystem`, `uevent`가 나타납니다.

`assert`와 `clear` file은 `seconds.nanoseconds#sequence` 형식으로 timestamp와 sequence number를 제공합니다. `#` 앞은 seconds 단위 timestamp이고 뒤는 event sequence입니다.

`echo`는 source에 echo function이 있는지, `mode`는 사용 가능한 PPS mode, `name`은 source 이름, `path`는 존재하는 경우 source가 연결된 device path를 보여 줍니다.

`/sys/class/pps/ppsN`
파일내용
`assert` / `clear`timestamp와 sequence number
`echo`echo callback 지원 여부
`mode`지원 PPS mode
`name`source name
`path`연결 device path
`dev` / `power` / `subsystem` / `uevent`device-model 정보

SYSFS support
-------------

If the SYSFS filesystem is enabled in the kernel it provides a new class::

   $ ls /sys/class/pps/
   pps0/  pps1/  pps2/

Every directory is the ID of a PPS sources defined in the system and
inside you find several files::

   $ ls -F /sys/class/pps/pps0/
   assert     dev        mode       path       subsystem@
   clear      echo       name       power/     uevent


Inside each "assert" and "clear" file you can find the timestamp and a
sequence number::

   $ cat /sys/class/pps/pps0/assert
   1170026870.983207967#8

Where before the "#" is the timestamp in seconds; after it is the
sequence number. Other files are:

 * echo: reports if the PPS source has an echo function or not;

 * mode: reports available PPS functioning modes;

 * name: reports the PPS source's name;

 * path: reports the PPS source's device path, that is the device the
   PPS source is connected to (if it exists).

pps-ktimer와 ppstest

171-197

전용 PPS hardware가 없어도 kernel configuration의 PPS client 항목에서 `pps-ktimer`를 enable하고 distribution의 `pps-tools`, linuxpps.org 또는 redlab-i/pps-tools를 사용해 지원을 시험할 수 있습니다.

module이면 `modprobe pps-ktimer`로 load한 뒤 `ppstest /dev/pps1`을 실행합니다. output은 source 발견 여부와 연속 assert timestamp·sequence를 보여 주며 clear event가 없으면 zero timestamp와 sequence 0으로 표시될 수 있습니다.

userland program을 compile하려면 pps-tools repository의 `timepps.h`가 필요합니다.

PPS test 절차
Enable `pps-ktimer``modprobe pps-ktimer``/dev/ppsN``ppstest`Assert timestamp sequence

software timer source로 char-device capture 경로를 검증합니다.

Testing the PPS support
-----------------------

In order to test the PPS support even without specific hardware you can use
the pps-ktimer driver (see the client subsection in the PPS configuration menu)
and the userland tools available in your distribution's pps-tools package,
http://linuxpps.org , or https://github.com/redlab-i/pps-tools.

Once you have enabled the compilation of pps-ktimer just modprobe it (if
not statically compiled)::

   # modprobe pps-ktimer

and the run ppstest as follow::

   $ ./ppstest /dev/pps1
   trying PPS source "/dev/pps1"
   found PPS source "/dev/pps1"
   ok, found 1 source(s), now start fetching data...
   source 0 - assert 1186592699.388832443, sequence: 364 - clear  0.000000000, sequence: 0
   source 0 - assert 1186592700.388931295, sequence: 365 - clear  0.000000000, sequence: 0
   source 0 - assert 1186592701.389032765, sequence: 366 - clear  0.000000000, sequence: 0

Please note that to compile userland programs, you need the file timepps.h.
This is available in the pps-tools repository mentioned above.

PPS generator 등록

198-226

distributed simulation처럼 여러 computer clock을 매우 정밀하게 맞추려면 PPS를 capture할 뿐 아니라 생성해야 합니다. 이를 위해 kernel은 `pps-gen` class를 제공합니다.

generator는 `struct pps_gen_source_info`를 정의해 등록합니다. `use_system_clock`은 pulse timing이 system clock인지 peripheral device clock인지 나타냅니다. `get_time()`은 generator clock의 현재 시간을 조회하고 `enable()`은 pulse generation을 enable 또는 disable합니다.

initialization routine에서 `pps_gen_register_source(&pps_gen_dummy_info)`를 호출하면 새 PPS generator가 system에 생성됩니다.

PPS generator lifecycle
`struct pps_gen_source_info``use_system_clock``get_time()` + `enable()``pps_gen_register_source()`PPS output

clock source와 callback을 등록해 주기적 output pulse를 제공합니다.

Generators
----------

Sometimes one needs to be able not only to catch PPS signals but to produce
them also. For example, running a distributed simulation, which requires
computers' clock to be synchronized very tightly.

To do so the class pps-gen has been added. PPS generators can be
registered in the kernel by defining a struct pps_gen_source_info as
follows::

    static const struct pps_gen_source_info pps_gen_dummy_info = {
            .use_system_clock       = true,
            .get_time               = pps_gen_dummy_get_time,
            .enable                 = pps_gen_dummy_enable,
    };

Where the use_system_clock states if the generator uses the system
clock to generate its pulses, or they are from a peripheral device
clock. Method get_time() is used to query the time stored into the
generator clock, while the method enable() is used to enable or
disable the PPS pulse generation.

Then calling the function pps_gen_register_source() in your
initialization routine as follows creates a new generator in the
system::

    pps_gen = pps_gen_register_source(&pps_gen_dummy_info);

PPS generator sysfs

227-244

SYSFS가 enable되면 `/sys/class/pps-gen/` 아래에 `pps-gen0`, `pps-gen1` 같은 generator directory가 생성됩니다. 각 directory에는 `dev`, `enable`, `name`, `power`, `subsystem`, `system`, `time`, `uevent`가 있습니다.

`enable`에 1을 쓰면 PPS signal generation을 시작합니다. 같은 file은 generator의 runtime output switch로 사용됩니다.

`/sys/class/pps-gen/pps-genN`
파일역할
`enable`1/0으로 pulse generation 제어
`system`system clock 사용 여부
`time`generator clock time
`name` / `dev`generator 식별

Generators SYSFS support
------------------------

If the SYSFS filesystem is enabled in the kernel it provides a new class::

    $ ls /sys/class/pps-gen/
    pps-gen0/  pps-gen1/  pps-gen2/

Every directory is the ID of a PPS generator defined in the system and
inside of it you find several files::

    $ ls -F /sys/class/pps-gen/pps-gen0/
    dev  enable  name  power/  subsystem@  system  time  uevent

To enable the PPS signal generation you can use the command below::

    $ echo 1 > /sys/class/pps-gen/pps-gen0/enable

parallel-port PPS generator와 cable timing

245-289

저렴한 distributed clock 구성은 master computer에 PPS generator를 load하고 slave computer에는 PPS client를 두어 simple parallel-port cable로 signal을 전달합니다. cable은 master의 STROBE pin 1을 slave의 ACK pin 10에 연결하고 pin 18–25의 GND를 서로 연결합니다. 다른 data/status pin은 이 예에서 연결하지 않습니다.

parallel-port interrupt는 high→low transition에서만 발생하므로 이 edge를 PPS assert로 사용합니다. clear edge는 interrupt handler 안의 polling으로 결정하며 interrupt latency가 크고 random할 수 있어 오히려 이 방식이 더 정밀할 수 있습니다. 현재 `pps_gen_parport`는 clear edge를 time synchronization 기준으로 사용합니다.

clear polling은 interrupt를 disabled한 채 수행하므로 assert와 clear 사이 delay는 system latency를 줄이도록 작게 해야 합니다. 너무 작으면 slave가 clear transition을 capture하지 못합니다. 기본 30µs가 대체로 적절하며 `pps_gen_parport` module의 `delay` parameter로 조정합니다.

parallel-port PPS cable
masterslave용도
pin 1 `STROBE`pin 10 `ACK`PPS signal
pin 18–25 `GND`pin 18–25 `GND`공통 ground
high→low edgeparallel IRQassert capture
clear edgeIRQ-disabled pollingtime synchronization
`delay=30` 기본30 µslatency와 capture 가능성 절충

Parallel port generator
------------------------

One way to do this is to invent some complicated hardware solutions but it
may be neither necessary nor affordable. The cheap way is to load a PPS
generator on one of the computers (master) and PPS clients on others
(slaves), and use very simple cables to deliver signals using parallel
ports, for example.

Parallel port cable pinout::

        pin        name        master      slave
        1        STROBE          *------     *
        2        D0          *     |     *
        3        D1          *     |     *
        4        D2          *     |     *
        5        D3          *     |     *
        6        D4          *     |     *
        7        D5          *     |     *
        8        D6          *     |     *
        9        D7          *     |     *
        10        ACK          *     ------*
        11        BUSY          *           *
        12        PE          *           *
        13        SEL          *           *
        14        AUTOFD          *           *
        15        ERROR          *           *
        16        INIT          *           *
        17        SELIN          *           *
        18-25        GND          *-----------*

Please note that parallel port interrupt occurs only on high->low transition,
so it is used for PPS assert edge. PPS clear edge can be determined only
using polling in the interrupt handler which actually can be done way more
precisely because interrupt handling delays can be quite big and random. So
current parport PPS generator implementation (pps_gen_parport module) is
geared towards using the clear edge for time synchronization.

Clear edge polling is done with disabled interrupts so it's better to select
delay between assert and clear edge as small as possible to reduce system
latencies. But if it is too small slave won't be able to capture clear edge
transition. The default of 30us should be good enough in most situations.
The delay can be selected using 'delay' pps_gen_parport module parameter.

Intel Timed I/O PPS generator

290-311

Intel Timed I/O는 2019년 이후 Intel CPU에 있는 high-precision device로 PPS signal을 생성할 수 있습니다. Timed I/O와 system time은 같은 hardware clock으로 구동되며 약 20 nanoseconds precision으로 signal을 만듭니다.

전용 Timed I/O pin으로 외부 device에 PPS를 전달해 external clock을 system clock과 동기화합니다. `/sys/class/pps-gen/pps-genx/enable`에 1을 쓰면 생성이 시작되고 0을 쓰면 중지됩니다.

Intel Timed I/O output
Shared hardware clockIntel Timed I/O~20 ns precisionDedicated PPS pinExternal device
`enable = 1`Generate PPS`enable = 0`Stop PPS

system time과 같은 hardware clock을 사용해 외부 device로 정밀 PPS를 보냅니다.

Intel Timed I/O PPS signal generator
------------------------------------

Intel Timed I/O is a high precision device, present on 2019 and newer Intel
CPUs, that can generate PPS signals.

Timed I/O and system time are both driven by same hardware clock. The signal
is generated with a precision of ~20 nanoseconds. The generated PPS signal
is used to synchronize an external device with system clock. For example,
it can be used to share your clock with a device that receives PPS signal,
generated by Timed I/O device. There are dedicated Timed I/O pins to deliver
the PPS signal to an external device.

Usage of Intel Timed I/O as PPS generator:

Start generating PPS signal::

        $echo 1 > /sys/class/pps-gen/pps-genx/enable

Stop generating PPS signal::

        $echo 0 > /sys/class/pps-gen/pps-genx/enable