[U-Boot] Timer implementations
Nishanth Menon
nm at ti.com
Tue Oct 26 17:11:45 CEST 2010
Reinhard Meyer had written, on 10/26/2010 02:57 AM, the following:
> Wolfgang Denk schrieb:
>> Dear Reinhard Meyer,
>>
>> In message <4CC67CA1.9090302 at emk-elektronik.de> you wrote:
>>> If implemented with true 64 bits for get_ticks() that function is useable
>>> for timeout programming:
>>>
>>> ulong timeval = get_timer (0);
>>>
>>> do {
>>> ...
>>> } while (get_timer (timeval) < TIMEOUT);
>>>
>>> It appears that the "base" parameter and return value is in CONFIG_SYS_HZ
>>> units, and not in native ticks. That causes 64 bit mul/div every
>>> time get_timer() is called. Won't hurt in a timeout loop, though.
>> But it will hurt in othe rplaces.
>>
>> Also, this code _is_ a bit different, as "get_timer(0)" makes sure
>> the counter starts ticking again at 0
>
> Nope, it does not reset the counter itself. It returns the current
> counter value (recalculated into CONFIG_SYS_HZ units).
> Maybe you mean reset_timer() instead?
>
> In arm9226ejs/omap/timer.c udelay() is implemented with reset_timer()
> and get_timer(). Since those functions are inherently not nestable,
> beware of base=get_timer(0); do { ... udelay(xx); ... } while (get_timer(base) < TIMEOUT);
> constructs!
At least the omap3+ code arch/arm/cpu/armv7/omap-common/timer.c
__udelay() does'nt seem to reset the timer
BUT,
unsigned long long get_ticks(void)
{
return get_timer(0);
}
ulong get_timer(ulong base)
{ return get_timer_masked() - base;
}
ulong get_timer_masked(void)
{
/* current tick value */
ulong now = readl(&timer_base->tcrr) / (TIMER_CLOCK /
CONFIG_SYS_HZ);
if (now >= lastinc) /* normal mode (non roll) */
/* move stamp fordward with absoulte diff ticks */
timestamp += (now - lastinc);
else /* we have rollover of incrementer */
timestamp += ((TIMER_LOAD_VAL / (TIMER_CLOCK /
CONFIG_SYS_HZ))
- lastinc) + now;
lastinc = now;
return timestamp;
}
if I am not mistaken, this is 32bit long.. but since we have as wdenk
mentions below a 2^32 tick duration, we can safely go with an option
such as:
/* If we fail after 1 second wait, something is really bad */
#define MAX_RETRY_US (1 * 1000 * 1000)
uint64_t etime; /* actually this could be u32 */
etime = get_ticks() + usec2ticks(MAX_RETRY_US);
while (!(readl(&mmc_base->stat) & CC_MASK)) {
if (get_ticks() <= etime) {
printf("%s: timedout waiting for cc2!\n", __func__);
return;
}
}
sounds right?
>
>> , and get_timer() is defined to
>> have millisecond resolution.
>
> Actually CONFIG_SYS_HZ (whatever that is).
>
>> So you have a guaranteed 2^32
>> milliseconds or 4294967 seconds or about 3.3 years available which
>> indeed should be sufficient to implement standard timeouts.
>
> I think it is necessary to summarize all implicit or explicit documented
> "defined to have's" regarding the timer and then to verify that all
> implementations adhere to them.
>
yes indeed.. :(
--
Regards,
Nishanth Menon
More information about the U-Boot
mailing list