[U-Boot] [RFC] Review of U-Boot timer API

Wolfgang Denk
2011-05-23T19:18:14Z

Dear "J. William Campbell",

In message <4DDA99BC.80809@comcast.net> you wrote:
>
> >> The library function acts as a pre-scaler using a 'raw tick counter' and a
> >> 'raw tick rate' supplied by the low level architecture. We define this weak
> > What are "raw" ticks? And what are "cooked" ticks, then?
> Hi all,
> FWIW, "cooked" ticks would be 1 ms ticks, although we never
> really use them as such.

Sorry, but I disagree here.

A tick is defined as the smallest increment of system time as measured by a
computer system (see http://en.wikipedia.org/wiki/System_time):

System time is measured by a system clock, which is typically
implemented as a simple count of the number of ticks that have
transpired since some arbitrary starting date, called the
epoch.

There is no such thing as "raw ticks", a tick is inherently "raw" and
needs scaling.

> I have looked at it as a reference. However, there is one disadvantage
> in using the PPC code as a reference. It has a 64 bit timestamp. Many
> systems do not have a 64 bit timestamp, but rather a 32 bit timestamp.
> It is possible to extend the 32 bit timestamp to a 64 bit timestamp if
> get_timer is called often enough that there will only be a single
> rollover of the bottom 32 bits between uses. However, if that condition

Or if there re other methods to detect and handle such a situation. On
many systems, the timer can generate an interrupt, so it would be
trivial enough to implement the handling of this in the interrupt
handler.

> is met, there is no need to extend the timer to 64 bits. Instead, just
> convert the elapsed time since the last call (which you know) to ms and
> be done with it. As Wolfgang said above, any counter that has better
> than 1 ms resolution is adequate to the task. The additional
> requirement that we have stated is that the counter be long enough that
> it does not overflow between calls to get_timer. If the counter is 64

The design should not make any assumptions about when or how often
get_timer() is being called. It should just work :-)

> can get that working in all cases quite easily I think. We can avoid the
> "no divide" optimization until everybody is satisfied with what we have.

We should first get a common API and a working implementation for all
architectures before we consider any optimizations.

<insert quote Donald Knuth about premature optimization>

> That is fine with me. The reason this was being done was to attempt to
> emulate, as much as possible, the power PC, where the 64 bit timestamp
> counter allows calls to get_timer separated by many minutes and several
> console commands to work properly. These get timer commands will NOT
> work properly on systems that have a 32 bit counter that overflows every
> 200 seconds or so. The call in the idle loop was an attempt to make the
> 32 bit systems work more like the 64 bit systems. One may then either

Can you show me any system where it is not possible to implement a 64
bit periodic timer with sufficient resolution?

Please note: even on PowerPC where we have a 64 bit time base
register for free, the timer services are not implemented on this
base. Instead, the interrupt handler for the decrementer will
increment the "timestamp" counter variable (see timer_interrupt() in
arch/powerpc/lib/interrupts.c).

I bet that functionally equivalent code is available on all systems.

Note2: this is a fundamental difference between get_timer() and
udelay(). udelay() has to be available very early, but needs to be
good for a few hundred microsecods or so. get_timer() is a high level
interface that should not suffer from any restrictions.

> 1. Define calls to get_timer to measure an elapsed interval
> separated by any returns to the command processor as broken.

No.

> 2. Require the use of interrupts to extend the 32 bit timestamp.
> (This may not be possible on all systems as the timer used for
> performance monitoring does not interrupt, etc.)

This is definitely an option. It works fine on some systems.
For those systems where it doesn't work, there are probably other
alternatives.

> 3. Allow the call in the idle loop under the assumption that we are
> talking about timing in the minutes range, not a few seconds.

We must not make any such assumptions. Assume someone is running a
standalone application (like some burn-in test software), which runs
for a couple of hours and then returns to U-Boot.

> If get_timer is used to timeout failing hardware operations, the CPU is
> usually in a reasonably tight loop and get_timer will certainly be
> called at least once a minute. In this case, all will be well. If
> get_timer is used to obtain a timestamp during one u-boot command to be
> compared with a timestamp taken by a later command (say inside a
> script), it will not function properly if the total delay (or the delay
> in any one command) exceeds the hardware timer rollover interval. The

get_timer() is defined to return milliseconds. It returns an unsigned
long, so it is good for UINT32_MAX/1000 = 4294967 seconds or more than
49 days before the timer rolls over.

It is up to the architecture specific implementation to warranty such
behaviour. I don't think this is an overly complicated task.

> When you say a "common base", consider that all systems do not have 64
> bit timers, and extending the 32 bit timer that they do have to 64 bits
> in software is not possible if the number of rollovers between calls to
> the timer update routine is unknown. OTOH, if the number of rollovers is

Then let's handle all rollovers? Are there systems out there where we
cannot either have a free runnign 64 bit timer, or cascaded 32 bit
timers, or a timer that is capable of generating interrupts? Does
U-Boot really support any such CPU?

Best regards,

Wolfgang Denk

--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"The pathology is to want control, not that you ever get it, because
of course you never do." - Gregory Bateson