On Mon, Apr 17, 2006 at 05:09:02PM -0000, Jesse Off wrote:
> > I have been testing this timer using the example code, and find the
> > speed, at least on the 7260 I have to be close to 983.285 Khz.
>
> The speed is 983040, exactly. It is the external 14.7456Mhz crystal
> input divided by 15. All you should have is the 50PPM error in the
> 14 Mhz crystal. The Linux system tick (and gettimeofday()),
> however, is much less accurate. Linux wants a precise 100.0Hz
> system tick which cannot be arrived at perfectly from the ep93xx
> timing hardware. All we can get is something like 100.09Hz (I can't
> recall exactly what it is)
This is how the ep93xx timer interrupt is currently implemented in
linux 2.6:
static unsigned int last_jiffy_time;
#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
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;
timer_tick(regs);
}
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
Coding it this way, it doesn't matter all that much whether the 100Hz
timer is 100.000Hz, 101Hz, or even 200Hz -- in the 200Hz case it'll
only call timer_tick() on every second timer interrupt.
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.
For reference, gettimeoffset is implemented as follows:
static unsigned long ep93xx_gettimeoffset(void)
{
int offset;
offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
/* Calculate (1000000 / 983040) * offset. */
return offset + (53 * offset / 3072);
}
cheers,
Lennert
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/
|