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

Graeme Russ
2011-05-25T06:02:51Z

Hi Wolfgang

On Wed, May 25, 2011 at 3:25 PM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Graeme Russ,
>
> In message <BANLkTinK+bxtZ+sumYZtvuHcd_Ft+jfyPw@mail.gmail.com> you wrote:
>>
>> > Yes, but without any guarantee for accuracy or resolution.
>> > This is good enough for timeouts, but nothing for time measurements.
>>
>> Out of curiosity, are there any platforms that do not use their most
>> accurate source(*) as the timebase for get_timer()? If a platform is using
>> it's most accurate, commonly available, source for get_timer() the the
>> whole accuracy argument is moot - You can't get any better anyway so
>> why sweat the details.
>
> Actually most boards do that, at least most of those who have a RTC
> chip on board. ?Almost always these RTCs provide much better accuracy
> than the system clock used for the CPU-internal timers. ?In an OS like
> Linux you will frequently see NTP being used to keep the system time
> in sync with the more accurate RTC (and eventually other, external
> time sources)

Well, I think we can leave NTP out of the picture for U-Boot - What I am
really getting at is are the time bases for udelay() and get_timer() the
same, and are they always the most accurate which is readily available
to U-Boot.

I am thinking the answer is not always 'Yes' as udelay() is needed before
relocation and therefore may only have access to a poor-man's time base
(using port-mapped I/O to force wait-states on the x86 for example)

>> (*)I'm actually referring to what is commonly available for that platform,
>> and not where a board has a high precision/accuracy source in addition to
>> the common source.
>
> I'm not sure what you mean here. ?Quite frequently even SoCs have a
> number of different clock sources, say a master clock which is used to
> derive the processor clock, and a 32768 Hz clock which is used to
> drive a SoC-internal RTC.

The eNET board for example has a microsecond counter in the FPGA which is
independently clocked to the CPU

>> As a followup question, how many platforms use two completely independent
>> sources for udelay() and get_timer() - x86 does, but I plan to change this
>> so the interrupt kicks the new prescaler which can be done at >> 1ms period
>> and udelay() and get_timer() will use the same tick source and therefore
>> have equivalent accuracy.
>
> Define "completely independent" - on PowerPC one uses the timebase
> register, while the other uses the decrementer. But in the end, both
> of them are most likely derived from the same system clock (or not
> - depending on SoC design). ?But this does not matter at all.

I mean udelay() clocked by a tick counter and get_timer() clocked by
an interrupt versus both being clocked by the same phyiscal tick counter
(even though both are clocked by the same on-board xtal)

>> Hmmm, I think it is worthwhile at least comparing the two - What is the
>> lesser of two evils
>>
>> ?1. Exposing 'ticks' through a HAL for the prescaler
>> ?2. Duplicating a function with identical code 50+ times across the source
>> ? ? tree
>
> If it's identical code, all these implementations can share common
> code, right?

Yes

>> I personally think #2 is way worse - The massive redundant duplication and
>> blind copying of code is what has get us into this (and many other) messes
>
> That don;t do it, and use common code for this.

But to do that, I need to make get_ticks() non static so the prescaler can
access the tick counter

>> > Currently we have unsigned long long get_ticks(void) =A0which is better
>> > as it matches existing hardware.
>>
>> Matches PPC - Does it match every other platform? I know it does not match
>> the sc520 which has a 16-bit millisecond and a 16-bit microsecond counter
>> (which only counts to 999 before resetting to 0)
>>
>> Don't assume every platform can implement a 64-bit tick counter. But yes,
>> we should cater for those platforms that can
>
> There are counters of many different sizes around. You cannot squeeze
> a bigger counter into a smaller data ubit, but you can easily stick
> smaller data into a bigger container. So it seems most natural to me
> to chose that data type that fits all, i. e. a bigger one.

Putting the smaller counter into a larger bit space causes problems because
it wraps to "All 0's" before it gets to "All 1's" - This makes a simple
unsigned 'current - last' calculation fail at the rollover point. The same
problem does not occur if you truncate a larger counter into a smaller bit
space

Regards,

Graeme