ts-7000
[Top] [All Lists]

Re: [ts-7000] Re: 983.04 Khz timer

To:
Subject: Re: [ts-7000] Re: 983.04 Khz timer
From: Lennert Buytenhek <>
Date: Thu, 20 Apr 2006 00:23:47 +0200
On Wed, Apr 19, 2006 at 06:44:26PM +0200, Lennert Buytenhek wrote:

> I was being lazy when I implemented this, and so the 983040/HZ division
> error will still cause some drift, but this should be easy enough to
> compensate for -- just do the TIMER4_TICKS_PER_JIFFY division as a round-
> to-zero instead of round-nearest division, and increment a separate
> accumulator by 983040 % HZ on every timer tick, and when that accumulator
> goes >= HZ, increment next_jiffy_time by one.  I'll just code that up
> right now and see if it works.

Sorry, didn't have much time today.  The patch below (against
2.6.17-rc2) should in theory (untested) make linux timekeeping as
accurate as possible, limited only by accuracy of the hardware.

Attached to this email is a small simulation program (blah.c) that
kind of sort of demonstrates that the algorithm is correct.  But of
course, someone will still have to verify it in practise.  :-)


cheers,
Lennert


diff -urN linux-2.6.17-rc2.orig/arch/arm/mach-ep93xx/core.c 
linux-2.6.17-rc2/arch/arm/mach-ep93xx/core.c
--- linux-2.6.17-rc2.orig/arch/arm/mach-ep93xx/core.c   2006-04-19 
21:54:41.000000000 +0200
+++ linux-2.6.17-rc2/arch/arm/mach-ep93xx/core.c        2006-04-20 
00:10:49.000000000 +0200
@@ -95,18 +95,32 @@
  * track of lost jiffies.
  */
 static unsigned int last_jiffy_time;
+static unsigned int next_jiffy_time;
+static unsigned int accumulator;
 
-#define TIMER4_TICKS_PER_JIFFY         ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
+#define TIMER4_TICKS_PER_JIFFY         (CLOCK_TICK_RATE / HZ)
+#define TIMER4_TICKS_MOD_JIFFY         (CLOCK_TICK_RATE % HZ)
+
+static int after_eq(unsigned long a, unsigned long b)
+{
+       return ((signed long)(a - b)) >= 0;
+}
 
 static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        write_seqlock(&xtime_lock);
 
        __raw_writel(1, EP93XX_TIMER1_CLEAR);
-       while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time
-                                               >= TIMER4_TICKS_PER_JIFFY) {
-               last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
+       while (after_eq(__raw_readl(EP93XX_TIMER4_VALUE_LOW), next_jiffy_time)) 
{
                timer_tick(regs);
+
+               last_jiffy_time = next_jiffy_time;
+               next_jiffy_time += TIMER4_TICKS_PER_JIFFY;
+               accumulator += TIMER4_TICKS_MOD_JIFFY;
+               if (accumulator >= HZ) {
+                       next_jiffy_time++;
+                       accumulator -= HZ;
+               }
        }
 
        write_sequnlock(&xtime_lock);
@@ -124,7 +138,7 @@
 {
        /* Enable periodic HZ timer.  */
        __raw_writel(0x48, EP93XX_TIMER1_CONTROL);
-       __raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD);
+       __raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD);
        __raw_writel(0xc8, EP93XX_TIMER1_CONTROL);
 
        /* Enable lost jiffy timer.  */


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/ts-7000/

<*> To unsubscribe from this group, send an email to:
    

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 

Attachment: blah.c
Description: Text document

<Prev in Thread] Current Thread [Next in Thread>
Admin

Disclaimer: Neither Andrew Taylor nor the University of NSW School of Computer and Engineering take any responsibility for the contents of this archive. It is purely a compilation of material sent by many people to the birding-aus mailing list. It has not been checked for accuracy nor its content verified in any way. If you wish to get material removed from the archive or have other queries about the archive e-mail Andrew Taylor at this address: andrewt@cse.unsw.EDU.AU