Dear Wolfgang Denk,

what we really need is only a 32 bit monotonous free running tick that 
increments
at a rate of at least 1 MHz. As someone pointed out a while ago, even at 1GHz 
that would
last for four seconds before it rolls over. But a 1HGz counter could be 64 bit 
internally
and always be returned as 32 bits when it is shifted right to bring it into the 
"few" MHz
range.

Any architecture should be able to provide such a 32 bit value. On powerpc that 
would
simply be tbu|tbl shifted right a few bits.

An architecture and SoC specific timer should export 3 functions:

int timer_init(void);
u32 get_tick(void); /* return the current value of the internal free running 
counter */
u32 get_tbclk(void); /* return the rate at which that counter increments (per 
second) */

A generic timer function common to *most* architectures and SoCs would use 
those two
functions to provice udelay() and reset_timer() and get_timer().
Any other timer functions should not be required in u-boot anymore.

However get_timer() and reset_timer() are a bit of a functional problem:

currently reset_timer() does either actually RESET the free running timer 
(BAD!) or
remember its current value in another (gd-)static variable which later is 
subtracted
when get_timer() is called. That precludes the use of several timers 
concurrently.

Also, since the 1000Hz base for that timer is usually derived from get_tick() by
dividing it by some value, the resulting 1000Hz base is not exhausting the 32 
bits
before it wraps to zero.

Therefore I propose two new functions that are to replace reset_timer() and 
get_timer():

u32 init_timeout(u32 timeout_in_ms); /* return the 32 bit tick value when the 
timeout will be */
bool is_timeout(u32 reference); /* return true if reference is in the past */

A timeout loop would therefore be like:

u32 t_ref = timeout_init(3000); /* init a 3 second timeout */

do ... loop ... while (!is_timeout(t_ref));

coarse sketches of those functions:

u32 init_timeout(u32 ms)
{
        return get_ticks() + ((u64)get_tbclk() * (u64)ms) / (u64)1000;
}

bool is_timeout(u32 reference)
{
        return ((int)get_ticks() - (int)reference) > 0;
}

Unfortunately this requires to "fix" all uses of get_timer() and friends, but I 
see no other
long term solution to the current incoherencies.

Comments welcome (and I would provide patches)... 

Reinhard

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to