[LinuxPPS] Advise on kernel documentation
Rodolfo Giometti
giometti at enneenne.com
Wed Feb 7 11:02:43 CET 2007
On Wed, Feb 07, 2007 at 10:21:52AM +0100, Bernhard Schiffner wrote:
>
> BTW: I didn't try the SYSFS. It's possible to do some write there to change
> pps behavior?
> echo 1 > /sys/class/pps/00/echo ?
Currently not.
> --- pps.txt 2007-02-07 10:08:10.000000000 +0100
> +++ pps_4.txt 2007-02-07 10:18:44.000000000 +0100
> @@ -113,7 +113,7 @@
> PPS_CAPTUREASSERT|PPS_OFFSETASSERT,
> -1 /* is up to the system */);
>
> -The linuxpps_register_source() prototipe is:
> +The linuxpps_register_source() prototype is:
>
> int linuxpps_register_source(struct linuxpps_source_info_s *info, int
> default_params, int try_id)
Applied.
> @@ -141,13 +141,13 @@
> PROCFS support
> --------------
>
> -If the PROCFS support is enabled a new directory is created:
> +If PROCFS support is enabled a new directory /proc/pps is created:
>
> $ ls /proc/pps/
> 00 01 sources
Applied.
> The file "sources" holds a brief description of all PPS sources
> -defined into the system:
> +defined in the system:
>
> $ cat /proc/pps/sources
> id mode echo name path
Applied.
> @@ -155,7 +155,7 @@
> 00 1133 no serial0 /dev/ttyS0
> 01 1133 no serial1 /dev/ttyS1
>
> -while other files are directories that hold one or two files according
> +The other entries are directories that hold one or two files according
> to the ability of the associated source to provide "assert" and
> "clear" timestamps:
Applied.
> @@ -163,7 +163,7 @@
> assert clear
>
> Inside each "assert" and "clear" file you can find the timestamp and a
> -sequence number as reported below:
> +sequence number:
>
> $ cat /proc/pps/00/assert
> 1170026870.983207967 #8
Applied.
> @@ -173,25 +173,26 @@
> -------------
>
> The SYSFS support is enabled by default if the SYSFS filesystem is
> -enabled into the kernel and it provides a new class:
> +enabled in the kernel and it provides a new class:
>
> $ ls /sys/class/pps/
> 00/ 01/ 02/
>
> -Each directory is the ID of each PPS sources defined into the system
> -and inside each one you can find several files:
> +Every directory is the ID of a PPS source defined in the system
> +and inside you find several files:
>
> $ ls /sys/class/pps/00/
> assert clear echo mode name path subsystem@ uevent
>
> -Files "assert" and "clear" have the same functionality as the PROCFS
> -alter ego (even if with different syntax due the one-value-per-file
> -sysfs pragma) while other files are:
> +Files "assert" and "clear" have the same functionality as their PROCFS
> +counterparts but with different syntax due to the one-value-per-file
> + sysfs pragma.
> +Other files are:
Applied.
> * echo: reports if the PPS source has an echo function or not;
>
> -* mode: reports available PPS functioning modes (in the same form of
> - PROCFS);
> +* mode: reports available PPS functioning modes (in the same form as
> + PROCFS does);
>
> * name: reports the PPS source's name;
Applied.
All applied! :)
Thanks,
Rodolfo
P.S. I attach the new doc version.
--
GNU/Linux Solutions e-mail: giometti at enneenne.com
Linux Device Driver giometti at gnudd.com
Embedded Systems giometti at linux.it
UNIX programming phone: +39 349 2432127
-------------- next part --------------
PPS - Pulse Per Second
----------------------
(C) Copyright 2007 Rodolfo Giometti <giometti at enneenne.com>
Overview
--------
LinuxPPS provides a programming interface (API) to define into the
system several PPS sources.
PPS means "pulse per second" and a PPS source is just a device who
provides an high and precise signal each second so that an application
can use it to adjust time clock.
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 comes the system must apply to it a timestamp
and record it for the 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 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
usefull beside(!) 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 change the original RFC 2783:
pps_handle_t type is an opaque __scalar type__ used to represent a
PPS source within the API
into a modified:
pps_handle_t type is an opaque __variable__ used to represent a PPS
source within the API and programs should not access it directly to
it due to its opacity.
This change seems to be neglibile because even the original RFC 2783
does not encourage programs to check (read: use) the pps_handle_t
variable before calling the time_pps_*() functions, since each
function should do this job internally.
If I intentionally separate the concept of "file descriptor" from the
concept of the "PPS source" I'm obliged to provide a solution to find
and register a PPS-source without using a file descriptor: it's done
by the functions time_pps_findsource() and time_pps_findpath() now.
According to this current NTPD drivers' code should be modified as
follows:
+#ifdef PPS_HAVE_FINDPATH
+ /* Get the PPS source's real name */
+ fd = readlink(link, path, STRING_LEN-1);
+ if (fd <= 0)
+ strncpy(path, link, STRING_LEN);
+ else
+ path[fd] = '\0';
+
+ /* Try to find the source */
+ fd = time_pps_findpath(path, STRING_LEN, id, STRING_LEN);
+ if (fd < 0) {
+ msyslog(LOG_ERR, "refclock: cannot find PPS source \"%s\" in the system", path);
+ return 1;
+ }
+ msyslog(LOG_INFO, "refclock: found PPS source #%d \"%s\" on \"%s\"", fd, path, id);
+#endif /* PPS_HAVE_FINDPATH */
+
+
if (time_pps_create(fd, &pps_handle) < 0) {
- pps_handle = 0;
msyslog(LOG_ERR, "refclock: time_pps_create failed: %m");
}
Coding example
--------------
To register a PPS source into the kernel you should define a struct
linuxpps_source_info_s as follow:
static struct linuxpps_source_info_s linuxpps_ktimer_info = {
name : "ktimer",
path : "",
mode : PPS_CAPTUREASSERT|PPS_OFFSETASSERT|PPS_ECHOASSERT| \
PPS_CANWAIT|PPS_TSFMT_TSPEC,
echo : linuxpps_ktimer_echo,
};
and then calling the function linuxpps_register_source() in your
intialization routine as follow:
source = linuxpps_register_source(&linuxpps_ktimer_info,
PPS_CAPTUREASSERT|PPS_OFFSETASSERT,
-1 /* is up to the system */);
The linuxpps_register_source() prototype is:
int linuxpps_register_source(struct linuxpps_source_info_s *info, int default_params, int try_id)
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 (is obvious that these parameters
must be a subset of ones defined into the struct
linuxpps_source_info_s which describe the capabilities of the driver)
and "try_id" can be used to force a particular ID for your device into
the system (just use -1 if you wish the system chooses one for you).
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:
linuxpps_event(source, PPS_CAPTUREASSERT, ptr);
The same function may also run the defined echo function
(linuxpps_ktimer_echo(), passing to it the "ptr" pointer) if the user
asked for that... etc..
Please see the file drivers/pps/clients/ktimer.c for an example code.
PROCFS support
--------------
If PROCFS support is enabled a new directory "/proc/pps" is created:
$ ls /proc/pps/
00 01 sources
The file "sources" holds a brief description of all PPS sources
defined in the system:
$ cat /proc/pps/sources
id mode echo name path
---- ------ ---- ---------------- ----------------
00 1133 no serial0 /dev/ttyS0
01 1133 no serial1 /dev/ttyS1
The other entries are directories that hold one or two files according
to the ability of the associated source to provide "assert" and
"clear" timestamps:
$ ls /proc/pps/00
assert clear
Inside each "assert" and "clear" file you can find the timestamp and a
sequence number:
$ cat /proc/pps/00/assert
1170026870.983207967 #8
SYSFS support
-------------
The SYSFS support is enabled by default if the SYSFS filesystem is
enabled in the kernel and it provides a new class:
$ ls /sys/class/pps/
00/ 01/ 02/
Every directory is the ID of each PPS sources defined into the system
and inside you find several files:
$ ls /sys/class/pps/00/
assert clear echo mode name path subsystem@ uevent
Files "assert" and "clear" have the same functionality as their PROCFS
counterparts but with different syntax due the one-value-per-file
sysfs pragma. Other files are:
* echo: reports if the PPS source has an echo function or not;
* mode: reports available PPS functioning modes (in the same form as
PROCFS does);
* 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).
Resources
---------
Wiki: http://wiki.enneenne.com/index.php/LinuxPPS_support and the LinuxPPS
ML: http://ml.enneenne.com/cgi-bin/mailman/listinfo/linuxpps.
More information about the LinuxPPS
mailing list