This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
technical_information [2018/08/29 16:06] giometti created |
technical_information [2025/02/24 10:02] (current) giometti [Parallel port generator] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== RFC considerations ====== | + | ====== Technical Information ====== |
+ | |||
+ | ===== RFC considerations ===== | ||
While implementing a PPS API as RFC 2783 defines and using an embedded | While implementing a PPS API as RFC 2783 defines and using an embedded | ||
Line 26: | Line 28: | ||
into files ''/dev/pps0'', ''/dev/pps1'', etc. | into files ''/dev/pps0'', ''/dev/pps1'', etc. | ||
- | ====== PPS with USB to serial devices ====== | + | ===== PPS with USB to serial devices ===== |
It is possible to grab the PPS from an USB to serial device. However, | It is possible to grab the PPS from an USB to serial device. However, | ||
Line 42: | Line 44: | ||
ch341 and pl2303 examples). | ch341 and pl2303 examples). | ||
- | ====== Coding example ====== | + | ===== Coding example ===== |
To register a PPS source into the kernel you should define a ''struct | To register a PPS source into the kernel you should define a ''struct | ||
Line 87: | Line 89: | ||
Please see the file ''drivers/pps/clients/pps-ktimer.c'' for example code. | Please see the file ''drivers/pps/clients/pps-ktimer.c'' for example code. | ||
- | ====== SYSFS support ====== | + | ===== SYSFS support ===== |
If the SYSFS filesystem is enabled in the kernel it provides a new class: | If the SYSFS filesystem is enabled in the kernel it provides a new class: | ||
Line 117: | Line 119: | ||
PPS source is connected to (if it exists). | PPS source is connected to (if it exists). | ||
- | ====== Testing the PPS support ====== | + | ===== Testing the PPS support ===== |
In order to test the PPS support even without specific hardware you can use | In order to test the PPS support even without specific hardware you can use | ||
Line 142: | Line 144: | ||
This is available in the **pps-tools** repository mentioned above. | This is available in the **pps-tools** repository mentioned above. | ||
- | ====== Generators ====== | + | ===== Generators ===== |
Sometimes one needs to be able not only to catch PPS signals but to produce | 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 | them also. For example, running a distributed simulation, which requires | ||
- | computers' clock to be synchronized very tightly. One way to do this is to | + | computers' clock to be synchronized very tightly. |
- | 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: | + | To do so the class pps-gen has been added. PPS generators can be |
- | pin name master slave | + | registered in the kernel by defining a ''struct pps_gen_source_info'' as |
- | 1 STROBE *------ * | + | follows: |
- | 2 D0 * | * | + | |
- | 3 D1 * | * | + | static struct pps_gen_source_info pps_gen_dummy_info = { |
- | 4 D2 * | * | + | .name = "dummy", |
- | 5 D3 * | * | + | .use_system_clock = true, |
- | 6 D4 * | * | + | .get_time = pps_gen_dummy_get_time, |
- | 7 D5 * | * | + | .enable = pps_gen_dummy_enable, |
- | 8 D6 * | * | + | }; |
- | 9 D7 * | * | + | |
- | 10 ACK * ------* | + | Where the ''use_system_clock'' states if the generator uses the system |
- | 11 BUSY * * | + | clock to generate its pulses, or they are from a peripheral device |
- | 12 PE * * | + | clock. Method ''get_time()'' is used to query the time stored into the |
- | 13 SEL * * | + | generator clock, while the method ''enable()'' is used to enable or |
- | 14 AUTOFD * * | + | disable the PPS pulse generation. |
- | 15 ERROR * * | + | |
- | 16 INIT * * | + | Then calling the function ''pps_gen_register_source()'' in your |
- | 17 SELIN * * | + | initialization routine as follows creates a new generator in the |
- | 18-25 GND *-----------* | + | system: |
+ | |||
+ | pps_gen = pps_gen_register_source(&pps_gen_dummy_info); | ||
+ | |||
+ | ===== 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 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, | Please note that parallel port interrupt occurs only on high->low transition, | ||
Line 177: | Line 224: | ||
using polling in the interrupt handler which actually can be done way more | 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 | precisely because interrupt handling delays can be quite big and random. So | ||
- | current parport PPS generator implementation (''pps_gen_parport'' module) is | + | current parport PPS generator implementation (pps_gen_parport module) is |
geared towards using the clear edge for time synchronization. | geared towards using the clear edge for time synchronization. | ||
Line 184: | Line 231: | ||
latencies. But if it is too small slave won't be able to capture clear edge | 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. | transition. The default of 30us should be good enough in most situations. | ||
- | The delay can be selected using ''delay'' ''pps_gen_parport'' module parameter. | + | The delay can be selected using ''delay'' pps_gen_parport module parameter. |
+ |