diff options
Diffstat (limited to 'Documentation/pps')
-rw-r--r-- | Documentation/pps/pps.txt | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/Documentation/pps/pps.txt b/Documentation/pps/pps.txt new file mode 100644 index 000000000000..125f4ab48998 --- /dev/null +++ b/Documentation/pps/pps.txt | |||
@@ -0,0 +1,172 @@ | |||
1 | |||
2 | PPS - Pulse Per Second | ||
3 | ---------------------- | ||
4 | |||
5 | (C) Copyright 2007 Rodolfo Giometti <giometti@enneenne.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | |||
18 | |||
19 | Overview | ||
20 | -------- | ||
21 | |||
22 | LinuxPPS provides a programming interface (API) to define in the | ||
23 | system several PPS sources. | ||
24 | |||
25 | PPS means "pulse per second" and a PPS source is just a device which | ||
26 | provides a high precision signal each second so that an application | ||
27 | can use it to adjust system clock time. | ||
28 | |||
29 | A PPS source can be connected to a serial port (usually to the Data | ||
30 | Carrier Detect pin) or to a parallel port (ACK-pin) or to a special | ||
31 | CPU's GPIOs (this is the common case in embedded systems) but in each | ||
32 | case when a new pulse arrives the system must apply to it a timestamp | ||
33 | and record it for userland. | ||
34 | |||
35 | Common use is the combination of the NTPD as userland program, with a | ||
36 | GPS receiver as PPS source, to obtain a wallclock-time with | ||
37 | sub-millisecond synchronisation to UTC. | ||
38 | |||
39 | |||
40 | RFC considerations | ||
41 | ------------------ | ||
42 | |||
43 | While implementing a PPS API as RFC 2783 defines and using an embedded | ||
44 | CPU GPIO-Pin as physical link to the signal, I encountered a deeper | ||
45 | problem: | ||
46 | |||
47 | At startup it needs a file descriptor as argument for the function | ||
48 | time_pps_create(). | ||
49 | |||
50 | This implies that the source has a /dev/... entry. This assumption is | ||
51 | ok for the serial and parallel port, where you can do something | ||
52 | useful besides(!) the gathering of timestamps as it is the central | ||
53 | task for a PPS-API. But this assumption does not work for a single | ||
54 | purpose GPIO line. In this case even basic file-related functionality | ||
55 | (like read() and write()) makes no sense at all and should not be a | ||
56 | precondition for the use of a PPS-API. | ||
57 | |||
58 | The problem can be simply solved if you consider that a PPS source is | ||
59 | not always connected with a GPS data source. | ||
60 | |||
61 | So your programs should check if the GPS data source (the serial port | ||
62 | for instance) is a PPS source too, and if not they should provide the | ||
63 | possibility to open another device as PPS source. | ||
64 | |||
65 | In LinuxPPS the PPS sources are simply char devices usually mapped | ||
66 | into files /dev/pps0, /dev/pps1, etc.. | ||
67 | |||
68 | |||
69 | Coding example | ||
70 | -------------- | ||
71 | |||
72 | To register a PPS source into the kernel you should define a struct | ||
73 | pps_source_info_s as follows: | ||
74 | |||
75 | static struct pps_source_info pps_ktimer_info = { | ||
76 | .name = "ktimer", | ||
77 | .path = "", | ||
78 | .mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \ | ||
79 | PPS_ECHOASSERT | \ | ||
80 | PPS_CANWAIT | PPS_TSFMT_TSPEC, | ||
81 | .echo = pps_ktimer_echo, | ||
82 | .owner = THIS_MODULE, | ||
83 | }; | ||
84 | |||
85 | and then calling the function pps_register_source() in your | ||
86 | intialization routine as follows: | ||
87 | |||
88 | source = pps_register_source(&pps_ktimer_info, | ||
89 | PPS_CAPTUREASSERT | PPS_OFFSETASSERT); | ||
90 | |||
91 | The pps_register_source() prototype is: | ||
92 | |||
93 | int pps_register_source(struct pps_source_info_s *info, int default_params) | ||
94 | |||
95 | where "info" is a pointer to a structure that describes a particular | ||
96 | PPS source, "default_params" tells the system what the initial default | ||
97 | parameters for the device should be (it is obvious that these parameters | ||
98 | must be a subset of ones defined in the struct | ||
99 | pps_source_info_s which describe the capabilities of the driver). | ||
100 | |||
101 | Once you have registered a new PPS source into the system you can | ||
102 | signal an assert event (for example in the interrupt handler routine) | ||
103 | just using: | ||
104 | |||
105 | pps_event(source, &ts, PPS_CAPTUREASSERT, ptr) | ||
106 | |||
107 | where "ts" is the event's timestamp. | ||
108 | |||
109 | The same function may also run the defined echo function | ||
110 | (pps_ktimer_echo(), passing to it the "ptr" pointer) if the user | ||
111 | asked for that... etc.. | ||
112 | |||
113 | Please see the file drivers/pps/clients/ktimer.c for example code. | ||
114 | |||
115 | |||
116 | SYSFS support | ||
117 | ------------- | ||
118 | |||
119 | If the SYSFS filesystem is enabled in the kernel it provides a new class: | ||
120 | |||
121 | $ ls /sys/class/pps/ | ||
122 | pps0/ pps1/ pps2/ | ||
123 | |||
124 | Every directory is the ID of a PPS sources defined in the system and | ||
125 | inside you find several files: | ||
126 | |||
127 | $ ls /sys/class/pps/pps0/ | ||
128 | assert clear echo mode name path subsystem@ uevent | ||
129 | |||
130 | Inside each "assert" and "clear" file you can find the timestamp and a | ||
131 | sequence number: | ||
132 | |||
133 | $ cat /sys/class/pps/pps0/assert | ||
134 | 1170026870.983207967#8 | ||
135 | |||
136 | Where before the "#" is the timestamp in seconds; after it is the | ||
137 | sequence number. Other files are: | ||
138 | |||
139 | * echo: reports if the PPS source has an echo function or not; | ||
140 | |||
141 | * mode: reports available PPS functioning modes; | ||
142 | |||
143 | * name: reports the PPS source's name; | ||
144 | |||
145 | * path: reports the PPS source's device path, that is the device the | ||
146 | PPS source is connected to (if it exists). | ||
147 | |||
148 | |||
149 | Testing the PPS support | ||
150 | ----------------------- | ||
151 | |||
152 | In order to test the PPS support even without specific hardware you can use | ||
153 | the ktimer driver (see the client subsection in the PPS configuration menu) | ||
154 | and the userland tools provided into Documentaion/pps/ directory. | ||
155 | |||
156 | Once you have enabled the compilation of ktimer just modprobe it (if | ||
157 | not statically compiled): | ||
158 | |||
159 | # modprobe ktimer | ||
160 | |||
161 | and the run ppstest as follow: | ||
162 | |||
163 | $ ./ppstest /dev/pps0 | ||
164 | trying PPS source "/dev/pps1" | ||
165 | found PPS source "/dev/pps1" | ||
166 | ok, found 1 source(s), now start fetching data... | ||
167 | source 0 - assert 1186592699.388832443, sequence: 364 - clear 0.000000000, sequence: 0 | ||
168 | source 0 - assert 1186592700.388931295, sequence: 365 - clear 0.000000000, sequence: 0 | ||
169 | source 0 - assert 1186592701.389032765, sequence: 366 - clear 0.000000000, sequence: 0 | ||
170 | |||
171 | Please, note that to compile userland programs you need the file timepps.h | ||
172 | (see Documentation/pps/). | ||