[U-Boot] Timer implementations

Reinhard Meyer u-boot at emk-elektronik.de
Tue Oct 26 15:33:38 CEST 2010


Dear Wolfgang Denk,
>> Then the define CONFIG_SYS_HZ should not be in every <board>.h since that
>> suggests that a board developer has some freedom there...
> 
> Agreed - there are historical reasons this has ever been changable at
> all.
> 
>> and MOST IMPORTANT that some implementations of udelay() might
>> call reset_timer() and therefore break an outer timeout loop !!!
> 
> Such implementations are inherently broken and need to be fixed.

Found such in arm926ejs/omap... But then, that timer is multiple-broken:
relocation broken (uses static data), returns 32 a bit value in get_ticks(),
returns CONFIG_SYS_HZ in get_tbclk() instead of the rate get_ticks()
increments...

PXA:
void udelay_masked (unsigned long usec)
{
	unsigned long long tmp;
	ulong tmo;

	tmo = us_to_tick(usec);
	tmp = get_ticks() + tmo;	/* get current timestamp */

	while (get_ticks() < tmp)
		/* loop till event _OR FOREVER is tmp happens to be > 32 bit_ */
		 /*NOP*/;

}

unsigned long long get_ticks(void)
{
	return readl(OSCR);
}
- not any better :( -- its the same code that AT91 had before I fixed it.

> 
>> It is also open if reset_timer() does actually reset the hardware timer
>> (e.g. tbu/tbl at PPC) - which would be messing up any time difference
>> calculation using get_ticks() - or does emulate that by remembering
>> the hardware value and subtracting it later in every subsequent
>> get_timer() call?
> 
> This is an implementation detail.

IF we require that get_ticks() and get_timer() shall not interfere with
each other and IF both are based on the same hardware timer only the
second method is available (same if the hardware timer is not easyly
resettable).

>> 2. get_ticks() and friends operate at a higher rate (tbu/tbl for PPC).
>> Since they are defined as having 64 bits they MUST not wrap at 32 bits,
>> i.e. if the hardware provides only 32 bits, the upper 32 bits must be
>> emulated by software.
> 
> Right.
> 
>> Otherwise we have to document that get_ticks() cannot be used to get
>> 64 bit time differences.
> 
> No. Such an implementation is broken and needs fixing.

Original AT91 timer.c was like that, and I think other ARMs where this was
copied around should be looked at... I don't know when get_timer() became
64 bits, but it seems that some implementations just did change the return
type: uint64 get_timer(void) {return (uint64)timer_val_32;}

> 
>> If you really closely look at the various implementations of those
>> timers, you will easyly see the wide variations implemented there.
> 
> Yes, I am aware of this :-(

I will start beautifying the AT91 timer - its already quite there,
except for a possible timer wrap problem in udelay() after a few billion
years :)

Best Regards,
Reinhard


More information about the U-Boot mailing list