[U-Boot] TIMER cleanup RFC, was: [PATCH 4/4] arm920t/at91/timer: replace bss variables by gd

Reinhard Meyer u-boot at emk-elektronik.de
Tue Nov 30 10:14:20 CET 2010


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



More information about the U-Boot mailing list