[LinuxPPS] delay through the irq code

Rodolfo Giometti giometti at enneenne.com
Mon Apr 14 09:04:18 CEST 2008


On Sun, Apr 13, 2008 at 09:47:29AM +1000, James Boddington wrote:
> Rodolfo Giometti wrote:
>> First of all let's see this message:
>>    http://lkml.org/lkml/2008/4/10/312
>> then we should consider that Linux is a complex system and we cannot
>> put our code where we wish... your solution is better then current
>> one, I agree, but we should find a good way to implement it into Linux
>> code, otherwise PPS support will remain a patch forever. :'(
>
> Saw the comment about using entry*.S. I am now using do_IRQ() which is what 
> entry_32.S calls.
>
>> Can you please show us your modifications?
>
> You will notice xjb_ used a lot. Those 3 letters mean something to me and 
> are easy to search for.
>
> xjb.patch is what I have done on top of linuxpps
> timex.h is my /usr/include/sys/timex.h
> ktimer.patch has ktimer.c using my pps_event_user() instead of pps_event().
>
> The modified user space timex.h allows ntp to compile with nano instead of 
> micro support.
>
> I get a time stamp in do_IRQ() if irq == 4. If we get through the serial 
> code checks for dcd assert/clear and make it to pps_event() it is a time 
> stamp for the correct event. I have pps_event() save the do_IRQ() time 
> stamp for later use if the event is an assert. pps_event() then sets the 
> time for pps0 as per normal.

This is an interesting solution... of course it cannot be used as is
due the "irq == 4" code etc.. However you can do something different,
you can put into do_IRQ() a special array (named for instance
pps_irq_timestamps[]) which holds all IRQs timestamps, then you can
use these values later into serial_core into pps_event()! :)

> Made a copy of pps_event() called pps_event_user(). It accepts a time stamp 
> as an argument and uses that instead of getnstimeday(). As ktimer.c already 
> provides the functionality to register a new pps source and update it every 
> second I modified ktimer.c to use pps_event_user() + my time stamp.
>
> This was written with only my case in mind of 1 pps source on ttyS0. The 
> final result is pps0 with the normal linuxpps time stamp and pps1 (via 
> ktimer) with the do_IRQ() time stamp.

This is a "work-around" in order to not use serial_core code... but
I'm not sure it could be the right solution. Maybe we can add a special
ldisc which register/deregister the pps source and then use the trick above to
report pps timestamps!

> kernel/time/ntp.c is modified based on the nano changes in the -mm kernel. 
> do_adjtimex() will use a micro or nano offset determined by STA_NANO.
>
> Some quick code in do_adjtimex() to set whether the offset provided by ntp 
> is used or if the last pps time stamp is used (for me pps1). This means if 
> I use 'cat /dev/ttyS0' the kernel can sync to the correct time without ntp 
> running.

This is not clear to me, but it seems to me a new functionality... can
you please provide a patch which implements only these modifications?

> Again in do_adjtimex() I can allow the normal kernel time constant to be 
> used or I can override it. At the moment I like ntp doing all the filtering 
> with a long time constant (10) and the kernel being able to react quickly 
> with a small time constant (1)

Provide a patch please.

> Have another kernel module that exports a few things for me in /proc. 

Please, don't use /proc which is deprecated, use /sysfs instaed.

> Allows me to set whether ntp or pps is used at run time. Can change the 
> time constant at run time. Also exported are the do_IRQ() time stamp, 
> offset from that time stamp, last offset that do_adjtime() used, difference 
> between the 2 offsets, current kernel time constant and which offset 
> do_adjtimex() is using ntp/pps.

Again, provide a patch please.

> I found with do_adjtimex() being fed a nano offset instead of micro offset 
> it has finer control. Smaller changes to the current frequency can be made.
>
> The lower level time stamp is more resistant to cpu load. My ntp server is 
> running gentoo and had some updates to do yesterday. I captured the 
> following graph while recompiling strace. 
> http://aiken.dnsalias.org/irq-pps-cpu.png
>
>  ntp_gettime() returns code 0 (OK)
>   time cbabc72e.00302b40  Sun, Apr 13 2008  9:41:34.000, (.000735584),
>   maximum error 7173 us, estimated error 0 us
> ntp_adjtime() returns code 0 (OK)
>   modes 0x0 (),
>   offset -0.246 us, frequency 0.782 ppm, interval 1 s,
>   maximum error 7173 us, estimated error 0 us,
>   status 0x2001 (PLL,NANO),
>   time constant 1, precision 0.001 us, tolerance 512 ppm,
>
>> However consider the fact that all these problems arise because the
>> DCD pin is just a weak solution. Better hardware solution is using a
>> dedicated CPU pin for PPS signal... in this case you can provide a
>> special PPS client which can be directly executed by
>> handle_IRQ_event() (or better, I'm just thinking at Fast IRQ on ARM
>> systems - see linux/arch/arm/kernel/fiq.c).
>
> DCD or parallel is all I have. I like the idea of access to a better way of 
> time stamping the pps but have to go with what I have.

You got a really interesting solution! However, please, help me in not
rewriting the code each time. You should provide a patch for each new
functionality so I can prepare specific patches for kernel inclusion.

Currently the new solution could be (in this order):

1) implementing the pps_irqs_timestamps[] array support.

2) adding a new ldisc which create the pps source according to the
serial port configuration (irq number).

Please, do these modifications on top of the GIT repository providing
the new patches into this list for review.

These will enhance the PPS accuracy and resolve the serial issue
arised by Alan! :)

Thanks for your help,

Rodolfo

-- 

GNU/Linux Solutions                  e-mail:    giometti at enneenne.com
Linux Device Driver                             giometti at linux.it
Embedded Systems                     phone:	+39 349 2432127
UNIX programming                     skype:     rodolfo.giometti



More information about the LinuxPPS mailing list