nios2: Reload timer count in reset_timer()

When the timestamp is incremented via interrupt and the interrupt
   period is greater than 1 msec, successive calls to get_timer() can
   produce inaccurate timing since the interrupts are asynchronous
   to the timing loop. For example, with an interrupt period of 10 msec
   two successive calls to get_timer() could indicate an elapsed time
   of 10 msec after only several hundred usecs -- depending on when
   the next interrupt actually occurs. This behavior can cause
   reliability issues with components such as CFI and NAND.

   This can be remedied by calling reset_timer() prior to establishing
   the base timestamp with get_timer(0), provided reset_timer()
   resets the hardware timer (rather than simply resetting only the
   timestamp). This has the effect of synchronizing the interrupts
   (and the advance of the timestamp) with the timing loop.

Signed-off-by: Scott McNutt <smcnutt@psyent.com>
This commit is contained in:
Scott McNutt 2010-04-01 00:00:56 -04:00
parent ed29415784
commit d8bc0a2889
1 changed files with 33 additions and 0 deletions

View File

@ -56,7 +56,40 @@ volatile ulong timestamp = 0;
void reset_timer (void)
{
nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE;
/* From Embedded Peripherals Handbook:
*
* "When the hardware is configured with Writeable period
* disabled, writing to one of the period_n registers causes
* the counter to reset to the fixed Timeout Period specified
* at system generation time."
*
* Here we force a reload to prevent early timeouts from
* get_timer() when the interrupt period is greater than
* than 1 msec.
*
* Simply write to periodl with its own value to force an
* internal counter reload, THEN reset the timestamp.
*/
writel (readl (&tmr->periodl), &tmr->periodl);
timestamp = 0;
/* From Embedded Peripherals Handbook:
*
* "Writing to one of the period_n registers stops the internal
* counter, except when the hardware is configured with Start/Stop
* control bits off. If Start/Stop control bits is off, writing
* either register does not stop the counter."
*
* In order to accomodate either configuration, the control
* register is re-written. If the counter is stopped, it will
* be restarted. If it is running, the write is essentially
* a nop.
*/
writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START,
&tmr->control);
}
ulong get_timer (ulong base)