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

J. William Campbell
2011-05-24T15:23:21Z

On 5/24/2011 7:12 AM, Wolfgang Denk wrote:
> Dear Albert ARIBAUD,
>
> In message<4DDB4C1C.7030301@aribaud.net> you wrote:
>> Not sure I still follow what the two options are -- a heads up is welcome.
>> However, I do like the simplicity in having a single time unit (ticks)
>> for the timer API -- asuming it covers all needs -- and providing other
>> time units only as helper functions.
> I don't think using ticks is a good idea. You would need to change
> all definitiuons of timeouts and delays and such.
>
> Why not using a scaled unit like microsecods or the currently used
> milliseconds?
>
> I wonder why we suddenly have to change everything that has been
> working fine for more than a decade (ignoring the large number of
> incorrect, incomplete or broken implementations). But so far we
> really never needed anything else but udelay() for the typical short
> device related timeouts, and get_time() for longer, often protocol
> defined, timeouts.
>
> Is there anything wrong with these two solutions, based on standard
> units (us and ms) ?
Hi All,
After really looking into this, I think I agree with Wolfgang
that using ms for a get_timer timebase is the best way to go. This
thinking is heavily influenced (in my case anyway) by the fact that in
the interrupt driven cases (and these are the ONLY fully compliant cases
ATM I think), the "cost" of using ms is 0, because that is the "native"
unit in which the timer ticks. This makes everything real simple. We
can, right today, produce an API that supports u32 get_time_ms(void) for
all CPUs in use. This would allow u32 get_timer(u32 base) to continue to
exist as-is. These implementations would still be technically "broken"
in the non-interrupt case, but they would work at least as well as they
presently do. In fact, they would operate better because they would all
use a single routine, not a bunch of different routines (some of which I
am pretty sure have errors). Wolfgang would need to accept the fact that
we are not yet "fixing" all the non-interrupt cases. This needs to be
done, but is a different problem (I hope). In the non-interrupt case
there is some cost in converting to ms from the native units, but we are
in a timout loop, so a few extra instructions do not matter much. It is
only a few 32 bit multiplies, which these days are real fast. If we can
figure out how to use interrupts eventually, even this will go away.

Then, we can ADD an optional performance measuring API like
Scott suggests. This API would be something similar to the following:
struct ticks
{
u32 tickmsb;
u32 ticklsb;
} ;
struct time_value
{
u32 seconds;
u 32 nano_seconds;
};

and the functions would be get_ticks(struct ticks * p) ,
get_tick_delta(struct ticks * minuend, struct ticks * subtrahend),
and cvt_tick_delta(struct time_value * result, struct ticks *input). I
didn't use u64 on purpose, because I don't want any un-necessary
functions pulled from the library. get_ticks reads a "hi precision"
counter. How high the precision is depends on the hardware.
get_tick_delta subtracts two tick values, leaving the difference in the
first operand. Yes, this is may be simple to do in open code but it is
better to hide the details. (What if msb is seconds and lsb is
nanoseconds, then it is not so simple). cvt_tick_delta converts from
ticks to seconds and nano_seconds. We also need a u32
get_tick_resolution, which would return the tick resolution in ns. The
user never needs to do any arithmetic on ticks, so that makes his life
much easier. However, the user may want to know the resolution of these
measurements. All these functions are quite fast except possibly
cvt_tick_delta, which is only needed for printing anyway.
If the hardware has a performance monitoring counter,
implementing these functions is quite simple. The PPC and the x86
certainly do (well, any x86 pentium and above anyway). This is a whole
lot of chips off our plate. In cases where no such counter exists, we
will use whatever counters there are available already. Some of the ARM
counters are running at 32 kHz, so their resolution won't be great, but
it is what it is. If we find out that some of these other CPUs have a
performance counter, we will use it. This API will be completely
optional in u-boot and can be removed by changing a #define.
Thoughts welcome.

Best Regards,
Bill Campbell

> Best regards,
>
> Wolfgang Denk
>