All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC] Review of U-Boot timer API
@ 2011-05-21 12:38 Graeme Russ
       [not found] ` <4DD7DB64.70605@comcast.net>
                   ` (3 more replies)
  0 siblings, 4 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-21 12:38 UTC (permalink / raw)
  To: u-boot

Hi All,

I've just had a good look through the timer API code with the view of
rationalising it and fixing up some of the inconsistencies. What I found
was a little scarier than I expected! Anyway, here is a write-up of what I
found - Please comment

Regards,

Graeme

--------

At the lowest level, the U-Boot timer API consists of a unsigned 32-bit
free running timestamp which increments every millisecond (wraps around
every 4294967 seconds, or about every 49.7 days). The U-Boot timer API
allows:
 - Time deltas to be measured between arbitrary code execution points
	ulong start_time;
	ulong elapsed_time;

	start_time = get_timer(0);
	...
	elapsed_time = get_timer(start_time);

 - Repetition of code for a specified duration
	ulong start_time;

	start_time = get_timer(0);

	while (get_timer(start_time) < REPEAT_TIME) {
		...
	}

 - Device timeout detection
	ulong start_time;

	send_command_to_device();
	start = get_timer (0);
	while (device_is_busy()) {
		if (get_timer(start) > TIMEOUT)
			return ERR_TIMOUT;
		udelay(1);
	}
	return ERR_OK;

The U-Boot timer API is not a 'callback' API and cannot 'trigger' a
function call after a pre-determined time.

NOTE: http://lists.denx.de/pipermail/u-boot/2010-June/073024.html appears
to imply the following implementation of get_timer() is wrong:

	ulong get_timer(ulong base)
	{
		return get_timer_masked() - base;
	}

U-Boot Timer API Details
========================
There are currently three functions in the U-Boot timer API:
	ulong get_timer(ulong start_time)
	void set_timer(ulong preset)
	void reset_timer(void)

get_timer() returns the number of milliseconds since 'start_time'. If
'start_time' is zero, therefore, it returns the current value of the
free running counter which can be used as a reference for subsequent
timing measurements.

set_timer() sets the free running counter to the value of 'preset'
reset_timer() sets the free running counter to the value of zero[1]. In
theory, the following examples are all identical

	----------------------------------------------------
	ulong start_time;
	ulong elapsed_time;

	start_time = get_timer(0);
	...
	elapsed_time = get_timer(start_time);
	----------------------------------------------------
	ulong elapsed_time;

	reset_timer();
	...
	elapsed_time = get_timer(0);
	----------------------------------------------------
	ulong elapsed_time;

	set_timer(0);
	...
	elapsed_time = get_timer(0);
	----------------------------------------------------

[1] arch/arm/cpu/arm926ejs/at91/ and arch/arm/cpu/arm926ejs/davinci/ are
exceptions, they set the free running counter to get_ticks() instead

Architecture Specific Peculiarities
===================================
ARM
 - Generally define get_timer_masked() and reset_timer_masked()
 - [get,reset]_timer_masked() are exposed outside arch\arm which is a bad
   idea as no other arches define these functions - build breakages are
   possible although the external files are most likely ARM specific (for
   now!)
 - Most CPUs define their own versions of the API get/set functions which
   are wrappers to the _masked equivalents. These all tend to be the same.
   The API functions could be moved into arch/arm/lib and made weak for
   the rare occasions where they need to be different
 - Implementations generally look sane[2] except for the following:
   - arm_intcm - No timer code (unused CPU arch?)
   - arm1136/mx35 - set_timer() is a NOP
   - arm926ejs/at91 - reset_timer() sets counter to get_ticks()
                      no implelemtation of set_timer()
   - arm926ejs/davinci - reset_timer() sets counter to get_ticks()
                         no implelemtation of set_timer()
   - arm926ejs/mb86r0x - No implementation of set_timer()
   - arm926ejs/nomadik - No implementation of set_timer()
   - arm946es - No timer code (unused CPU arch?)
   - ixp - No implementation of set_timer()
         - If CONFIG_TIMER_IRQ is defined, timer is incremented by an
           interrupt routine - reset_timer() writes directly to the
           counter without interrupts disables - Could cause corruption
           if reset_timer() is not atomic
         - If CONFIG_TIMER_IRQ is not defined, reset_timer() appears to
           not be implemented
   - pxa - set_timer() is a NOP
   - sa1100 - get_timer() does not subtract the argument

nios, powerpc, sparc, x86
 - All look sane[2]

avr32
 - Not obvious, but looks sane[2]

blackfin
 - Does not implement set_timer()
 - Provides a 64-bit get_ticks() which simply returns 32-bit get_timer(0)
 - reset_timer() calls timer_init()
 - Looks sane[2]

m68k
 - Looks sane[2] if CONFIG_MCFTMR et al are defined. If CONFIG_MCFPIT is
   defined instead, reset_timer() is unimplemented and build breakage will
   result if cfi driver is included in the build - No configurations use
   this define, so that code is dead anyway

microblaze
 - Only sane[2] if CONFIG_SYS_INTC_0 and CONFIG_SYS_TIMER_0 are both defined.
   Doing so enables a timer interrupt which increments the internal
   counter. Otherwise, it is incremented when get_timer() is called which
   will lead to horrible (i.e. none at all) accuracy

mips
 - Not obvious, but looks sane[2]

sh
 - Generally looks sane[2]
 - Writes 0xffff to the CMCOR_0 control register when resetting to zero,
   but writes the actual 'set' value when not zero
 - Uses a 32-bit microsecond based timebase:
	static unsigned long get_usec (void)
	{
	...
	}

	get_timer(ulong base)
	{
		return (get_usec() / 1000) - base;
	}

 - Timer will wrap after ~4295 seconds (71 minutes)

[2] Sane means something close to:
	void reset_timer (void)
	{
		timestamp = 0;
	}

	ulong get_timer(ulong base)
	{
		return timestamp - base;
	}

	void set_timer(ulong t)
	{
		timestamp = t;
	}

Rationalising the API
=====================
Realistically, the value of the free running timer at the start of a timing
operation is irrelevant (even if the counter wraps during the timed period).
Moreover, using reset_timer() and set_timer() makes nested usage of the
timer API impossible. So in theory, the entire API could be reduced to
simply get_timer()

0. Fix arch/arm/cpu/sa1100/timer.c:get_timer()
----------------------------------------------
This appears to be the only get_timer() which does not subtract the
argument from timestamp

1. Remove set_timer()
---------------------
regex "[^e]set_timer\s*\([^)]*\);" reveals 14 call sites for set_timer()
and all except arch/sh/lib/time_sh2:[timer_init(),reset_timer()] are
set_timer(0). The code in arch/sh is trivial to resolve in order to
remove set_timer()

2. Remove reset_timer()
-----------------------------------------------
regex "[\t ]*reset_timer\s*\([^)]*\);" reveals 22 callers across the
following groups:
 - timer_init() - Make reset_timer() static or fold into timer_init()
 - board_init_r() - Unnecessary
 - arch/m68k/lib/time.c:wait_ticks() - convert[3]
 - Board specific flash drivers - convert[3]
 - drivers/block/mg_disk.c:mg_wait() - Unnecessary
 - drivers/mtd/cfi_flash.c:flash_status_check() - Unnecessary
 - drivers/mtd/cfi_flash.c:flash_status_poll() - Unnecessary

[3] These instance can be trivially converted to use one of the three
examples at the beginning of this document

3. Remove reset_timer_masked()
------------------------------
This is only implemented in arm but has propagated outside arch/arm and
into board/ and drivers/ (bad!)

regex "[\t ]*reset_timer_masked\s*\([^)]*\);" reveals 135 callers!

A lot are in timer_init() and reset_timer(), but the list includes:
 - arch/arm/cpu/arm920t/at91rm9200/spi.c:AT91F_SpiWrite()
 - arch/arm/cpu/arm926ejs/omap/timer.c:__udelay()
 - arch/arm/cpu/arm926ejs/versatile/timer.c:__udelay()
 - arch/arm/armv7/s5p-common/timer.c:__udelay()
 - arch/arm/lh7a40x/timer.c:__udelay()
 - A whole bunch of board specific flash drivers
 - board/mx1ads/syncflash.c:flash_erase()
 - board/trab/cmd_trab.c:do_burn_in()
 - board/trab/cmd_trab.c:led_blink()
 - board/trab/cmd_trab.c:do_temp_log()
 - drivers/mtd/spi/eeprom_m95xxx.c:spi_write()
 - drivers/net/netarm_eth.c:na_mii_poll_busy()
 - drivers/net/netarm_eth.c:reset_eth()
 - drivers/spi/atmel_dataflash_spi.c/AT91F_SpiWrite()

Most of these instance can be converted to use one of the three examples
at the beginning of this document, but __udelay() will need closer
examination

This is preventing nesting of timed code - Any code which uses udelay()
has the potential to foul up outer-loop timers. The problem is somewhat
unique to ARM though

4. Implement microsecond API - get_usec_timer()
-----------------------------------------------
 - Useful for profiling
 - A 32-bit microsecond counter wraps in 71 minutes - Probably OK for most
   U-Boot usage scenarios
 - By default could return get_timer() * 1000 if hardware does not support
   microsecond accuracy - Beware of results > 32 bits!
 - If hardware supports microsecond resolution counters, get_timer() could
   simply use get_usec_timer() / 1000
 - get_usec_timer_64() could offer a longer period (584942 years!)

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
       [not found] ` <4DD7DB64.70605@comcast.net>
@ 2011-05-22  0:06   ` Graeme Russ
  2011-05-22  0:43     ` J. William Campbell
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-22  0:06 UTC (permalink / raw)
  To: u-boot

On 22/05/11 01:33, J. William Campbell wrote:
> On 5/21/2011 5:38 AM, Graeme Russ wrote:
>> Hi All,

>> 4. Implement microsecond API - get_usec_timer()
>> -----------------------------------------------
>>   - Useful for profiling
>>   - A 32-bit microsecond counter wraps in 71 minutes - Probably OK for most
>>     U-Boot usage scenarios
>>   - By default could return get_timer() * 1000 if hardware does not support
>>     microsecond accuracy - Beware of results>  32 bits!
> Hi All,
>       I think the multiply overflowing an unsigned long is ok here as long
> as the timeout value you desire is less than 71 seconds. This assumes that
> the CPU returns the correct lower 32 bits when overflow occurs, but I think
> this is the "normal" behavior(?)

I think you mean 71 minutes - 2^32 = 4294967296 (usec) = 4294967.296 (msec)
= 4294.967296 s = 71.582788267 minutes

So provided any millisecond timer using a 32-bit microsecond timer as a
time base is called every 71 minutes, a 32-bit microsecond  timer should
suffice to keep the msb's accurately maintained by software

>>   - If hardware supports microsecond resolution counters, get_timer() could
>>     simply use get_usec_timer() / 1000
>        I think this actually is NOT equivalent to the "current" API  in
> that the full 32 bits of the timer is not available and as a result the
> "wrapping" properties of a 32 bit subtract for delta times will not work
> properly. If a "larger"  counter is available in hardware, then it is
> certainly possible to do a 64 by 32 bit divide in get_timer, but probably
> you don't want to do that  either. As previously discussed, it is possible
> to extract a 32 bit monotonic counter of given resolution (microsecond or
> millisecond resolution) from a higher resolution counter using a shift to
> "approximately" the desired resolution followed by a couple of multiply/add
> functions of 32 bit resolution.  To do this with a microsecond resolution,
> a 42 bit or larger timer is required. The "extra" bits can be provided in

Of course, how silly of me - To downscale the microsecond timer down to
milliseconds you need to have at least 1000 times more resolution
(9.965784285 bits) - It was late ;)

> software as long as the get_timer/get_usec_timer routines are called more
> often than every 71/2 sec, so that a correct delta in microseconds can be
> obtained. Note that when the timer is not actively in use (not  called
> often enough), the millisecond timer msb would stop updating, but that
> wouldn't matter.

Minutes - see above

>        If the hardware supports sub-microsecond accuracy in a "longer"
> register, say 64 bits, you can just convert the 64 bit hardware timer to 32
> bit microseconds or milliseconds by a shift  and 32 bit multiplies

Yes

> 
>       Good luck with this effort. I think getting the timer API and also
> the method of implementation of the interface to the hardware to be the
> same across all u-boot architectures is a very good idea, and it is
> possible. However, it is a quite a bit of work and I am glad you are brave
> enough to try!

It's all there already - it just needs a little bit of housekeeping :)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  0:06   ` Graeme Russ
@ 2011-05-22  0:43     ` J. William Campbell
  0 siblings, 0 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-22  0:43 UTC (permalink / raw)
  To: u-boot

On 5/21/2011 5:06 PM, Graeme Russ wrote:
> On 22/05/11 01:33, J. William Campbell wrote:
>> On 5/21/2011 5:38 AM, Graeme Russ wrote:
>>> Hi All,
>>> 4. Implement microsecond API - get_usec_timer()
>>> -----------------------------------------------
>>>    - Useful for profiling
>>>    - A 32-bit microsecond counter wraps in 71 minutes - Probably OK for most
>>>      U-Boot usage scenarios
>>>    - By default could return get_timer() * 1000 if hardware does not support
>>>      microsecond accuracy - Beware of results>   32 bits!
>> Hi All,
>>        I think the multiply overflowing an unsigned long is ok here as long
>> as the timeout value you desire is less than 71 seconds. This assumes that
>> the CPU returns the correct lower 32 bits when overflow occurs, but I think
>> this is the "normal" behavior(?)
> I think you mean 71 minutes - 2^32 = 4294967296 (usec) = 4294967.296 (msec)
> = 4294.967296 s = 71.582788267 minutes
>
> So provided any millisecond timer using a 32-bit microsecond timer as a
> time base is called every 71 minutes, a 32-bit microsecond  timer should
> suffice to keep the msb's accurately maintained by software
>
Hi Graeme,
         Yes, you are certainly correct, it is minutes, not seconds.
>>>    - If hardware supports microsecond resolution counters, get_timer() could
>>>      simply use get_usec_timer() / 1000
>>         I think this actually is NOT equivalent to the "current" API  in
>> that the full 32 bits of the timer is not available and as a result the
>> "wrapping" properties of a 32 bit subtract for delta times will not work
>> properly. If a "larger"  counter is available in hardware, then it is
>> certainly possible to do a 64 by 32 bit divide in get_timer, but probably
>> you don't want to do that  either. As previously discussed, it is possible
>> to extract a 32 bit monotonic counter of given resolution (microsecond or
>> millisecond resolution) from a higher resolution counter using a shift to
>> "approximately" the desired resolution followed by a couple of multiply/add
>> functions of 32 bit resolution.  To do this with a microsecond resolution,
>> a 42 bit or larger timer is required. The "extra" bits can be provided in
> Of course, how silly of me - To downscale the microsecond timer down to
> milliseconds you need to have at least 1000 times more resolution
> (9.965784285 bits) - It was late ;)
>
>> software as long as the get_timer/get_usec_timer routines are called more
>> often than every 71/2 sec, so that a correct delta in microseconds can be
>> obtained. Note that when the timer is not actively in use (not  called
>> often enough), the millisecond timer msb would stop updating, but that
>> wouldn't matter.
> Minutes - see above
Correct.
>>         If the hardware supports sub-microsecond accuracy in a "longer"
>> register, say 64 bits, you can just convert the 64 bit hardware timer to 32
>> bit microseconds or milliseconds by a shift  and 32 bit multiplies
> Yes
>
>>        Good luck with this effort. I think getting the timer API and also
>> the method of implementation of the interface to the hardware to be the
>> same across all u-boot architectures is a very good idea, and it is
>> possible. However, it is a quite a bit of work and I am glad you are brave
>> enough to try!
> It's all there already - it just needs a little bit of housekeeping :)
Correct, if we do not worry too much about the "low level" details of 
get_timer. It looks to me like there is a lot of cruft there, depending 
on which architecture one looks at. Many implementations create a 
parallel universe of get_ticks or some similar timing system that is 
then used to support get_timer. However, the get_ticks routines are also 
used in timeouts elsewhere in the code. Searching on "get_timer" doesn't 
find these non-standard usages. It would be nice to fix these also, but 
every bit does help!

Best Regards,
Bill Campbell
> Regards,
>
> Graeme
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-21 12:38 [U-Boot] [RFC] Review of U-Boot timer API Graeme Russ
       [not found] ` <4DD7DB64.70605@comcast.net>
@ 2011-05-22  4:26 ` Reinhard Meyer
  2011-05-22  6:23   ` Graeme Russ
  2011-05-22  6:57   ` J. William Campbell
  2011-05-24  3:42 ` Mike Frysinger
  2011-05-24  4:07 ` Graeme Russ
  3 siblings, 2 replies; 101+ messages in thread
From: Reinhard Meyer @ 2011-05-22  4:26 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,
> Hi All,
>
> I've just had a good look through the timer API code with the view of
> rationalising it and fixing up some of the inconsistencies. What I found
> was a little scarier than I expected! Anyway, here is a write-up of what I
> found - Please comment

We have been at this discussion a multiple of times :) but never reached a consent.

However, at current master, I have reduced at91 architecture to only use
get_timer(base), set_timer() never existed and reset_timer() has been removed.

As it showed up recently, common cfi code still calls reset_timer() - which certainly
can be fixed with little effort...

> At the lowest level, the U-Boot timer API consists of a unsigned 32-bit
> free running timestamp which increments every millisecond (wraps around
> every 4294967 seconds, or about every 49.7 days). The U-Boot timer API
> allows:
>   - Time deltas to be measured between arbitrary code execution points
> 	ulong start_time;
> 	ulong elapsed_time;
>
> 	start_time = get_timer(0);
> 	...
> 	elapsed_time = get_timer(start_time);
>
>   - Repetition of code for a specified duration
> 	ulong start_time;
>
> 	start_time = get_timer(0);
>
> 	while (get_timer(start_time)<  REPEAT_TIME) {
> 		...
> 	}
>
>   - Device timeout detection
> 	ulong start_time;
>
> 	send_command_to_device();
> 	start = get_timer (0);
> 	while (device_is_busy()) {
> 		if (get_timer(start)>  TIMEOUT)
> 			return ERR_TIMOUT;
> 		udelay(1);
> 	}
> 	return ERR_OK;
correct.

>
> The U-Boot timer API is not a 'callback' API and cannot 'trigger' a
> function call after a pre-determined time.
that would be too complex to implement and of little use in a single task
system. u-boot can do fine with polling.

>
> NOTE: http://lists.denx.de/pipermail/u-boot/2010-June/073024.html appears
> to imply the following implementation of get_timer() is wrong:
>
> 	ulong get_timer(ulong base)
> 	{
> 		return get_timer_masked() - base;
> 	}
Is is not wrong as long as get_timer_masked() returns the full 32 bit space
of numbers and 0xffffffff is followed by 0x00000000. Most implementations
probably do NOT have this property.

>
> U-Boot Timer API Details
> ========================
> There are currently three functions in the U-Boot timer API:
> 	ulong get_timer(ulong start_time)
As you point out in the following, this is the only function required.
However it REQUIRES that the internal timer value must exploit the full
32 bit range of 0x00000000 to 0xffffffff before it wraps back to 0x00000000.

> 	void set_timer(ulong preset)
> 	void reset_timer(void)
>
> get_timer() returns the number of milliseconds since 'start_time'. If
> 'start_time' is zero, therefore, it returns the current value of the
> free running counter which can be used as a reference for subsequent
> timing measurements.
>
> set_timer() sets the free running counter to the value of 'preset'
> reset_timer() sets the free running counter to the value of zero[1]. In
> theory, the following examples are all identical
>
> 	----------------------------------------------------
> 	ulong start_time;
> 	ulong elapsed_time;
>
> 	start_time = get_timer(0);
> 	...
> 	elapsed_time = get_timer(start_time);
> 	----------------------------------------------------
> 	ulong elapsed_time;
>
> 	reset_timer();
> 	...
> 	elapsed_time = get_timer(0);
> 	----------------------------------------------------
> 	ulong elapsed_time;
>
> 	set_timer(0);
> 	...
> 	elapsed_time = get_timer(0);
> 	----------------------------------------------------
>
> [1] arch/arm/cpu/arm926ejs/at91/ and arch/arm/cpu/arm926ejs/davinci/ are
> exceptions, they set the free running counter to get_ticks() instead
Not anymore on at91.
>
> Architecture Specific Peculiarities
> ===================================
> ARM
>   - Generally define get_timer_masked() and reset_timer_masked()
>   - [get,reset]_timer_masked() are exposed outside arch\arm which is a bad
>     idea as no other arches define these functions - build breakages are
>     possible although the external files are most likely ARM specific (for
>     now!)
>   - Most CPUs define their own versions of the API get/set functions which
>     are wrappers to the _masked equivalents. These all tend to be the same.
>     The API functions could be moved into arch/arm/lib and made weak for
>     the rare occasions where they need to be different
>   - Implementations generally look sane[2] except for the following:
>     - arm_intcm - No timer code (unused CPU arch?)
>     - arm1136/mx35 - set_timer() is a NOP
>     - arm926ejs/at91 - reset_timer() sets counter to get_ticks()
>                        no implelemtation of set_timer()
See current master for actual implementation!
>     - arm926ejs/davinci - reset_timer() sets counter to get_ticks()
>                           no implelemtation of set_timer()
>     - arm926ejs/mb86r0x - No implementation of set_timer()
>     - arm926ejs/nomadik - No implementation of set_timer()
>     - arm946es - No timer code (unused CPU arch?)
>     - ixp - No implementation of set_timer()
>           - If CONFIG_TIMER_IRQ is defined, timer is incremented by an
>             interrupt routine - reset_timer() writes directly to the
>             counter without interrupts disables - Could cause corruption
>             if reset_timer() is not atomic
>           - If CONFIG_TIMER_IRQ is not defined, reset_timer() appears to
>             not be implemented
>     - pxa - set_timer() is a NOP
>     - sa1100 - get_timer() does not subtract the argument
>
> nios, powerpc, sparc, x86
>   - All look sane[2]
>
> avr32
>   - Not obvious, but looks sane[2]
>
> blackfin
>   - Does not implement set_timer()
>   - Provides a 64-bit get_ticks() which simply returns 32-bit get_timer(0)
>   - reset_timer() calls timer_init()
>   - Looks sane[2]
>
> m68k
>   - Looks sane[2] if CONFIG_MCFTMR et al are defined. If CONFIG_MCFPIT is
>     defined instead, reset_timer() is unimplemented and build breakage will
>     result if cfi driver is included in the build - No configurations use
>     this define, so that code is dead anyway
>
> microblaze
>   - Only sane[2] if CONFIG_SYS_INTC_0 and CONFIG_SYS_TIMER_0 are both defined.
>     Doing so enables a timer interrupt which increments the internal
>     counter. Otherwise, it is incremented when get_timer() is called which
>     will lead to horrible (i.e. none at all) accuracy
>
> mips
>   - Not obvious, but looks sane[2]
>
> sh
>   - Generally looks sane[2]
>   - Writes 0xffff to the CMCOR_0 control register when resetting to zero,
>     but writes the actual 'set' value when not zero
>   - Uses a 32-bit microsecond based timebase:
> 	static unsigned long get_usec (void)
> 	{
> 	...
> 	}
>
> 	get_timer(ulong base)
> 	{
> 		return (get_usec() / 1000) - base;
> 	}
>
>   - Timer will wrap after ~4295 seconds (71 minutes)
>
> [2] Sane means something close to:
> 	void reset_timer (void)
> 	{
> 		timestamp = 0;
> 	}
>
> 	ulong get_timer(ulong base)
> 	{
> 		return timestamp - base;
> 	}
>
> 	void set_timer(ulong t)
> 	{
> 		timestamp = t;
> 	}
>
> Rationalising the API
> =====================
> Realistically, the value of the free running timer at the start of a timing
> operation is irrelevant (even if the counter wraps during the timed period).
> Moreover, using reset_timer() and set_timer() makes nested usage of the
> timer API impossible. So in theory, the entire API could be reduced to
> simply get_timer()
Full ACK here !!!
>
> 0. Fix arch/arm/cpu/sa1100/timer.c:get_timer()
> ----------------------------------------------
> This appears to be the only get_timer() which does not subtract the
> argument from timestamp
>
> 1. Remove set_timer()
> ---------------------
> regex "[^e]set_timer\s*\([^)]*\);" reveals 14 call sites for set_timer()
> and all except arch/sh/lib/time_sh2:[timer_init(),reset_timer()] are
> set_timer(0). The code in arch/sh is trivial to resolve in order to
> remove set_timer()
>
> 2. Remove reset_timer()
> -----------------------------------------------
> regex "[\t ]*reset_timer\s*\([^)]*\);" reveals 22 callers across the
> following groups:
>   - timer_init() - Make reset_timer() static or fold into timer_init()
>   - board_init_r() - Unnecessary
>   - arch/m68k/lib/time.c:wait_ticks() - convert[3]
>   - Board specific flash drivers - convert[3]
>   - drivers/block/mg_disk.c:mg_wait() - Unnecessary
>   - drivers/mtd/cfi_flash.c:flash_status_check() - Unnecessary
>   - drivers/mtd/cfi_flash.c:flash_status_poll() - Unnecessary
>
> [3] These instance can be trivially converted to use one of the three
> examples at the beginning of this document
>
> 3. Remove reset_timer_masked()
> ------------------------------
> This is only implemented in arm but has propagated outside arch/arm and
> into board/ and drivers/ (bad!)
>
> regex "[\t ]*reset_timer_masked\s*\([^)]*\);" reveals 135 callers!
>
> A lot are in timer_init() and reset_timer(), but the list includes:
>   - arch/arm/cpu/arm920t/at91rm9200/spi.c:AT91F_SpiWrite()
>   - arch/arm/cpu/arm926ejs/omap/timer.c:__udelay()
>   - arch/arm/cpu/arm926ejs/versatile/timer.c:__udelay()
>   - arch/arm/armv7/s5p-common/timer.c:__udelay()
>   - arch/arm/lh7a40x/timer.c:__udelay()
>   - A whole bunch of board specific flash drivers
>   - board/mx1ads/syncflash.c:flash_erase()
>   - board/trab/cmd_trab.c:do_burn_in()
>   - board/trab/cmd_trab.c:led_blink()
>   - board/trab/cmd_trab.c:do_temp_log()
>   - drivers/mtd/spi/eeprom_m95xxx.c:spi_write()
>   - drivers/net/netarm_eth.c:na_mii_poll_busy()
>   - drivers/net/netarm_eth.c:reset_eth()
>   - drivers/spi/atmel_dataflash_spi.c/AT91F_SpiWrite()
Fixed in current master.
>
> Most of these instance can be converted to use one of the three examples
> at the beginning of this document, but __udelay() will need closer
> examination
>
> This is preventing nesting of timed code - Any code which uses udelay()
> has the potential to foul up outer-loop timers. The problem is somewhat
> unique to ARM though
>
> 4. Implement microsecond API - get_usec_timer()
> -----------------------------------------------
>   - Useful for profiling
>   - A 32-bit microsecond counter wraps in 71 minutes - Probably OK for most
>     U-Boot usage scenarios
>   - By default could return get_timer() * 1000 if hardware does not support
>     microsecond accuracy - Beware of results>  32 bits!
>   - If hardware supports microsecond resolution counters, get_timer() could
>     simply use get_usec_timer() / 1000

That is wrong. Dividing 32 bits by any number will result in a result that does not
exploit the full 32 bit range, i.e. wrap from (0xffffffff/1000) to 0x00000000,
which makes time differences go wrong when they span across such a wrap!

>   - get_usec_timer_64() could offer a longer period (584942 years!)
Correct. And a "must be" when one uses such division.

But you have to realize that most hardware does not provide a simple means to
implement a timer that runs in either exact microseconds or exact milliseconds.

Powerpc for example has a 64 bit free running hardware counter at CPU clock,
which can be in the GHz range, making the lower 32 bits overflow within seconds,
so the full 64 bits MUST BE used to obtain a millisecond timer by division.

arm/at91 has a timer that can be made to appear like a 32 bit free running counter
at some fraction of cpu clock (can be brought into a few MHz value by a prescaler)
and the current implementation extends this to 64 bits by software, so it is
similar to powerpc.

A get timer() simply uses this 64 bit value by dividing it by (tickrate/1000).

Of course this results in a wrong wrap "gigaseconds" after the timer has been started,
but certainly this can be ignored...

On any account, I see only the following two functions to be implemented for use by
other u-boot code parts:

1. void udelay(u32 microseconds) with the following properties:
- must not affect get_timer() results
- must not delay less than the given time, may delay longer
(this might be true especially for very small delay values)
- shall not be used for delays in the seconds range and longer
(or any other limit we see practical)
Note: a loop doing "n" udelays of "m" microseconds might take _much_ longer than
"n * m" microseconds and therefore is the wrong approach to implement a timeout.
get_timer() must be used for any such timeouts instead!

2. u32 get_timer(u32 base) with the following properties:
- must return the elapsed milliseconds since base
- must work without wrapping problems for at least several hours

Best Regards,
Reinhard

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  4:26 ` Reinhard Meyer
@ 2011-05-22  6:23   ` Graeme Russ
  2011-05-22  7:21     ` J. William Campbell
  2011-05-22  6:57   ` J. William Campbell
  1 sibling, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-22  6:23 UTC (permalink / raw)
  To: u-boot

On 22/05/11 14:26, Reinhard Meyer wrote:
> Dear Graeme Russ,
>> Hi All,
>>
>> I've just had a good look through the timer API code with the view of
>> rationalising it and fixing up some of the inconsistencies. What I found
>> was a little scarier than I expected! Anyway, here is a write-up of what I
>> found - Please comment
> 
> We have been at this discussion a multiple of times :) but never reached a
> consent.
> 
> However, at current master, I have reduced at91 architecture to only use
> get_timer(base), set_timer() never existed and reset_timer() has been removed.

Excellent

> As it showed up recently, common cfi code still calls reset_timer() - which
> certainly
> can be fixed with little effort...

Yes, this is one of the easy fixes as all call sites already use the start
= get_timer(0), elapsed = get_timer(start) convention anyway - The
reset_timer() calls are 100% redundant (provided get_timer() behaves
correctly at the 32-bit rollover for all arches)

>> The U-Boot timer API is not a 'callback' API and cannot 'trigger' a
>> function call after a pre-determined time.
> that would be too complex to implement and of little use in a single task
> system. u-boot can do fine with polling.

I am in no way suggesting this - I just want to clarify the API for anyone
who needs to use it

>> NOTE: http://lists.denx.de/pipermail/u-boot/2010-June/073024.html appears
>> to imply the following implementation of get_timer() is wrong:
>>
>>     ulong get_timer(ulong base)
>>     {
>>         return get_timer_masked() - base;
>>     }
> Is is not wrong as long as get_timer_masked() returns the full 32 bit space
> of numbers and 0xffffffff is followed by 0x00000000. Most implementations
> probably do NOT have this property.
>>
>> U-Boot Timer API Details
>> ========================
>> There are currently three functions in the U-Boot timer API:
>>     ulong get_timer(ulong start_time)
> As you point out in the following, this is the only function required.
> However it REQUIRES that the internal timer value must exploit the full
> 32 bit range of 0x00000000 to 0xffffffff before it wraps back to 0x00000000.

So this needs to be clearly spelt out in formal documentation

>> Rationalising the API
>> =====================
>> Realistically, the value of the free running timer at the start of a timing
>> operation is irrelevant (even if the counter wraps during the timed period).
>> Moreover, using reset_timer() and set_timer() makes nested usage of the
>> timer API impossible. So in theory, the entire API could be reduced to
>> simply get_timer()
> Full ACK here !!!

I don't think there will be much resistance to this

>> 3. Remove reset_timer_masked()
>> ------------------------------
>> This is only implemented in arm but has propagated outside arch/arm and
>> into board/ and drivers/ (bad!)
>>
>> regex "[\t ]*reset_timer_masked\s*\([^)]*\);" reveals 135 callers!
>>
>> A lot are in timer_init() and reset_timer(), but the list includes:
>>   - arch/arm/cpu/arm920t/at91rm9200/spi.c:AT91F_SpiWrite()
>>   - arch/arm/cpu/arm926ejs/omap/timer.c:__udelay()
>>   - arch/arm/cpu/arm926ejs/versatile/timer.c:__udelay()
>>   - arch/arm/armv7/s5p-common/timer.c:__udelay()
>>   - arch/arm/lh7a40x/timer.c:__udelay()
>>   - A whole bunch of board specific flash drivers
>>   - board/mx1ads/syncflash.c:flash_erase()
>>   - board/trab/cmd_trab.c:do_burn_in()
>>   - board/trab/cmd_trab.c:led_blink()
>>   - board/trab/cmd_trab.c:do_temp_log()
>>   - drivers/mtd/spi/eeprom_m95xxx.c:spi_write()
>>   - drivers/net/netarm_eth.c:na_mii_poll_busy()
>>   - drivers/net/netarm_eth.c:reset_eth()
>>   - drivers/spi/atmel_dataflash_spi.c/AT91F_SpiWrite()
> Fixed in current master.

Excellent. I have not pulled master for a little while, guess I should

>>   - If hardware supports microsecond resolution counters, get_timer() could
>>     simply use get_usec_timer() / 1000
> 
> That is wrong. Dividing 32 bits by any number will result in a result that
> does not
> exploit the full 32 bit range, i.e. wrap from (0xffffffff/1000) to 0x00000000,
> which makes time differences go wrong when they span across such a wrap!
> 

Yes, this has already been pointer out - 42 bits are needed as a bare
minimum. However, we can get away with 32-bits provided get_timer() is
called at least every 71 minutes

P.S. Can we use the main loop to kick the timer?

>>   - get_usec_timer_64() could offer a longer period (584942 years!)
> Correct. And a "must be" when one uses such division.

Unless we can rely on get_timer() to be called at least every 71 minutes in
which case we can handle the msb's without error in software

> But you have to realize that most hardware does not provide a simple means to
> implement a timer that runs in either exact microseconds or exact
> milliseconds.

This is where things get interesting and we need to start pushing a
mandated low-level HAL. For example, I believe get_timer() should be
implemented in /lib as:

	ulong get_timer(ulong base)
	{
		return get_raw_msec() - base;
	}

get_raw_ms() MUST:
 - Return an unsigned 32-but value which increments every 1ms
 - Wraps from 0xffffffff to 0x00000000
 - Be atomic (no possibility of corruption by an interrupt)

The counter behind get_raw_ms() can be maintained by either:

 1. A hardware timer programmed with a 1ms increment
 2. A hardware timer programmed with a non-1ms increment scaled in software
 3. A software counter ticked by a 1ms interrupt
 4. A software counter ticked by a non-1ms interrupt scaled in software

get_raw_ms() does not need a fixed epoch - It could be 1st Jan 1970, the
date the CPU/SOC was manufactured, when the device was turned on, your
eldest child's birthday - whatever. It will not matter provided the counter
wraps correctly

> Powerpc for example has a 64 bit free running hardware counter at CPU clock,
> which can be in the GHz range, making the lower 32 bits overflow within
> seconds,
> so the full 64 bits MUST BE used to obtain a millisecond timer by division.
> arm/at91 has a timer that can be made to appear like a 32 bit free running
> counter
> at some fraction of cpu clock (can be brought into a few MHz value by a
> prescaler)
> and the current implementation extends this to 64 bits by software, so it is
> similar to powerpc.

So these are all examples of #2

x86 is an example of #3

> A get timer() simply uses this 64 bit value by dividing it by (tickrate/1000).
> 
> Of course this results in a wrong wrap "gigaseconds" after the timer has
> been started,
> but certainly this can be ignored...

Strictly speaking, I don't think we should allow this - There should never
be timer glitches

> On any account, I see only the following two functions to be implemented
> for use by
> other u-boot code parts:
> 
> 1. void udelay(u32 microseconds) with the following properties:
> - must not affect get_timer() results

Absolutely

> - must not delay less than the given time, may delay longer
> (this might be true especially for very small delay values)

Hadn't though about that, but OK

> - shall not be used for delays in the seconds range and longer
> (or any other limit we see practical)

Any udelay up to the full range of a ulong should be handled without error
by udelay() - If the arch dependant implementation of udelay() uses
get_timer() to implement long delays due to hardware limitations then that
should be fine.

> Note: a loop doing "n" udelays of "m" microseconds might take _much_ longer
> than
> "n * m" microseconds and therefore is the wrong approach to implement a
> timeout.
> get_timer() must be used for any such timeouts instead!

ACK - as mentioned, udelay() can use get_timer() of the delay is >> 1ms if
such an implementation provides better accuracy. If the HAL implementation
of get_raw_ms() uses a hardware level microsecond time base, there will be
no accuracy advantage anyway.

> 2. u32 get_timer(u32 base) with the following properties:
> - must return the elapsed milliseconds since base

ACK

> - must work without wrapping problems for at least several hours

Provided that the architecture implementation of get_raw_ms() is
implemented as described, the only limitation will be the maximum
measurable delay. The timer API should work correctly no matter how long
the device has been running

I think the HAL should implement:
	- get_raw_ms() - 32-bit millisecond counter
	- get_raw_us() - 32-bit microsecond counter
	- get_raw_us64() - 64-bit microsecond counter

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  4:26 ` Reinhard Meyer
  2011-05-22  6:23   ` Graeme Russ
@ 2011-05-22  6:57   ` J. William Campbell
  2011-05-23 12:13     ` Wolfgang Denk
  1 sibling, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-22  6:57 UTC (permalink / raw)
  To: u-boot

On 5/21/2011 9:26 PM, Reinhard Meyer wrote:
> Dear Graeme Russ,
>> Hi All,
>>
>> I've just had a good look through the timer API code with the view of
>> rationalising it and fixing up some of the inconsistencies. What I found
>> was a little scarier than I expected! Anyway, here is a write-up of what I
>> found - Please comment
> We have been at this discussion a multiple of times :) but never reached a consent.
>
> However, at current master, I have reduced at91 architecture to only use
> get_timer(base), set_timer() never existed and reset_timer() has been removed.
>
> As it showed up recently, common cfi code still calls reset_timer() - which certainly
> can be fixed with little effort...
>
>> At the lowest level, the U-Boot timer API consists of a unsigned 32-bit
>> free running timestamp which increments every millisecond (wraps around
>> every 4294967 seconds, or about every 49.7 days). The U-Boot timer API
>> allows:
>>    - Time deltas to be measured between arbitrary code execution points
>> 	ulong start_time;
>> 	ulong elapsed_time;
>>
>> 	start_time = get_timer(0);
>> 	...
>> 	elapsed_time = get_timer(start_time);
>>
>>    - Repetition of code for a specified duration
>> 	ulong start_time;
>>
>> 	start_time = get_timer(0);
>>
>> 	while (get_timer(start_time)<   REPEAT_TIME) {
>> 		...
>> 	}
>>
>>    - Device timeout detection
>> 	ulong start_time;
>>
>> 	send_command_to_device();
>> 	start = get_timer (0);
>> 	while (device_is_busy()) {
>> 		if (get_timer(start)>   TIMEOUT)
>> 			return ERR_TIMOUT;
>> 		udelay(1);
>> 	}
>> 	return ERR_OK;
> correct.
>
>> The U-Boot timer API is not a 'callback' API and cannot 'trigger' a
>> function call after a pre-determined time.
> that would be too complex to implement and of little use in a single task
> system. u-boot can do fine with polling.
>
>> NOTE: http://lists.denx.de/pipermail/u-boot/2010-June/073024.html appears
>> to imply the following implementation of get_timer() is wrong:
>>
>> 	ulong get_timer(ulong base)
>> 	{
>> 		return get_timer_masked() - base;
>> 	}
> Is is not wrong as long as get_timer_masked() returns the full 32 bit space
> of numbers and 0xffffffff is followed by 0x00000000. Most implementations
> probably do NOT have this property.
>
>> U-Boot Timer API Details
>> ========================
>> There are currently three functions in the U-Boot timer API:
>> 	ulong get_timer(ulong start_time)
> As you point out in the following, this is the only function required.
> However it REQUIRES that the internal timer value must exploit the full
> 32 bit range of 0x00000000 to 0xffffffff before it wraps back to 0x00000000.
>
>> 	void set_timer(ulong preset)
>> 	void reset_timer(void)
>>
>> get_timer() returns the number of milliseconds since 'start_time'. If
>> 'start_time' is zero, therefore, it returns the current value of the
>> free running counter which can be used as a reference for subsequent
>> timing measurements.
>>
>> set_timer() sets the free running counter to the value of 'preset'
>> reset_timer() sets the free running counter to the value of zero[1]. In
>> theory, the following examples are all identical
>>
>> 	----------------------------------------------------
>> 	ulong start_time;
>> 	ulong elapsed_time;
>>
>> 	start_time = get_timer(0);
>> 	...
>> 	elapsed_time = get_timer(start_time);
>> 	----------------------------------------------------
>> 	ulong elapsed_time;
>>
>> 	reset_timer();
>> 	...
>> 	elapsed_time = get_timer(0);
>> 	----------------------------------------------------
>> 	ulong elapsed_time;
>>
>> 	set_timer(0);
>> 	...
>> 	elapsed_time = get_timer(0);
>> 	----------------------------------------------------
>>
>> [1] arch/arm/cpu/arm926ejs/at91/ and arch/arm/cpu/arm926ejs/davinci/ are
>> exceptions, they set the free running counter to get_ticks() instead
> Not anymore on at91.
>> Architecture Specific Peculiarities
>> ===================================
>> ARM
>>    - Generally define get_timer_masked() and reset_timer_masked()
>>    - [get,reset]_timer_masked() are exposed outside arch\arm which is a bad
>>      idea as no other arches define these functions - build breakages are
>>      possible although the external files are most likely ARM specific (for
>>      now!)
>>    - Most CPUs define their own versions of the API get/set functions which
>>      are wrappers to the _masked equivalents. These all tend to be the same.
>>      The API functions could be moved into arch/arm/lib and made weak for
>>      the rare occasions where they need to be different
>>    - Implementations generally look sane[2] except for the following:
>>      - arm_intcm - No timer code (unused CPU arch?)
>>      - arm1136/mx35 - set_timer() is a NOP
>>      - arm926ejs/at91 - reset_timer() sets counter to get_ticks()
>>                         no implelemtation of set_timer()
> See current master for actual implementation!
>>      - arm926ejs/davinci - reset_timer() sets counter to get_ticks()
>>                            no implelemtation of set_timer()
>>      - arm926ejs/mb86r0x - No implementation of set_timer()
>>      - arm926ejs/nomadik - No implementation of set_timer()
>>      - arm946es - No timer code (unused CPU arch?)
>>      - ixp - No implementation of set_timer()
>>            - If CONFIG_TIMER_IRQ is defined, timer is incremented by an
>>              interrupt routine - reset_timer() writes directly to the
>>              counter without interrupts disables - Could cause corruption
>>              if reset_timer() is not atomic
>>            - If CONFIG_TIMER_IRQ is not defined, reset_timer() appears to
>>              not be implemented
>>      - pxa - set_timer() is a NOP
>>      - sa1100 - get_timer() does not subtract the argument
>>
>> nios, powerpc, sparc, x86
>>    - All look sane[2]
>>
>> avr32
>>    - Not obvious, but looks sane[2]
>>
>> blackfin
>>    - Does not implement set_timer()
>>    - Provides a 64-bit get_ticks() which simply returns 32-bit get_timer(0)
>>    - reset_timer() calls timer_init()
>>    - Looks sane[2]
>>
>> m68k
>>    - Looks sane[2] if CONFIG_MCFTMR et al are defined. If CONFIG_MCFPIT is
>>      defined instead, reset_timer() is unimplemented and build breakage will
>>      result if cfi driver is included in the build - No configurations use
>>      this define, so that code is dead anyway
>>
>> microblaze
>>    - Only sane[2] if CONFIG_SYS_INTC_0 and CONFIG_SYS_TIMER_0 are both defined.
>>      Doing so enables a timer interrupt which increments the internal
>>      counter. Otherwise, it is incremented when get_timer() is called which
>>      will lead to horrible (i.e. none at all) accuracy
>>
>> mips
>>    - Not obvious, but looks sane[2]
>>
>> sh
>>    - Generally looks sane[2]
>>    - Writes 0xffff to the CMCOR_0 control register when resetting to zero,
>>      but writes the actual 'set' value when not zero
>>    - Uses a 32-bit microsecond based timebase:
>> 	static unsigned long get_usec (void)
>> 	{
>> 	...
>> 	}
>>
>> 	get_timer(ulong base)
>> 	{
>> 		return (get_usec() / 1000) - base;
>> 	}
>>
>>    - Timer will wrap after ~4295 seconds (71 minutes)
>>
>> [2] Sane means something close to:
>> 	void reset_timer (void)
>> 	{
>> 		timestamp = 0;
>> 	}
>>
>> 	ulong get_timer(ulong base)
>> 	{
>> 		return timestamp - base;
>> 	}
>>
>> 	void set_timer(ulong t)
>> 	{
>> 		timestamp = t;
>> 	}
>>
>> Rationalising the API
>> =====================
>> Realistically, the value of the free running timer at the start of a timing
>> operation is irrelevant (even if the counter wraps during the timed period).
>> Moreover, using reset_timer() and set_timer() makes nested usage of the
>> timer API impossible. So in theory, the entire API could be reduced to
>> simply get_timer()
> Full ACK here !!!
>> 0. Fix arch/arm/cpu/sa1100/timer.c:get_timer()
>> ----------------------------------------------
>> This appears to be the only get_timer() which does not subtract the
>> argument from timestamp
>>
>> 1. Remove set_timer()
>> ---------------------
>> regex "[^e]set_timer\s*\([^)]*\);" reveals 14 call sites for set_timer()
>> and all except arch/sh/lib/time_sh2:[timer_init(),reset_timer()] are
>> set_timer(0). The code in arch/sh is trivial to resolve in order to
>> remove set_timer()
>>
>> 2. Remove reset_timer()
>> -----------------------------------------------
>> regex "[\t ]*reset_timer\s*\([^)]*\);" reveals 22 callers across the
>> following groups:
>>    - timer_init() - Make reset_timer() static or fold into timer_init()
>>    - board_init_r() - Unnecessary
>>    - arch/m68k/lib/time.c:wait_ticks() - convert[3]
>>    - Board specific flash drivers - convert[3]
>>    - drivers/block/mg_disk.c:mg_wait() - Unnecessary
>>    - drivers/mtd/cfi_flash.c:flash_status_check() - Unnecessary
>>    - drivers/mtd/cfi_flash.c:flash_status_poll() - Unnecessary
>>
>> [3] These instance can be trivially converted to use one of the three
>> examples at the beginning of this document
>>
>> 3. Remove reset_timer_masked()
>> ------------------------------
>> This is only implemented in arm but has propagated outside arch/arm and
>> into board/ and drivers/ (bad!)
>>
>> regex "[\t ]*reset_timer_masked\s*\([^)]*\);" reveals 135 callers!
>>
>> A lot are in timer_init() and reset_timer(), but the list includes:
>>    - arch/arm/cpu/arm920t/at91rm9200/spi.c:AT91F_SpiWrite()
>>    - arch/arm/cpu/arm926ejs/omap/timer.c:__udelay()
>>    - arch/arm/cpu/arm926ejs/versatile/timer.c:__udelay()
>>    - arch/arm/armv7/s5p-common/timer.c:__udelay()
>>    - arch/arm/lh7a40x/timer.c:__udelay()
>>    - A whole bunch of board specific flash drivers
>>    - board/mx1ads/syncflash.c:flash_erase()
>>    - board/trab/cmd_trab.c:do_burn_in()
>>    - board/trab/cmd_trab.c:led_blink()
>>    - board/trab/cmd_trab.c:do_temp_log()
>>    - drivers/mtd/spi/eeprom_m95xxx.c:spi_write()
>>    - drivers/net/netarm_eth.c:na_mii_poll_busy()
>>    - drivers/net/netarm_eth.c:reset_eth()
>>    - drivers/spi/atmel_dataflash_spi.c/AT91F_SpiWrite()
> Fixed in current master.
>> Most of these instance can be converted to use one of the three examples
>> at the beginning of this document, but __udelay() will need closer
>> examination
>>
>> This is preventing nesting of timed code - Any code which uses udelay()
>> has the potential to foul up outer-loop timers. The problem is somewhat
>> unique to ARM though
>>
>> 4. Implement microsecond API - get_usec_timer()
>> -----------------------------------------------
>>    - Useful for profiling
>>    - A 32-bit microsecond counter wraps in 71 minutes - Probably OK for most
>>      U-Boot usage scenarios
>>    - By default could return get_timer() * 1000 if hardware does not support
>>      microsecond accuracy - Beware of results>   32 bits!
>>    - If hardware supports microsecond resolution counters, get_timer() could
>>      simply use get_usec_timer() / 1000
> That is wrong. Dividing 32 bits by any number will result in a result that does not
> exploit the full 32 bit range, i.e. wrap from (0xffffffff/1000) to 0x00000000,
> which makes time differences go wrong when they span across such a wrap!
Hi All,
       True, as previously discussed.
>>    - get_usec_timer_64() could offer a longer period (584942 years!)
> Correct. And a "must be" when one uses such division.
>
> But you have to realize that most hardware does not provide a simple means to
> implement a timer that runs in either exact microseconds or exact milliseconds.
Also True.
> Powerpc for example has a 64 bit free running hardware counter at CPU clock,
> which can be in the GHz range, making the lower 32 bits overflow within seconds,
> so the full 64 bits MUST BE used to obtain a millisecond timer by division.
       This statement, as written, is false. While it is true that the 
power PC (and others) have a 64 bit counter that runs at a many 
megahertz rate, it is NOT true that all 64 bits must be used to obtain a 
millisecond timer. A millisecond timer can be produced by using the 33 
bits of the 64 bit counter whose lsb is <= 1 ms and > 0.5 ms. This value 
can be extracted by a right shift and masking of the 64 bit counter. Two 
32 bit multiplies and adds will produce a correct monotonic 1 ms timer. 
This is certainly the best way to go on systems that do not have a 
hardware 64 bit by 32 bit divide. See the thread "ARM timing code 
refactoring" for an example of how this can be done. This timer will 
NEVER result in a wrong value, although it does loose  1 ms every 1193 
hours.
> arm/at91 has a timer that can be made to appear like a 32 bit free running counter
> at some fraction of cpu clock (can be brought into a few MHz value by a prescaler)
> and the current implementation extends this to 64 bits by software, so it is
> similar to powerpc.
>
> A get timer() simply uses this 64 bit value by dividing it by (tickrate/1000).
Or as above on the PPC
> Of course this results in a wrong wrap "gigaseconds" after the timer has been started,
> but certainly this can be ignored...
FWIW, this does not happen with the shift and multiply approach.
> On any account, I see only the following two functions to be implemented for use by
> other u-boot code parts:
>
> 1. void udelay(u32 microseconds) with the following properties:
> - must not affect get_timer() results
> - must not delay less than the given time, may delay longer
> (this might be true especially for very small delay values)
> - shall not be used for delays in the seconds range and longer
> (or any other limit we see practical)
> Note: a loop doing "n" udelays of "m" microseconds might take _much_ longer than
> "n * m" microseconds and therefore is the wrong approach to implement a timeout.
> get_timer() must be used for any such timeouts instead!
>
> 2. u32 get_timer(u32 base) with the following properties:
> - must return the elapsed milliseconds since base
> - must work without wrapping problems for at least several hours
>
> Best Regards,
> Reinhard
I think this is a correct appreciation of what is needed.

Best Regards.
Bill Campbell
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  6:23   ` Graeme Russ
@ 2011-05-22  7:21     ` J. William Campbell
  2011-05-22  7:44       ` Graeme Russ
  2011-05-22  8:15       ` Reinhard Meyer
  0 siblings, 2 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-22  7:21 UTC (permalink / raw)
  To: u-boot

On 5/21/2011 11:23 PM, Graeme Russ wrote:
> On 22/05/11 14:26, Reinhard Meyer wrote:
>> Dear Graeme Russ,
>>> Hi All,
>>>
>>> I've just had a good look through the timer API code with the view of
>>> rationalising it and fixing up some of the inconsistencies. What I found
>>> was a little scarier than I expected! Anyway, here is a write-up of what I
>>> found - Please comment
>> We have been at this discussion a multiple of times :) but never reached a
>> consent.
>>
>> However, at current master, I have reduced at91 architecture to only use
>> get_timer(base), set_timer() never existed and reset_timer() has been removed.
> Excellent
>
>> As it showed up recently, common cfi code still calls reset_timer() - which
>> certainly
>> can be fixed with little effort...
> Yes, this is one of the easy fixes as all call sites already use the start
> = get_timer(0), elapsed = get_timer(start) convention anyway - The
> reset_timer() calls are 100% redundant (provided get_timer() behaves
> correctly at the 32-bit rollover for all arches)
>
>>> The U-Boot timer API is not a 'callback' API and cannot 'trigger' a
>>> function call after a pre-determined time.
>> that would be too complex to implement and of little use in a single task
>> system. u-boot can do fine with polling.
> I am in no way suggesting this - I just want to clarify the API for anyone
> who needs to use it
>
>>> NOTE: http://lists.denx.de/pipermail/u-boot/2010-June/073024.html appears
>>> to imply the following implementation of get_timer() is wrong:
>>>
>>>      ulong get_timer(ulong base)
>>>      {
>>>          return get_timer_masked() - base;
>>>      }
>> Is is not wrong as long as get_timer_masked() returns the full 32 bit space
>> of numbers and 0xffffffff is followed by 0x00000000. Most implementations
>> probably do NOT have this property.
>>> U-Boot Timer API Details
>>> ========================
>>> There are currently three functions in the U-Boot timer API:
>>>      ulong get_timer(ulong start_time)
>> As you point out in the following, this is the only function required.
>> However it REQUIRES that the internal timer value must exploit the full
>> 32 bit range of 0x00000000 to 0xffffffff before it wraps back to 0x00000000.
> So this needs to be clearly spelt out in formal documentation
>
>>> Rationalising the API
>>> =====================
>>> Realistically, the value of the free running timer at the start of a timing
>>> operation is irrelevant (even if the counter wraps during the timed period).
>>> Moreover, using reset_timer() and set_timer() makes nested usage of the
>>> timer API impossible. So in theory, the entire API could be reduced to
>>> simply get_timer()
>> Full ACK here !!!
> I don't think there will be much resistance to this
>
>>> 3. Remove reset_timer_masked()
>>> ------------------------------
>>> This is only implemented in arm but has propagated outside arch/arm and
>>> into board/ and drivers/ (bad!)
>>>
>>> regex "[\t ]*reset_timer_masked\s*\([^)]*\);" reveals 135 callers!
>>>
>>> A lot are in timer_init() and reset_timer(), but the list includes:
>>>    - arch/arm/cpu/arm920t/at91rm9200/spi.c:AT91F_SpiWrite()
>>>    - arch/arm/cpu/arm926ejs/omap/timer.c:__udelay()
>>>    - arch/arm/cpu/arm926ejs/versatile/timer.c:__udelay()
>>>    - arch/arm/armv7/s5p-common/timer.c:__udelay()
>>>    - arch/arm/lh7a40x/timer.c:__udelay()
>>>    - A whole bunch of board specific flash drivers
>>>    - board/mx1ads/syncflash.c:flash_erase()
>>>    - board/trab/cmd_trab.c:do_burn_in()
>>>    - board/trab/cmd_trab.c:led_blink()
>>>    - board/trab/cmd_trab.c:do_temp_log()
>>>    - drivers/mtd/spi/eeprom_m95xxx.c:spi_write()
>>>    - drivers/net/netarm_eth.c:na_mii_poll_busy()
>>>    - drivers/net/netarm_eth.c:reset_eth()
>>>    - drivers/spi/atmel_dataflash_spi.c/AT91F_SpiWrite()
>> Fixed in current master.
> Excellent. I have not pulled master for a little while, guess I should
>
>>>    - If hardware supports microsecond resolution counters, get_timer() could
>>>      simply use get_usec_timer() / 1000
>> That is wrong. Dividing 32 bits by any number will result in a result that
>> does not
>> exploit the full 32 bit range, i.e. wrap from (0xffffffff/1000) to 0x00000000,
>> which makes time differences go wrong when they span across such a wrap!
>>
> Yes, this has already been pointer out - 42 bits are needed as a bare
> minimum. However, we can get away with 32-bits provided get_timer() is
> called at least every 71 minutes
>
> P.S. Can we use the main loop to kick the timer?
>
>>>    - get_usec_timer_64() could offer a longer period (584942 years!)
>> Correct. And a "must be" when one uses such division.
> Unless we can rely on get_timer() to be called at least every 71 minutes in
> which case we can handle the msb's without error in software
>
>> But you have to realize that most hardware does not provide a simple means to
>> implement a timer that runs in either exact microseconds or exact
>> milliseconds.
> This is where things get interesting and we need to start pushing a
> mandated low-level HAL. For example, I believe get_timer() should be
> implemented in /lib as:
>
> 	ulong get_timer(ulong base)
> 	{
> 		return get_raw_msec() - base;
> 	}
>
> get_raw_ms() MUST:
>   - Return an unsigned 32-but value which increments every 1ms
>   - Wraps from 0xffffffff to 0x00000000
>   - Be atomic (no possibility of corruption by an interrupt)
Hi All,
       I agree that a mandated HAL would be a real good idea in reducing 
the uncertainty in what is required. This is a very good idea, IMHO.
> The counter behind get_raw_ms() can be maintained by either:
>
>   1. A hardware timer programmed with a 1ms increment
>   2. A hardware timer programmed with a non-1ms increment scaled in software
>   3. A software counter ticked by a 1ms interrupt
>   4. A software counter ticked by a non-1ms interrupt scaled in software
>
> get_raw_ms() does not need a fixed epoch - It could be 1st Jan 1970, the
> date the CPU/SOC was manufactured, when the device was turned on, your
> eldest child's birthday - whatever. It will not matter provided the counter
> wraps correctly
>
>> Powerpc for example has a 64 bit free running hardware counter at CPU clock,
>> which can be in the GHz range, making the lower 32 bits overflow within
>> seconds,
>> so the full 64 bits MUST BE used to obtain a millisecond timer by division.
>> arm/at91 has a timer that can be made to appear like a 32 bit free running
>> counter
>> at some fraction of cpu clock (can be brought into a few MHz value by a
>> prescaler)
>> and the current implementation extends this to 64 bits by software, so it is
>> similar to powerpc.
> So these are all examples of #2
>
> x86 is an example of #3
>
>> A get timer() simply uses this 64 bit value by dividing it by (tickrate/1000).
>>
>> Of course this results in a wrong wrap "gigaseconds" after the timer has
>> been started,
>> but certainly this can be ignored...
> Strictly speaking, I don't think we should allow this - There should never
> be timer glitches
Agreed, although this glitch probably would never be observed.
>> On any account, I see only the following two functions to be implemented
>> for use by
>> other u-boot code parts:
>>
>> 1. void udelay(u32 microseconds) with the following properties:
>> - must not affect get_timer() results
> Absolutely
>
>> - must not delay less than the given time, may delay longer
>> (this might be true especially for very small delay values)
> Hadn't though about that, but OK
>
>> - shall not be used for delays in the seconds range and longer
>> (or any other limit we see practical)
> Any udelay up to the full range of a ulong should be handled without error
> by udelay() - If the arch dependant implementation of udelay() uses
> get_timer() to implement long delays due to hardware limitations then that
> should be fine.
I wonder about this requirement. I think it might be better to say that 
udelay can only be used up to a delay of a short unsigned (65 ms), If a 
longer delay is required, a get_timer loop should be used.  Since udelay 
uses a different resolution, it implies a more precise delay is 
required. If you are delaying more than 65 ms, I suspect precision is 
not what you are after, and udelay should return an error (not be void). 
This makes implementing udelay a lot easier, in that one can always 
convert the desired time interval into an internal clock resolution 
without difficulty.
>> Note: a loop doing "n" udelays of "m" microseconds might take _much_ longer
>> than
>> "n * m" microseconds and therefore is the wrong approach to implement a
>> timeout.
>> get_timer() must be used for any such timeouts instead!
> ACK - as mentioned, udelay() can use get_timer() of the delay is>>  1ms if
> such an implementation provides better accuracy. If the HAL implementation
> of get_raw_ms() uses a hardware level microsecond time base, there will be
> no accuracy advantage anyway.
What if it provides worse accuracy? It is better if udelay can use the 
hardware timer resolution directly. This is easy if the delay is a short 
unsigned, so the desired delay can be internally expressed as a long 
unsigned in hardware timer ticks. Otherwise, it gets harder, and udelay 
is not oriented towards longer delays. It CAN be done, but why should we?
>> 2. u32 get_timer(u32 base) with the following properties:
>> - must return the elapsed milliseconds since base
> ACK
>
>> - must work without wrapping problems for at least several hours
> Provided that the architecture implementation of get_raw_ms() is
> implemented as described, the only limitation will be the maximum
> measurable delay. The timer API should work correctly no matter how long
> the device has been running
>
> I think the HAL should implement:
> 	- get_raw_ms() - 32-bit millisecond counter
Only the get_raw_ms should be mandatory. I propose adding udelay to the 
HAL, as it is best mechanized at the hardware timer tick level.

> 	- get_raw_us() - 32-bit microsecond counter
Used for performance monitor. Not mandatory.
> 	- get_raw_us64() - 64-bit microsecond counter
I can see no possible use for this in u-boot. What operation that we 
care about could take this long  and require microsecond resolution? 71 
seconds is certainly long enough for anything this precise. This 
certainly should NOT be mandatory. 64 bits is not for free on many 
processors.

Best Regards,
Bill Campbell
> Regards,
>
> Graeme
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  7:21     ` J. William Campbell
@ 2011-05-22  7:44       ` Graeme Russ
  2011-05-22  8:15       ` Reinhard Meyer
  1 sibling, 0 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-22  7:44 UTC (permalink / raw)
  To: u-boot

On 22/05/11 17:21, J. William Campbell wrote:
> On 5/21/2011 11:23 PM, Graeme Russ wrote:
>> On 22/05/11 14:26, Reinhard Meyer wrote:

>>> - shall not be used for delays in the seconds range and longer
>>> (or any other limit we see practical)
>> Any udelay up to the full range of a ulong should be handled without error
>> by udelay() - If the arch dependant implementation of udelay() uses
>> get_timer() to implement long delays due to hardware limitations then that
>> should be fine.
> I wonder about this requirement. I think it might be better to say that
> udelay can only be used up to a delay of a short unsigned (65 ms), If a

We would have to change the prototype for udelay()

> longer delay is required, a get_timer loop should be used.  Since udelay
> uses a different resolution, it implies a more precise delay is required.

Agree

> If you are delaying more than 65 ms, I suspect precision is not what you
> are after, and udelay should return an error (not be void). This makes
> implementing udelay a lot easier, in that one can always convert the
> desired time interval into an internal clock resolution without difficulty.

Who is ever going to check if udelay() returned an error? It is a primitive
that one assumes 'just works' and should work for all possible parameter values

>>> Note: a loop doing "n" udelays of "m" microseconds might take _much_ longer
>>> than
>>> "n * m" microseconds and therefore is the wrong approach to implement a
>>> timeout.
>>> get_timer() must be used for any such timeouts instead!
>> ACK - as mentioned, udelay() can use get_timer() of the delay is>>  1ms if
>> such an implementation provides better accuracy. If the HAL implementation
>> of get_raw_ms() uses a hardware level microsecond time base, there will be
>> no accuracy advantage anyway.
> What if it provides worse accuracy? It is better if udelay can use the
> hardware timer resolution directly. This is easy if the delay is a short
> unsigned, so the desired delay can be internally expressed as a long
> unsigned in hardware timer ticks. Otherwise, it gets harder, and udelay is
> not oriented towards longer delays. It CAN be done, but why should we?

What if the udelay parameter is calculated? You would then need an explicit
check for >65ms - Seems a bit onerous if you're expecting to occasionally
(if ever) to exceed this, but it not being out of the realm of possibility

>>> 2. u32 get_timer(u32 base) with the following properties:
>>> - must return the elapsed milliseconds since base
>> ACK
>>
>>> - must work without wrapping problems for at least several hours
>> Provided that the architecture implementation of get_raw_ms() is
>> implemented as described, the only limitation will be the maximum
>> measurable delay. The timer API should work correctly no matter how long
>> the device has been running
>>
>> I think the HAL should implement:
>>     - get_raw_ms() - 32-bit millisecond counter
> Only the get_raw_ms should be mandatory. I propose adding udelay to the
> HAL, as it is best mechanized at the hardware timer tick level.
> 
>>     - get_raw_us() - 32-bit microsecond counter
> Used for performance monitor. Not mandatory.

True, but useful

>>     - get_raw_us64() - 64-bit microsecond counter
> I can see no possible use for this in u-boot. What operation that we care
> about could take this long  and require microsecond resolution? 71 seconds

*cough* minutes *cough* ;)

> is certainly long enough for anything this precise. This certainly should
> NOT be mandatory. 64 bits is not for free on many processors.

True - I agree there is no need for it

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  7:21     ` J. William Campbell
  2011-05-22  7:44       ` Graeme Russ
@ 2011-05-22  8:15       ` Reinhard Meyer
  2011-05-23  0:02         ` Graeme Russ
  2011-05-23  0:14         ` J. William Campbell
  1 sibling, 2 replies; 101+ messages in thread
From: Reinhard Meyer @ 2011-05-22  8:15 UTC (permalink / raw)
  To: u-boot

Dear J. William Campbell,

please demonstrate for me (and others), by a practical example,
how _any_ arithmetic (even less with just shifts and multiplies)
can convert a free running 3.576 MHz (wild example) free running
32 bit counter (maybe software extended to 64 bits) into a ms
value that will properly wrap from 2**32-1 to 0 ?

I fail to see how that will be possible...

Best Regards,
Reinhard

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  8:15       ` Reinhard Meyer
@ 2011-05-23  0:02         ` Graeme Russ
  2011-05-23  0:20           ` J. William Campbell
  2011-05-23  0:14         ` J. William Campbell
  1 sibling, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-23  0:02 UTC (permalink / raw)
  To: u-boot

Dear Reinhard,

On Sun, May 22, 2011 at 6:15 PM, Reinhard Meyer
<u-boot@emk-elektronik.de> wrote:
> Dear J. William Campbell,
>
> please demonstrate for me (and others), by a practical example,
> how _any_ arithmetic (even less with just shifts and multiplies)
> can convert a free running 3.576 MHz (wild example) free running
> 32 bit counter (maybe software extended to 64 bits) into a ms
> value that will properly wrap from 2**32-1 to 0 ?
>
> I fail to see how that will be possible...

These may help:

http://blogs.msdn.com/b/devdev/archive/2005/12/12/502980.aspx
http://www.hackersdelight.org/divcMore.pdf

of Google 'division of unsigned integer by a constant'

Basically you will be dividing by a constant value of 3576 which can be
highly optimised

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  8:15       ` Reinhard Meyer
  2011-05-23  0:02         ` Graeme Russ
@ 2011-05-23  0:14         ` J. William Campbell
  2011-05-23  1:00           ` Graeme Russ
  2011-05-23  3:26           ` Reinhard Meyer
  1 sibling, 2 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-23  0:14 UTC (permalink / raw)
  To: u-boot

On 5/22/2011 1:15 AM, Reinhard Meyer wrote:
> Dear J. William Campbell,
>
> please demonstrate for me (and others), by a practical example,
> how _any_ arithmetic (even less with just shifts and multiplies)
> can convert a free running 3.576 MHz (wild example) free running
> 32 bit counter (maybe software extended to 64 bits) into a ms
> value that will properly wrap from 2**32-1 to 0 ?
Hi All
       I accept the challenge! I will present two ways to do this, one 
using a 32 bit by 16 bit divide, and one using only multiplies.
This first method is "exact", in that there is no difference in 
performance from a "hardware" counter ticking at the 1 ms rate. This is 
accomplished by operating the 1 ms counter based on the delta time in 
the hardware time base. It is necessary to call this routine often 
enough that the hardware counter does not wrap more than once between 
calls. This is not really a problem, as this time is 1201 seconds or so. 
If the routine is not called for a long time, or at the first call, it 
will return a timer_in_ms value that will work for all subsequent calls 
that are within a hardware rollover interval. Since the timer in ms is a 
32 bit number anyway. The same rollover issue will exist if you 
"software extend" the timer to 64 bits. You must assume 1 rollover. If 
it is more than 1, the timer is wrong.


The variables in the gd are
u32 prev_timer;
u32 timer_in_ms;
u16 timer_remainder;

/* gd->timer remainder must be initialized to 0 (actually, an number 
less than 3576, but 0 is nice). Other two variables don't matter but can 
be initialized if desired  */

u32 get_raw_ms()
{
         u32 delta;
        u32  t_save;

       read(t_save);   /* atomic read of the hardware 32 bit timer 
running at 3.576 MHz */
       delta_t = (t_save  - gd->prev_timer) ;

       gd->prev_timer =  t_save;
      /*
        Hopefully, the following two lines only results in one hardware 
divide when optimized. If your CPU has no hardware divide, or if it 
slow, see second method .
     */
      gd->timer_in_ms += delta_t  / 3576; /* convert elapsed time to ms */
      gd->timer_remainder += delta_t  % 3576; /* add in remaining part 
not included above */
      if (gd->timer_remainder >= 3576) /* a carry has been detected */
     {
        ++gd->timer_in_ms;
        gd->timer_remainder -= 3576; /* fix remainder for the carry above */
     }

      return(gd->timer_in_ms)
}

This approach works well when the number of ticks per ms is an exact 
number representable as a small integer, as it is in this case. It is 
exact with a clock rate of 600 MHz, but is not exact for a clock rate of 
666 MHz. 666667 is not an exact estimate of ticks per ms, It is off by 
0.00005 % That should be acceptable for use as a timeout delay. The 
accumulated error in a 10 second delay should be less than 0.5 ms.

There is a way that the divide above can be approximated by multiplying 
by an appropriate fraction, taking the resulting delta t in ms, 
multiplying it by 3576, and subtracting the product from the original 
delta to get the remainder.  This is the way to go if your CPU divides 
slowly or not at all. This approach is presented below.

the vaues in gd are as follows:

u32 prev_timer;
u32 timer_in_ms;

/*
     One tick of the 3.576 MHz timer corresponds to 1/3.576/1000 ms,
     or 0.000279642 ms. Scale the fraction by 65536 (16 bit shift),
     you get 37532.9217
*/
u32 get_raw_ms(void)
{
   u32  t_save;
   u32  temp;

   /* read the hardware 32 bit timer running at 3.576 MHz */
   read_timer_atomic(t_save);
   t_save         -= gd->prev_timer; /* get "delta time" since last call */
   gd->prev_timer += t_save; /* assume we will use all of the counts */

   /*
    * This first while loop is entered for any delta time > about 18.3 
ms. The
    * while loop will execute twice 2.734% of the time, otherwise once.
    */
   while (t_save > 65535)
   {
     temp = t_save >> 16;   /* extract msb */
     temp  = ((temp * 37532) + ((temp * 60404) >> 16)) >> 11;
     /* temp  = (temp * 37532) >> 11; */
     gd->timer_in_ms += temp;
     t_save          -= temp * 3576;
   }
   /*
    * This second while loop is entered for 94.837% of all possible 
delta times,
    * 0 through 0XFFFFFFFF. The second while loop will execute twice 
0.037% of
    * the time, otherwise once.
    */
   while (t_save >= 3576)
   {
     temp  = (t_save * 37532) >> (16 + 11);
     if (temp == 0)
       temp = 1;     /* we know that 1 works for sure */
     gd->timer_in_ms += temp;
     t_save          -= temp * 3576;
   }
   gd->prev_timer -= t_save; /* restore any counts we didn't use this 
time */
   return gd->timer_in_ms;
}

I have tested this code and it seems to work fine for me. I have 
attached a more readable copy as "example .c" for those who wish to play 
around with it. In my original post, I had a version of this code that 
could be used with different clock rates. I can provide the same 
functionality with this code, for CPUs/systems where the clock rate is 
unknown at compile time or is variable. I can also address the error 
encountered by non-integer ticks per millisecond, if people really think 
the error is enough to matter, but I won't post it unless people want to 
see it.

Best Regards,
Bill Campbell




>
> I fail to see how that will be possible...
>
> Best Regards,
> Reinhard
>
>

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: example.c
Url: http://lists.denx.de/pipermail/u-boot/attachments/20110522/8aee390d/attachment.txt 

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  0:02         ` Graeme Russ
@ 2011-05-23  0:20           ` J. William Campbell
  0 siblings, 0 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-23  0:20 UTC (permalink / raw)
  To: u-boot

On 5/22/2011 5:02 PM, Graeme Russ wrote:
> Dear Reinhard,
>
> On Sun, May 22, 2011 at 6:15 PM, Reinhard Meyer
> <u-boot@emk-elektronik.de>  wrote:
>> Dear J. William Campbell,
>>
>> please demonstrate for me (and others), by a practical example,
>> how _any_ arithmetic (even less with just shifts and multiplies)
>> can convert a free running 3.576 MHz (wild example) free running
>> 32 bit counter (maybe software extended to 64 bits) into a ms
>> value that will properly wrap from 2**32-1 to 0 ?
>>
>> I fail to see how that will be possible...
> These may help:
>
> http://blogs.msdn.com/b/devdev/archive/2005/12/12/502980.aspx
> http://www.hackersdelight.org/divcMore.pdf
>
> of Google 'division of unsigned integer by a constant'
>
> Basically you will be dividing by a constant value of 3576 which can be
> highly optimised
Hi All,
        Yes, you can do it this way. I prefer not to use properties of 
the constant because it doesn't allow multiple clock rates easily. The 
code I posted just a moment ago is easy to change for different rates 
because it does not rely much on the exact bit structure of 3576.
There are simple formulas for all the "magic numbers" in what I posted, 
so it is easy to change the input frequency.
Best Regards,
Bill Campbell
> Regards,
>
> Graeme
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  0:14         ` J. William Campbell
@ 2011-05-23  1:00           ` Graeme Russ
       [not found]             ` <4DD9B608.7080307@comcast.net>
  2011-05-23  3:26           ` Reinhard Meyer
  1 sibling, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-23  1:00 UTC (permalink / raw)
  To: u-boot

Hi Bill,

On Mon, May 23, 2011 at 10:14 AM, J. William Campbell
<jwilliamcampbell@comcast.net> wrote:
> On 5/22/2011 1:15 AM, Reinhard Meyer wrote:
>>
>> Dear J. William Campbell,
>>
>> please demonstrate for me (and others), by a practical example,
>> how _any_ arithmetic (even less with just shifts and multiplies)
>> can convert a free running 3.576 MHz (wild example) free running
>> 32 bit counter (maybe software extended to 64 bits) into a ms
>> value that will properly wrap from 2**32-1 to 0 ?
>
> Hi All
> ? ? ?I accept the challenge! I will present two ways to do this, one using a

[Snip first method]

> There is a way that the divide above can be approximated by multiplying by
> an appropriate fraction, taking the resulting delta t in ms, multiplying it
> by 3576, and subtracting the product from the original delta to get the
> remainder. ?This is the way to go if your CPU divides slowly or not at all.
> This approach is presented below.
>
> the vaues in gd are as follows:
>
> u32 prev_timer;
> u32 timer_in_ms;
>
> /*
> ? ?One tick of the 3.576 MHz timer corresponds to 1/3.576/1000 ms,
> ? ?or 0.000279642 ms. Scale the fraction by 65536 (16 bit shift),
> ? ?you get 37532.9217
> */
> u32 get_raw_ms(void)
> {
> ?u32 ?t_save;
> ?u32 ?temp;
>
> ?/* read the hardware 32 bit timer running at 3.576 MHz */
> ?read_timer_atomic(t_save);
> ?t_save ? ? ? ? -= gd->prev_timer; /* get "delta time" since last call */
> ?gd->prev_timer += t_save; /* assume we will use all of the counts */
>
> ?/*
> ? * This first while loop is entered for any delta time > about 18.3 ms. The
> ? * while loop will execute twice 2.734% of the time, otherwise once.
> ? */
> ?while (t_save > 65535)
> ?{
> ? ?temp = t_save >> 16; ? /* extract msb */
> ? ?temp ?= ((temp * 37532) + ((temp * 60404) >> 16)) >> 11;

Where does 60404 come from?

> ? ?/* temp ?= (temp * 37532) >> 11; */
> ? ?gd->timer_in_ms += temp;
> ? ?t_save ? ? ? ? ?-= temp * 3576;
> ?}
> ?/*
> ? * This second while loop is entered for 94.837% of all possible delta
> times,
> ? * 0 through 0XFFFFFFFF. The second while loop will execute twice 0.037% of
> ? * the time, otherwise once.
> ? */
> ?while (t_save >= 3576)
> ?{
> ? ?temp ?= (t_save * 37532) >> (16 + 11);
> ? ?if (temp == 0)
> ? ? ?temp = 1; ? ? /* we know that 1 works for sure */
> ? ?gd->timer_in_ms += temp;
> ? ?t_save ? ? ? ? ?-= temp * 3576;
> ?}
> ?gd->prev_timer -= t_save; /* restore any counts we didn't use this time */
> ?return gd->timer_in_ms;
> }
>
> I have tested this code and it seems to work fine for me. I have attached a
> more readable copy as "example .c" for those who wish to play around with
> it. In my original post, I had a version of this code that could be used
> with different clock rates. I can provide the same functionality with this
> code, for CPUs/systems where the clock rate is unknown at compile time or is
> variable. I can also address the error encountered by non-integer ticks per
> millisecond, if people really think the error is enough to matter, but I
> won't post it unless people want to see it.

Provided the hardware counter has high enough resolution (in this case an
extra 12 bits meaning the counter must be at least 44 bits) I assume this
methog guarantees full 32-bit resolution with correct roll-over, but if
the hardware counter is only 32-bit we run into problems. And does this
solution work for, say, the entire range of a 64-bit hardware counter
including when it wraps?

Questions:
 - If the hardware supports a native 64-bit counter, could we have a
   u64 get_raw_ticks64() HAL API and 'libify' the above function using
   either a 'tick rate' in gd or a get_tick_rate() HAL function
 - Can we reduce the HAL to u32 get_raw_ticks() and make some assumptions
   about how often get_raw_ms() is called (maybe in the main loop for
   example - We already call the watchdog periodically anyway)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
       [not found]             ` <4DD9B608.7080307@comcast.net>
@ 2011-05-23  1:42               ` Graeme Russ
  2011-05-23  5:02                 ` J. William Campbell
  2011-05-23 12:09                 ` Wolfgang Denk
  0 siblings, 2 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-23  1:42 UTC (permalink / raw)
  To: u-boot

OK, so in summary, we can (in theory) have:
 - A timer API in /lib/ with a single u32 get_timer(u32 base) function
 - A HAL with two functions
   - u32 get_raw_ticks()
   - u32 get_raw_tick_rate() which returns the tick rate in kHz (which
     max's out at just after 4GHz)
 - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
   and get_tick_rate() to correctly maintain the ms counter used by
   get_timer() - This function can be weak (so next point)
 - If the hardware supports a native 32-bit ms counter, get_raw_ms()
   can be overridden to simply return the hardware counter. In this case,
   get_raw_ticks() would return 1
 - Calling of get_raw_ticks() regularly in the main loop (how ofter will
   depend on the raw tick rate, but I image it will never be necessary
   to call more often than once every few minutes)
 - If the hardware implements a native 32-bit 1ms counter, no call in
   the main loop is required
 - An optional HAL function u32 get_raw_us() which can be used for
   performance profiling (must wrap correctly)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  0:14         ` J. William Campbell
  2011-05-23  1:00           ` Graeme Russ
@ 2011-05-23  3:26           ` Reinhard Meyer
  2011-05-23  5:20             ` J. William Campbell
  1 sibling, 1 reply; 101+ messages in thread
From: Reinhard Meyer @ 2011-05-23  3:26 UTC (permalink / raw)
  To: u-boot

Dear J. William Campbell,
> On 5/22/2011 1:15 AM, Reinhard Meyer wrote:
>> Dear J. William Campbell,
>>
>> please demonstrate for me (and others), by a practical example,
>> how _any_ arithmetic (even less with just shifts and multiplies)
>> can convert a free running 3.576 MHz (wild example) free running
>> 32 bit counter (maybe software extended to 64 bits) into a ms
>> value that will properly wrap from 2**32-1 to 0 ?
> Hi All
> I accept the challenge! I will present two ways to do this, one using a 32 bit by 16 bit divide, and one using only multiplies.
> This first method is "exact", in that there is no difference in performance from a "hardware" counter ticking at the 1 ms rate. This is accomplished by operating the 1 ms counter based on the delta time in the hardware time base. It is necessary to call this routine often enough that the hardware counter does not wrap more than once between calls. This is not really a problem, as this time is 1201 seconds or so. If the routine is not called for a long time, or at the first call, it will return a timer_in_ms value that will work for all subsequent calls that are within a hardware rollover interval. Since the timer in ms is a 32 bit number anyway. The same rollover issue will exist if you "software extend" the timer to 64 bits. You must assume 1 rollover. If it is more than 1, the timer is wrong.
>
>
> The variables in the gd are
> u32 prev_timer;
> u32 timer_in_ms;
> u16 timer_remainder;
>
> /* gd->timer remainder must be initialized to 0 (actually, an number less than 3576, but 0 is nice). Other two variables don't matter but can be initialized if desired */
>
> u32 get_raw_ms()
> {
> u32 delta;
> u32 t_save;
>
> read(t_save); /* atomic read of the hardware 32 bit timer running at 3.576 MHz */
> delta_t = (t_save - gd->prev_timer) ;
>
> gd->prev_timer = t_save;
> /*
> Hopefully, the following two lines only results in one hardware divide when optimized. If your CPU has no hardware divide, or if it slow, see second method .
> */
> gd->timer_in_ms += delta_t / 3576; /* convert elapsed time to ms */
> gd->timer_remainder += delta_t % 3576; /* add in remaining part not included above */
> if (gd->timer_remainder >= 3576) /* a carry has been detected */
> {
> ++gd->timer_in_ms;
> gd->timer_remainder -= 3576; /* fix remainder for the carry above */
> }
>
> return(gd->timer_in_ms)
> }

Thank you! Basically this is similar to a Bresenham Algorithm.

>
> This approach works well when the number of ticks per ms is an exact number representable as a small integer, as it is in this case. It is exact with a clock rate of 600 MHz, but is not exact for a clock rate of 666 MHz. 666667 is not an exact estimate of ticks per ms, It is off by 0.00005 % That should be acceptable for use as a timeout delay. The accumulated error in a 10 second delay should be less than 0.5 ms.

I would think the non exact cases result in such a small error that can be
tolerated. We are using the ms tick for timeouts, not for providing a clock
or exact delays. We should just round up when calculating the divider.

Hence the hick-ups that result when this is not called frequent enough to
prevent a multiple rollover of the raw value between calls do not matter
either (they should be just documented).

>
> There is a way that the divide above can be approximated by multiplying by an appropriate fraction, taking the resulting delta t in ms, multiplying it by 3576, and subtracting the product from the original delta to get the remainder. This is the way to go if your CPU divides slowly or not at all. This approach is presented below.
>
[...]

Optimizations would be up to the implementer of such a hardware and work
only if the divider is a compile time constant. Often the divider will be
run time determined (AT91 for example).

Reinhard

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  1:42               ` Graeme Russ
@ 2011-05-23  5:02                 ` J. William Campbell
  2011-05-23  5:25                   ` Graeme Russ
  2011-05-23 12:09                 ` Wolfgang Denk
  1 sibling, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-23  5:02 UTC (permalink / raw)
  To: u-boot

On 5/22/2011 6:42 PM, Graeme Russ wrote:
> OK, so in summary, we can (in theory) have:
>   - A timer API in /lib/ with a single u32 get_timer(u32 base) function
>   - A HAL with two functions
>     - u32 get_raw_ticks()
>     - u32 get_raw_tick_rate() which returns the tick rate in kHz (which
>       max's out at just after 4GHz)
>   - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>     and get_tick_rate() to correctly maintain the ms counter used by
>     get_timer() - This function can be weak (so next point)
>   - If the hardware supports a native 32-bit ms counter, get_raw_ms()
>     can be overridden to simply return the hardware counter. In this case,
>     get_raw_ticks() would return 1
>   - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>     depend on the raw tick rate, but I image it will never be necessary
>     to call more often than once every few minutes)
>   - If the hardware implements a native 32-bit 1ms counter, no call in
>     the main loop is required
>   - An optional HAL function u32 get_raw_us() which can be used for
>     performance profiling (must wrap correctly)
Hi All,
       Graeme, I think you have stated exactly what is the "best" 
approach to this problem.  I will provide a version of "get_raw_ms" that 
is  initialized using get_raw_tick_rate that will work for all 
"reasonable" values of raw_tick_rate. This will be the "generic" 
solution. Both the initialization function and the get_raw_ms function 
can be overridden if there is reason to do so, like "exact" clock rates. 
I will do the same with get_raw_us. This will be posted sometime on 
Monday for people to review, and to make sure I didn't get too far off 
base. Thank you to both Graeme and Reinhard for looking at/working on 
this.. Hopefully, this solution will put this timing issue to rest for 
all future ports as well as the presently existing ones.
        On a different note, the "graylisting" application is causing 
some (about half) of my replies to the list from showing up. The 
messages are going to the specified individuals correctly, but not 
always to the list. This is apparently because my ISP has so many 
different network address available that the probability of using the 
same one (or same subnet) is not very high. Is there anything that can 
be done about this?

Best Regards,
Bill Campbell
> Regards,
>
> Graeme
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  3:26           ` Reinhard Meyer
@ 2011-05-23  5:20             ` J. William Campbell
  0 siblings, 0 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-23  5:20 UTC (permalink / raw)
  To: u-boot

On 5/22/2011 8:26 PM, Reinhard Meyer wrote:
> Dear J. William Campbell,
>> On 5/22/2011 1:15 AM, Reinhard Meyer wrote:
>>> Dear J. William Campbell,
>>>
>>> please demonstrate for me (and others), by a practical example,
>>> how _any_ arithmetic (even less with just shifts and multiplies)
>>> can convert a free running 3.576 MHz (wild example) free running
>>> 32 bit counter (maybe software extended to 64 bits) into a ms
>>> value that will properly wrap from 2**32-1 to 0 ?
>> Hi All
>> I accept the challenge! I will present two ways to do this, one using 
>> a 32 bit by 16 bit divide, and one using only multiplies.
>> This first method is "exact", in that there is no difference in 
>> performance from a "hardware" counter ticking at the 1 ms rate. This 
>> is accomplished by operating the 1 ms counter based on the delta time 
>> in the hardware time base. It is necessary to call this routine often 
>> enough that the hardware counter does not wrap more than once between 
>> calls. This is not really a problem, as this time is 1201 seconds or 
>> so. If the routine is not called for a long time, or at the first 
>> call, it will return a timer_in_ms value that will work for all 
>> subsequent calls that are within a hardware rollover interval. Since 
>> the timer in ms is a 32 bit number anyway. The same rollover issue 
>> will exist if you "software extend" the timer to 64 bits. You must 
>> assume 1 rollover. If it is more than 1, the timer is wrong.
>>
>>
>> The variables in the gd are
>> u32 prev_timer;
>> u32 timer_in_ms;
>> u16 timer_remainder;
>>
>> /* gd->timer remainder must be initialized to 0 (actually, an number 
>> less than 3576, but 0 is nice). Other two variables don't matter but 
>> can be initialized if desired */
>>
>> u32 get_raw_ms()
>> {
>> u32 delta;
>> u32 t_save;
>>
>> read(t_save); /* atomic read of the hardware 32 bit timer running at 
>> 3.576 MHz */
>> delta_t = (t_save - gd->prev_timer) ;
>>
>> gd->prev_timer = t_save;
>> /*
>> Hopefully, the following two lines only results in one hardware 
>> divide when optimized. If your CPU has no hardware divide, or if it 
>> slow, see second method .
>> */
>> gd->timer_in_ms += delta_t / 3576; /* convert elapsed time to ms */
>> gd->timer_remainder += delta_t % 3576; /* add in remaining part not 
>> included above */
>> if (gd->timer_remainder >= 3576) /* a carry has been detected */
>> {
>> ++gd->timer_in_ms;
>> gd->timer_remainder -= 3576; /* fix remainder for the carry above */
>> }
>>
>> return(gd->timer_in_ms)
>> }
>
> Thank you! Basically this is similar to a Bresenham Algorithm.
Hi All,
       Yes, I think you are correct. I didn't know it by that name, but 
i think you are correct. It is a bit different use of the idea, but it 
is very similar.
>
>>
>> This approach works well when the number of ticks per ms is an exact 
>> number representable as a small integer, as it is in this case. It is 
>> exact with a clock rate of 600 MHz, but is not exact for a clock rate 
>> of 666 MHz. 666667 is not an exact estimate of ticks per ms, It is 
>> off by 0.00005 % That should be acceptable for use as a timeout 
>> delay. The accumulated error in a 10 second delay should be less than 
>> 0.5 ms.
>
> I would think the non exact cases result in such a small error that 
> can be
> tolerated. We are using the ms tick for timeouts, not for providing a 
> clock
> or exact delays. We should just round up when calculating the divider.
Yes, we should round off the divider value, so 666.6666666666 MHz rounds 
to 666667 ticks/Ms while 333.3333333333 MHz rounds to 333333 ticks/Ms.
>
> Hence the hick-ups that result when this is not called frequent enough to
> prevent a multiple rollover of the raw value between calls do not matter
> either (they should be just documented).
Good, I am glad we agree on this also.
>
>>
>> There is a way that the divide above can be approximated by 
>> multiplying by an appropriate fraction, taking the resulting delta t 
>> in ms, multiplying it by 3576, and subtracting the product from the 
>> original delta to get the remainder. This is the way to go if your 
>> CPU divides slowly or not at all. This approach is presented below.
>>
> [...]
>
> Optimizations would be up to the implementer of such a hardware and work
> only if the divider is a compile time constant. Often the divider will be
> run time determined (AT91 for example).
Correct. I will provide a "generic" version that computes the constants 
at run time.  If the clock rate is a constant, these routines can be 
overridden at compile/link time. This generic version should be 
available on Monday for further review.

Best Regards,
Bill Campbell
>
> Reinhard
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  5:02                 ` J. William Campbell
@ 2011-05-23  5:25                   ` Graeme Russ
  2011-05-23  6:29                     ` Albert ARIBAUD
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-23  5:25 UTC (permalink / raw)
  To: u-boot

On Mon, May 23, 2011 at 3:02 PM, J. William Campbell
<jwilliamcampbell@comcast.net> wrote:
> On 5/22/2011 6:42 PM, Graeme Russ wrote:
>>
>> OK, so in summary, we can (in theory) have:
>> ?- A timer API in /lib/ with a single u32 get_timer(u32 base) function
>> ?- A HAL with two functions
>> ? ?- u32 get_raw_ticks()
>> ? ?- u32 get_raw_tick_rate() which returns the tick rate in kHz (which
>> ? ? ?max's out at just after 4GHz)
>> ?- A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>> ? ?and get_tick_rate() to correctly maintain the ms counter used by
>> ? ?get_timer() - This function can be weak (so next point)
>> ?- If the hardware supports a native 32-bit ms counter, get_raw_ms()
>> ? ?can be overridden to simply return the hardware counter. In this case,
>> ? ?get_raw_ticks() would return 1
>> ?- Calling of get_raw_ticks() regularly in the main loop (how ofter will
>> ? ?depend on the raw tick rate, but I image it will never be necessary
>> ? ?to call more often than once every few minutes)
>> ?- If the hardware implements a native 32-bit 1ms counter, no call in
>> ? ?the main loop is required
>> ?- An optional HAL function u32 get_raw_us() which can be used for
>> ? ?performance profiling (must wrap correctly)
>
> Hi All,
> ? ? ?Graeme, I think you have stated exactly what is the "best" approach to
> this problem. ?I will provide a version of "get_raw_ms" that is ?initialized
> using get_raw_tick_rate that will work for all "reasonable" values of
> raw_tick_rate. This will be the "generic" solution. Both the initialization
> function and the get_raw_ms function can be overridden if there is reason to
> do so, like "exact" clock rates. I will do the same with get_raw_us. This
> will be posted sometime on Monday for people to review, and to make sure I
> didn't get too far off base. Thank you to both Graeme and Reinhard for
> looking at/working on this.. Hopefully, this solution will put this timing
> issue to rest for all future ports as well as the presently existing ones.

Great - I am in the middle of cleaning up the current usages of the timer
API, reducing it all down to get_timer() - I will then 'libify'
get_timer() and setup the hooks into the HAL get_raw_ticks() and
get_raw_tick_rate() API

I think there will need to be a lot of cleanup, especially in arch/arm to
get this to all fit

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  5:25                   ` Graeme Russ
@ 2011-05-23  6:29                     ` Albert ARIBAUD
  2011-05-23 10:53                       ` Graeme Russ
  2011-05-23 16:22                       ` J. William Campbell
  0 siblings, 2 replies; 101+ messages in thread
From: Albert ARIBAUD @ 2011-05-23  6:29 UTC (permalink / raw)
  To: u-boot

Hi all,

Sorry, could not follow the discussion although I find it very 
interesting, so I will handle the task of coming in late and asking the 
silly questions.

Le 23/05/2011 07:25, Graeme Russ a ?crit :

> On Mon, May 23, 2011 at 3:02 PM, J. William Campbell
> <jwilliamcampbell@comcast.net>  wrote:
>> On 5/22/2011 6:42 PM, Graeme Russ wrote:
>>>
>>> OK, so in summary, we can (in theory) have:
>>>   - A timer API in /lib/ with a single u32 get_timer(u32 base) function
>>>   - A HAL with two functions
>>>     - u32 get_raw_ticks()
>>>     - u32 get_raw_tick_rate() which returns the tick rate in kHz (which
>>>       max's out at just after 4GHz)
>>>   - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>>>     and get_tick_rate() to correctly maintain the ms counter used by
>>>     get_timer() - This function can be weak (so next point)
>>>   - If the hardware supports a native 32-bit ms counter, get_raw_ms()
>>>     can be overridden to simply return the hardware counter. In this case,
>>>     get_raw_ticks() would return 1

Are you sure you did not mean 'get_raw_ticks_rate' here? Besides, I'd 
like the name to specify the units used: 'get_raw_ticks_rate_in_khz' (or 
conversively 'get_raw_ticks_per_ms', depending on which is simpler to 
implement and use).

>>>   - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>>>     depend on the raw tick rate, but I image it will never be necessary
>>>     to call more often than once every few minutes)

That's to keep track of get_raw_ticks() rollovers, right? And then the 
get_timer function (which, again, I would prefer to have '... in ms' 
expressed in its name) would call get_raw_ticks() in confidence that at 
most one rollover may have occurred since the last time the helper 
function was called, so a simple difference of the current vs last tick 
value will always be correct.

>>>   - If the hardware implements a native 32-bit 1ms counter, no call in
>>>     the main loop is required
>>>   - An optional HAL function u32 get_raw_us() which can be used for
>>>     performance profiling (must wrap correctly)
>>
>> Hi All,
>>       Graeme, I think you have stated exactly what is the "best" approach to
>> this problem.  I will provide a version of "get_raw_ms" that is  initialized
>> using get_raw_tick_rate that will work for all "reasonable" values of
>> raw_tick_rate. This will be the "generic" solution. Both the initialization
>> function and the get_raw_ms function can be overridden if there is reason to
>> do so, like "exact" clock rates. I will do the same with get_raw_us. This
>> will be posted sometime on Monday for people to review, and to make sure I
>> didn't get too far off base. Thank you to both Graeme and Reinhard for
>> looking at/working on this.. Hopefully, this solution will put this timing
>> issue to rest for all future ports as well as the presently existing ones.

In Greame's description, I did not see a get_raw_ms, only a get_raw_us. 
Was this last one a typo or is that a third HAL function?

> Great - I am in the middle of cleaning up the current usages of the timer
> API, reducing it all down to get_timer() - I will then 'libify'
> get_timer() and setup the hooks into the HAL get_raw_ticks() and
> get_raw_tick_rate() API
>
> I think there will need to be a lot of cleanup, especially in arch/arm to
> get this to all fit
>
> Regards,
>
> Graeme

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  6:29                     ` Albert ARIBAUD
@ 2011-05-23 10:53                       ` Graeme Russ
  2011-05-23 16:22                       ` J. William Campbell
  1 sibling, 0 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-23 10:53 UTC (permalink / raw)
  To: u-boot

On 23/05/11 16:29, Albert ARIBAUD wrote:
> Hi all,
> 
> Sorry, could not follow the discussion although I find it very 
> interesting, so I will handle the task of coming in late and asking the 
> silly questions.
> 
> Le 23/05/2011 07:25, Graeme Russ a ?crit :
> 
>> On Mon, May 23, 2011 at 3:02 PM, J. William Campbell
>> <jwilliamcampbell@comcast.net>  wrote:
>>> On 5/22/2011 6:42 PM, Graeme Russ wrote:
>>>>
>>>> OK, so in summary, we can (in theory) have:
>>>>   - A timer API in /lib/ with a single u32 get_timer(u32 base) function
>>>>   - A HAL with two functions
>>>>     - u32 get_raw_ticks()
>>>>     - u32 get_raw_tick_rate() which returns the tick rate in kHz (which
>>>>       max's out at just after 4GHz)
>>>>   - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>>>>     and get_tick_rate() to correctly maintain the ms counter used by
>>>>     get_timer() - This function can be weak (so next point)
>>>>   - If the hardware supports a native 32-bit ms counter, get_raw_ms()
>>>>     can be overridden to simply return the hardware counter. In this case,
>>>>     get_raw_ticks() would return 1
> 
> Are you sure you did not mean 'get_raw_ticks_rate' here? Besides, I'd 

Yes, I did mean get_raw_ticks_rate()

> like the name to specify the units used: 'get_raw_ticks_rate_in_khz' (or 
> conversively 'get_raw_ticks_per_ms', depending on which is simpler to 
> implement and use).
> 

indeed, get_raw_ticks_per_ms() is a better name

>>>>   - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>>>>     depend on the raw tick rate, but I image it will never be necessary
>>>>     to call more often than once every few minutes)
> 
> That's to keep track of get_raw_ticks() rollovers, right? And then the 

Yes

> get_timer function (which, again, I would prefer to have '... in ms' 
> expressed in its name) would call get_raw_ticks() in confidence that at 
> most one rollover may have occurred since the last time the helper 
> function was called, so a simple difference of the current vs last tick 
> value will always be correct.

Correct - And a change to get_ms_timer() could be in order if generally
supported, but this would be a big patch across a lot of code for a simple
rename

>>>>   - If the hardware implements a native 32-bit 1ms counter, no call in
>>>>     the main loop is required
>>>>   - An optional HAL function u32 get_raw_us() which can be used for
>>>>     performance profiling (must wrap correctly)
>>>
>>> Hi All,
>>>       Graeme, I think you have stated exactly what is the "best" approach to
>>> this problem.  I will provide a version of "get_raw_ms" that is  initialized
>>> using get_raw_tick_rate that will work for all "reasonable" values of
>>> raw_tick_rate. This will be the "generic" solution. Both the initialization
>>> function and the get_raw_ms function can be overridden if there is reason to
>>> do so, like "exact" clock rates. I will do the same with get_raw_us. This
>>> will be posted sometime on Monday for people to review, and to make sure I
>>> didn't get too far off base. Thank you to both Graeme and Reinhard for
>>> looking at/working on this.. Hopefully, this solution will put this timing
>>> issue to rest for all future ports as well as the presently existing ones.
> 
> In Greame's description, I did not see a get_raw_ms, only a get_raw_us. 
> Was this last one a typo or is that a third HAL function?

get_raw_ms() is used by get_timer(). get_raw_us() is an optional function
which can be used for performance profiling


>> Great - I am in the middle of cleaning up the current usages of the timer
>> API, reducing it all down to get_timer() - I will then 'libify'
>> get_timer() and setup the hooks into the HAL get_raw_ticks() and
>> get_raw_tick_rate() API
>>
>> I think there will need to be a lot of cleanup, especially in arch/arm to
>> get this to all fit
>>
>> Regards,
>>
>> Graeme
> 
> Amicalement,

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  1:42               ` Graeme Russ
  2011-05-23  5:02                 ` J. William Campbell
@ 2011-05-23 12:09                 ` Wolfgang Denk
  2011-05-23 12:29                   ` Graeme Russ
  1 sibling, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-23 12:09 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

sorry for jumping in late here (was busy with the ELDK 5.0 release).

In message <BANLkTimqGpnsbRSF1hwmjJaaMxV3M_K8gg@mail.gmail.com> you wrote:
> OK, so in summary, we can (in theory) have:
>  - A timer API in /lib/ with a single u32 get_timer(u32 base) function
>  - A HAL with two functions
>    - u32 get_raw_ticks()

What des this provide?

>    - u32 get_raw_tick_rate() which returns the tick rate in kHz (which
>      max's out at just after 4GHz)

Can we please omit the _raw part in these names?

>  - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>    and get_tick_rate() to correctly maintain the ms counter used by
>    get_timer() - This function can be weak (so next point)

Ditto.  What would that do?  If it gets milliseconds as the name
suggest, that's already the function needed for get_timer()?

>  - If the hardware supports a native 32-bit ms counter, get_raw_ms()
>    can be overridden to simply return the hardware counter. In this case,
>    get_raw_ticks() would return 1

I don't think this is possible on may systems, so I doubt if this is
auseful approach.

>  - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>    depend on the raw tick rate, but I image it will never be necessary
>    to call more often than once every few minutes)

NAK. This concept is fundamentally broken.  I will not accept it.

>  - If the hardware implements a native 32-bit 1ms counter, no call in
>    the main loop is required

We should make no such requirements.

>  - An optional HAL function u32 get_raw_us() which can be used for
>    performance profiling (must wrap correctly)

Sorry for rewinding the thread.

Can we not start simple, say by a plain free-runnign 64 bit counter,
be it implemented in hardwar eor in software?  On PowerPC, we have
this immediately in form of the time base register (or more precisely
in form of the two 32 bit registers tbu and tbl representing time base
upper and time base lower).

Modelling a similar interface using _any_ kind of timer service should
be trivial.  And from there, we can just use the existing code again.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I often quote myself; it adds spice to my conversation.  - G. B. Shaw

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-22  6:57   ` J. William Campbell
@ 2011-05-23 12:13     ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-23 12:13 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DD8B3ED.4000408@comcast.net> you wrote:
>
...
>        This statement, as written, is false. While it is true that the 
> power PC (and others) have a 64 bit counter that runs at a many 
> megahertz rate, it is NOT true that all 64 bits must be used to obtain a 
> millisecond timer. A millisecond timer can be produced by using the 33 
> bits of the 64 bit counter whose lsb is <= 1 ms and > 0.5 ms. This value 
> can be extracted by a right shift and masking of the 64 bit counter. Two 
> 32 bit multiplies and adds will produce a correct monotonic 1 ms timer. 
> This is certainly the best way to go on systems that do not have a 
> hardware 64 bit by 32 bit divide. See the thread "ARM timing code 
> refactoring" for an example of how this can be done. This timer will 
> NEVER result in a wrong value, although it does loose  1 ms every 1193 
> hours.

I think we should NOT bother about low level optimization details
wether or not we have a 64 bit divide instruction of if we need to
emulate it in software.  Let's keep such early optimizations out of
this phase and deal with the specific implementation later, once we
agreed on a design.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"...one of the main causes of the fall of the Roman Empire was  that,
lacking  zero,  they had no way to indicate successful termination of
their C programs."                                     - Robert Firth

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 12:09                 ` Wolfgang Denk
@ 2011-05-23 12:29                   ` Graeme Russ
  2011-05-23 13:19                     ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-23 12:29 UTC (permalink / raw)
  To: u-boot

On 23/05/11 22:09, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> sorry for jumping in late here (was busy with the ELDK 5.0 release).

I thought you were a bit quite on such a 'touchy' subject ;)

> 
> In message <BANLkTimqGpnsbRSF1hwmjJaaMxV3M_K8gg@mail.gmail.com> you wrote:
>> OK, so in summary, we can (in theory) have:
>>  - A timer API in /lib/ with a single u32 get_timer(u32 base) function
>>  - A HAL with two functions
>>    - u32 get_raw_ticks()
> 
> What des this provide?
> 
>>    - u32 get_raw_tick_rate() which returns the tick rate in kHz (which
>>      max's out at just after 4GHz)
> 
> Can we please omit the _raw part in these names?
> 
>>  - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>>    and get_tick_rate() to correctly maintain the ms counter used by
>>    get_timer() - This function can be weak (so next point)
> 
> Ditto.  What would that do?  If it gets milliseconds as the name
> suggest, that's already the function needed for get_timer()?

OK, there appears to be a consensus that not all hardware actually supports
a free-running timer with 1ms resolution. To overcome this, the idea is to
create a common library function which maintains the free running counter.
The library function acts as a pre-scaler using a 'raw tick counter' and a
'raw tick rate' supplied by the low level architecture. We define this weak
so that if the architecture can provide a free running 1ms counter, there
is no (code size) penalty

This approach eliminates all the existing per-arch code which (attempts) to
manage the time base behind get time. So we simplify each arch down to it's
bare essentials - Provide a counter which increments at a natural fixed
rate and what the rate is - Let common library code deal with the rest.

>>  - If the hardware supports a native 32-bit ms counter, get_raw_ms()
>>    can be overridden to simply return the hardware counter. In this case,
>>    get_raw_ticks() would return 1
> 
> I don't think this is possible on may systems, so I doubt if this is
> auseful approach.

x86 does as it implements a 1ms interrupt (I know other systems do as well)

>>  - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>>    depend on the raw tick rate, but I image it will never be necessary
>>    to call more often than once every few minutes)
> 
> NAK. This concept is fundamentally broken.  I will not accept it.

Some existing timers are fundamentally broken - The glitch at the
0xffffffff to 0x00000000 rollover or rollover early - The method discussed
in this thread eliminates all such glitches. Provided pre-scaler in /lib/
(triggered by get_timer() usually) is called often enough (71 minutes for a
32-bit 1MHz counter) then there is no need. Even then, it is only important
over the time period you are measuring (i.e. two independent 5s delays 2
hours apart will not be a problem)

Kicking the pre-scaler (like kicking the watchdog) eliminates the problem
entirely.

> 
>>  - If the hardware implements a native 32-bit 1ms counter, no call in
>>    the main loop is required
> 
> We should make no such requirements.

No such requirement of what?

>>  - An optional HAL function u32 get_raw_us() which can be used for
>>    performance profiling (must wrap correctly)
> 
> Sorry for rewinding the thread.
> 
> Can we not start simple, say by a plain free-runnign 64 bit counter,
> be it implemented in hardwar eor in software?  On PowerPC, we have

That's exactly what we are suggesting - Let the hardware be free to
implement the counter at whatever frequency suits it. 64-bit is not needed
in reality

> this immediately in form of the time base register (or more precisely
> in form of the two 32 bit registers tbu and tbl representing time base
> upper and time base lower).
> 
> Modelling a similar interface using _any_ kind of timer service should
> be trivial.  And from there, we can just use the existing code again.

Yes, have the library function manage the actual '1ms' aspect

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 12:29                   ` Graeme Russ
@ 2011-05-23 13:19                     ` Wolfgang Denk
  2011-05-23 17:30                       ` J. William Campbell
                                         ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-23 13:19 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDA5334.4060308@gmail.com> you wrote:
>
> >>  - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
> >>    and get_tick_rate() to correctly maintain the ms counter used by
> >>    get_timer() - This function can be weak (so next point)
> > 
> > Ditto.  What would that do?  If it gets milliseconds as the name
> > suggest, that's already the function needed for get_timer()?
> 
> OK, there appears to be a consensus that not all hardware actually supports
> a free-running timer with 1ms resolution. To overcome this, the idea is to

Indeed.  I guess most of them do not.

> create a common library function which maintains the free running counter.
> The library function acts as a pre-scaler using a 'raw tick counter' and a
> 'raw tick rate' supplied by the low level architecture. We define this weak

What are "raw" ticks?  And what are "cooked" ticks, then?

> so that if the architecture can provide a free running 1ms counter, there
> is no (code size) penalty

Why do we need a free running 1ms counter at all?  Any free running
counter of at least millisecoind resolution should be good enough.

> This approach eliminates all the existing per-arch code which (attempts) to
> manage the time base behind get time. So we simplify each arch down to it's
> bare essentials - Provide a counter which increments at a natural fixed
> rate and what the rate is - Let common library code deal with the rest.

Did you have a look at the PowerPC implementation?  I'd like to see
this used as reference.

> >>  - Calling of get_raw_ticks() regularly in the main loop (how ofter will
> >>    depend on the raw tick rate, but I image it will never be necessary
> >>    to call more often than once every few minutes)
> > 
> > NAK. This concept is fundamentally broken.  I will not accept it.
> 
> Some existing timers are fundamentally broken - The glitch at the
> 0xffffffff to 0x00000000 rollover or rollover early - The method discussed
> in this thread eliminates all such glitches. Provided pre-scaler in /lib/
> (triggered by get_timer() usually) is called often enough (71 minutes for a
> 32-bit 1MHz counter) then there is no need. Even then, it is only important

We already have this nightmare of code for triggering the watchdog on
systems that use it.

Assuming there are places in the main loop that get executed often
enough is a broken concept, and I will not accept any such code.

> over the time period you are measuring (i.e. two independent 5s delays 2
> hours apart will not be a problem)

What is the practical purpose of get_timer()?  What is the longest
interval we have to cover?  And what is the problem with a rollover?

> >>  - If the hardware implements a native 32-bit 1ms counter, no call in
> >>    the main loop is required
> > 
> > We should make no such requirements.
> 
> No such requirement of what?

Of making any calls in the main loop.

> > Can we not start simple, say by a plain free-runnign 64 bit counter,
> > be it implemented in hardwar eor in software?  On PowerPC, we have
> 
> That's exactly what we are suggesting - Let the hardware be free to
> implement the counter at whatever frequency suits it. 64-bit is not needed
> in reality

It may not be needed on some systems, but may be needed on others
where 32 bit is too short.  Let's use the common base that is know to
work on all systems, even if it's not strictly needed on all of them.

> > this immediately in form of the time base register (or more precisely
> > in form of the two 32 bit registers tbu and tbl representing time base
> > upper and time base lower).
> > 
> > Modelling a similar interface using _any_ kind of timer service should
> > be trivial.  And from there, we can just use the existing code again.
> 
> Yes, have the library function manage the actual '1ms' aspect

This is what PPC is doing. And I understand that Reinhard did the same
in software for AT91.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Alles Gescheite ist schon gedacht worden, man mu? nur versuchen,
es noch einmal zu denken.          -- Goethe, Maximen und Reflexionen

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23  6:29                     ` Albert ARIBAUD
  2011-05-23 10:53                       ` Graeme Russ
@ 2011-05-23 16:22                       ` J. William Campbell
  1 sibling, 0 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-23 16:22 UTC (permalink / raw)
  To: u-boot

On 5/22/2011 11:29 PM, Albert ARIBAUD wrote:
> Hi all,
>
> Sorry, could not follow the discussion although I find it very
> interesting, so I will handle the task of coming in late and asking the
> silly questions.
I am glad you are looking at our discussion. I am sure we are going to 
need all the help/oversight/questions that we can get, as this is a 
change that will affect all architectures.
> Le 23/05/2011 07:25, Graeme Russ a ?crit :
>
>> On Mon, May 23, 2011 at 3:02 PM, J. William Campbell
>> <jwilliamcampbell@comcast.net>   wrote:
>>> On 5/22/2011 6:42 PM, Graeme Russ wrote:
>>>> OK, so in summary, we can (in theory) have:
>>>>    - A timer API in /lib/ with a single u32 get_timer(u32 base) function
>>>>    - A HAL with two functions
>>>>      - u32 get_raw_ticks()
>>>>      - u32 get_raw_tick_rate() which returns the tick rate in kHz (which
>>>>        max's out at just after 4GHz)
>>>>    - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>>>>      and get_tick_rate() to correctly maintain the ms counter used by
>>>>      get_timer() - This function can be weak (so next point)
>>>>    - If the hardware supports a native 32-bit ms counter, get_raw_ms()
>>>>      can be overridden to simply return the hardware counter. In this case,
>>>>      get_raw_ticks() would return 1
> Are you sure you did not mean 'get_raw_ticks_rate' here? Besides, I'd
> like the name to specify the units used: 'get_raw_ticks_rate_in_khz' (or
> conversively 'get_raw_ticks_per_ms', depending on which is simpler to
> implement and use).
I think you are correct, it was the rate function desired here. I think 
the best way to go is use a "get_raw_tick_rate_in_mhz" function, because 
it is probably the easiest one to implement, and in many cases something 
like it already exists.
>>>>    - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>>>>      depend on the raw tick rate, but I image it will never be necessary
>>>>      to call more often than once every few minutes)
> That's to keep track of get_raw_ticks() rollovers, right? And then the
> get_timer function (which, again, I would prefer to have '... in ms'
> expressed in its name) would call get_raw_ticks() in confidence that at
> most one rollover may have occurred since the last time the helper
> function was called, so a simple difference of the current vs last tick
> value will always be correct.
Exactly so. Note that this same function probably needs to be called in 
udelay for the same reason. More precisely, the get_timer function will 
call get_raw_ms, which will call get_raw_ticks. I think it may be better 
to move get_timer "down" a level in the hierarchy,
so we don't need a get_raw_ms. get_timer would then be part of the HAL. 
One would use a get_timer(0) in order to do what get_raw_ms alone would 
have done. If the user had a good reason, he would then override 
get_timer with his own version. What do you think Graeme? It reduces the 
nesting depth by one level. As for the name change to get_timer_in_ms, I 
would support it. Naturally, such a change would be up to Mr. Denk. 
Since by definition that is what the function does, it seems to be a 
good change from my point of view.
>>>>    - If the hardware implements a native 32-bit 1ms counter, no call in
>>>>      the main loop is required
>>>>    - An optional HAL function u32 get_raw_us() which can be used for
>>>>      performance profiling (must wrap correctly)
>>> Hi All,
>>>        Graeme, I think you have stated exactly what is the "best" approach to
>>> this problem.  I will provide a version of "get_raw_ms" that is  initialized
>>> using get_raw_tick_rate that will work for all "reasonable" values of
>>> raw_tick_rate. This will be the "generic" solution. Both the initialization
>>> function and the get_raw_ms function can be overridden if there is reason to
>>> do so, like "exact" clock rates. I will do the same with get_raw_us. This
>>> will be posted sometime on Monday for people to review, and to make sure I
>>> didn't get too far off base. Thank you to both Graeme and Reinhard for
>>> looking at/working on this.. Hopefully, this solution will put this timing
>>> issue to rest for all future ports as well as the presently existing ones.
> In Greame's description, I did not see a get_raw_ms, only a get_raw_us.
> Was this last one a typo or is that a third HAL function?
get_raw_ms was referenced as a library function a few lines above.  
Right now, I think the functionality we require from the HAL is

   1. get_raw_tick_rate_in_mhz
   2. get_raw_ms
   3. get_raw_ticks
   4. (optional)get_raw_us

There is also  APIs for these functions called get_timer.

I think we need to add a call to another function called 
"initialize_timer_system" or similar that will initialize the data 
structures in gd by calling get_raw_tick_rate_in_mhz. Additionally, I 
think we need to provide a udelay function, simply because it can 
interact with calling get_raw_ms often enough. We are somewhat caught 
between two fires here, in that on the one hand we want to provide a 
very "generic" approach to the timing system that will work on "any" CPU 
while on the other hand we want to allow easy 
customization/simplification of the timer system where appropriate. 
There is more than one way to approach this. Another approach is to 
define the HAL as:

   1. get_timer (_in_ms if approved)
   2. udelay
   3. (optional)get_raw_us
   4. get_raw_tick_rate_in_mhz
   5.   initialize_timer_system

We would provide a "reference" implementation of get_timer and udelay 
with comments regarding the implementation of the get_raw_ticks 
functionality (static inline comes to mind). This would provide a 
functional but possibly not optimal timer system. Later, once everything 
is working, the user could "hack up" the get_timer routines and the 
initialize_timer_system routines to remove any functionality that was 
not relevant to his system, such as using a fixed clock rate etc. The 
benefit of this approach is that in simple systems where space is real 
tight one can still utilize a minimal, optimal timer system without the 
extra code required to make it generic. There are no "extra levels". The 
disadvantage of this approach is that it allows the user to wander off 
into an incompatible non-standard implementation. Thoughts on this 
subject are welcome. The design we have will work, but it will require 
somewhat more text than the "present" system. How much more, and does it 
matter, I don't know.
>> Great - I am in the middle of cleaning up the current usages of the timer
>> API, reducing it all down to get_timer() - I will then 'libify'
>> get_timer() and setup the hooks into the HAL get_raw_ticks() and
>> get_raw_tick_rate() API
>>
>> I think there will need to be a lot of cleanup, especially in arch/arm to
>> get this to all fit
I share your concern. We may have to iterate a bit.

Best Regards,
Bill Campbell

>> Regards,
>>
>> Graeme
> Amicalement,

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 13:19                     ` Wolfgang Denk
@ 2011-05-23 17:30                       ` J. William Campbell
  2011-05-23 18:24                         ` Albert ARIBAUD
  2011-05-23 19:18                         ` Wolfgang Denk
  2011-05-23 18:27                       ` J. William Campbell
  2011-05-23 20:48                       ` Graeme Russ
  2 siblings, 2 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-23 17:30 UTC (permalink / raw)
  To: u-boot

On 5/23/2011 6:19 AM, Wolfgang Denk wrote:
> Dear Graeme Russ,
>
> In message<4DDA5334.4060308@gmail.com>  you wrote:
>>>>   - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>>>>     and get_tick_rate() to correctly maintain the ms counter used by
>>>>     get_timer() - This function can be weak (so next point)
>>> Ditto.  What would that do?  If it gets milliseconds as the name
>>> suggest, that's already the function needed for get_timer()?
>> OK, there appears to be a consensus that not all hardware actually supports
>> a free-running timer with 1ms resolution. To overcome this, the idea is to
> Indeed.  I guess most of them do not.
>
>> create a common library function which maintains the free running counter.
>> The library function acts as a pre-scaler using a 'raw tick counter' and a
>> 'raw tick rate' supplied by the low level architecture. We define this weak
> What are "raw" ticks?  And what are "cooked" ticks, then?
Hi all,
      FWIW,  "cooked" ticks would be 1 ms ticks, although we never 
really use them as such.
>> so that if the architecture can provide a free running 1ms counter, there
>> is no (code size) penalty
> Why do we need a free running 1ms counter at all?  Any free running
> counter of at least millisecoind resolution should be good enough.
Correct. Any free running counter whose resolution is better than one 
millisecond and which is "long enough" that it will not overflow between 
calls to get_timer is sufficient.
>> This approach eliminates all the existing per-arch code which (attempts) to
>> manage the time base behind get time. So we simplify each arch down to it's
>> bare essentials - Provide a counter which increments at a natural fixed
>> rate and what the rate is - Let common library code deal with the rest.
> Did you have a look at the PowerPC implementation?  I'd like to see
> this used as reference.
I have looked at it as a reference. However, there is one disadvantage 
in using the PPC code as a reference. It has a 64 bit timestamp. Many 
systems do not have a 64 bit timestamp, but rather a 32 bit timestamp.  
It is possible to extend the 32 bit timestamp to a 64 bit timestamp if 
get_timer is called often enough that there will only be a single 
rollover of the bottom 32 bits  between uses. However, if that condition 
is met, there is no need to extend the timer to 64 bits. Instead, just 
convert the elapsed time since the last call (which you know) to ms and 
be done with it.  As Wolfgang said above, any counter that has better 
than 1 ms resolution  is adequate to the task. The additional 
requirement that we have stated is that the counter be long enough that 
it does not overflow between calls to get_timer. If the counter is 64 
bits long, it pretty much for sure meets this requirement  (although 
bits below 0.5 ms resolution really don't help any). If the timer is 32 
bits long, it will meet any requirements using get_timer to time out 
hardware intervals. My original implementation used a 32 bit divide and 
does exactly that. This is the shortest and simplest approach, and we 
can get that working in all cases quite easily I think. We can avoid the 
"no divide" optimization until everybody is satisfied with what we have.
>>>>   - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>>>>     depend on the raw tick rate, but I image it will never be necessary
>>>>     to call more often than once every few minutes)
>>> NAK. This concept is fundamentally broken.  I will not accept it.
>> Some existing timers are fundamentally broken - The glitch at the
>> 0xffffffff to 0x00000000 rollover or rollover early - The method discussed
>> in this thread eliminates all such glitches. Provided pre-scaler in /lib/
>> (triggered by get_timer() usually) is called often enough (71 minutes for a
>> 32-bit 1MHz counter) then there is no need. Even then, it is only important
> We already have this nightmare of code for triggering the watchdog on
> systems that use it.
>
> Assuming there are places in the main loop that get executed often
> enough is a broken concept, and I will not accept any such code.
That is fine with me. The reason this was being done was to attempt to 
emulate, as much as possible, the power PC, where the 64 bit timestamp 
counter allows calls to get_timer separated by many minutes and several 
console commands to work properly. These get timer commands will NOT 
work properly on systems that have a 32 bit counter that overflows every 
200 seconds or so. The call in the idle loop was an attempt to make the 
32 bit systems work more like the 64 bit systems. One may then either

   1.   Define calls to get_timer to measure an elapsed interval
      separated by any returns to the command processor as broken.
   2. Require the use of interrupts to extend the 32 bit timestamp.
      (This may not be possible on all systems as the timer used for
      performance monitoring does not interrupt, etc.)
   3. Allow the call in the idle loop under the assumption that we are
      talking about timing in the minutes range, not a few seconds.

If you go with number 1, all problems are solved.
>> over the time period you are measuring (i.e. two independent 5s delays 2
>> hours apart will not be a problem)
> What is the practical purpose of get_timer()?  What is the longest
> interval we have to cover?  And what is the problem with a rollover?
If get_timer is used to timeout failing hardware operations, the CPU is 
usually in a reasonably tight loop and get_timer will certainly be 
called at least once a minute. In this case, all will be well. If 
get_timer is used to obtain a timestamp during one u-boot command to be 
compared with a timestamp taken by a later command (say inside a 
script), it will not function properly if the total delay (or the delay 
in any one command) exceeds the hardware timer rollover interval. The 
elapsed time returned by the second call to get_timer will be wring 
modulo the actual number of rollovers that occurred. With an added call 
to get_timer inside the command loop, the condition becomes the delay in 
any one command, not the total delay. This is still broken, just not as 
bad. If 1 was selected above, no problem.
>>>>   - If the hardware implements a native 32-bit 1ms counter, no call in
>>>>     the main loop is required
>>> We should make no such requirements.
>> No such requirement of what?
> Of making any calls in the main loop.
>
>>> Can we not start simple, say by a plain free-runnign 64 bit counter,
>>> be it implemented in hardwar eor in software?  On PowerPC, we have
>> That's exactly what we are suggesting - Let the hardware be free to
>> implement the counter at whatever frequency suits it. 64-bit is not needed
>> in reality
> It may not be needed on some systems, but may be needed on others
> where 32 bit is too short.  Let's use the common base that is know to
> work on all systems, even if it's not strictly needed on all of them.
When you say a "common base", consider that all systems do not have 64 
bit timers, and extending the 32 bit timer that they do have to 64 bits 
in software is not possible if the number of rollovers between calls to 
the timer update routine is unknown. OTOH, if the number of rollovers is 
assumed to be at most 1, there is no benefit to extending the counter to 
64 bits, as the elapsed time is already known exactly and can be 
converted to ms exactly. We would extending the timer to 64 bits 
(incrementing the top 32 bits)to then do another subtraction to get the 
number we already have. If 32 bits is too short, and that is all you 
have, you are doomed anyway.

Best Regards,
Bill Campbell

>>> this immediately in form of the time base register (or more precisely
>>> in form of the two 32 bit registers tbu and tbl representing time base
>>> upper and time base lower).
>>>
>>> Modelling a similar interface using _any_ kind of timer service should
>>> be trivial.  And from there, we can just use the existing code again.
>> Yes, have the library function manage the actual '1ms' aspect
> This is what PPC is doing. And I understand that Reinhard did the same
> in software for AT91.
>
> Best regards,
>
> Wolfgang Denk
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 17:30                       ` J. William Campbell
@ 2011-05-23 18:24                         ` Albert ARIBAUD
  2011-05-23 19:18                         ` Wolfgang Denk
  1 sibling, 0 replies; 101+ messages in thread
From: Albert ARIBAUD @ 2011-05-23 18:24 UTC (permalink / raw)
  To: u-boot

Le 23/05/2011 19:30, J. William Campbell a ?crit :

>> Did you have a look at the PowerPC implementation? I'd like to see
>> this used as reference.

> I have looked at it as a reference. However, there is one disadvantage
> in using the PPC code as a reference. It has a 64 bit timestamp. Many
> systems do not have a 64 bit timestamp, but rather a 32 bit timestamp.
> It is possible to extend the 32 bit timestamp to a 64 bit timestamp if
> get_timer is called often enough that there will only be a single
> rollover of the bottom 32 bits between uses. However, if that condition
> is met, there is no need to extend the timer to 64 bits.

Well, there is one: making sure that drivers do not need to know if 
timestamps are 32 or 64 bits, or even what resolution they are.

Granted, you could define a timestamp_t type to be either u32 or u64 
depending on the actual timestamp width, so that the driver would not 
need to know the details; but extending u32 to u64, or subtracting two 
u64 values, are not so much of an effort, and that would mean a single API.

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 13:19                     ` Wolfgang Denk
  2011-05-23 17:30                       ` J. William Campbell
@ 2011-05-23 18:27                       ` J. William Campbell
  2011-05-23 19:33                         ` Wolfgang Denk
  2011-05-23 20:48                       ` Graeme Russ
  2 siblings, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-23 18:27 UTC (permalink / raw)
  To: u-boot

On 5/23/2011 6:19 AM, Wolfgang Denk wrote:
> Dear Graeme Russ,
<snip>
> This is what PPC is doing. And I understand that Reinhard did the same
> in software for AT91.
Hi All,
      My apologies for being a little (perhaps more than a little) 
dense. As they say, "after further review", I think the key aspect of 
the PPC timer system is that it uses the decrementer register to 
generate an interrupt at a 1 KHz rate. What I have been attempting here 
is to produce a timer system that does not use interrupts at all. This 
is a fundamental design question. Naturally, systems that can generate 
an interrupt at a 1 KHz rate (or at any (reasonable) higher rate for 
that matter) using the decrementer register can produce a 1 ms 
resolution software counter that updates "by magic". If my understanding 
of this PPC  code is incorrect, somebody please stop me before I make a 
further fool of myself!  Is it then a design requirement that the timer 
system use interrupts? Is that what is meant by using the PPC system as 
a model? If so, is it possible/reasonable on all the u-boots that are 
out there to generate and process timer interrupts at some (hopefully 
but not necessarily) programmable rate?

Best Regards,
Bill Campbell
> Best regards,
>
> Wolfgang Denk
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 17:30                       ` J. William Campbell
  2011-05-23 18:24                         ` Albert ARIBAUD
@ 2011-05-23 19:18                         ` Wolfgang Denk
  1 sibling, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-23 19:18 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDA99BC.80809@comcast.net> you wrote:
>
> >> The library function acts as a pre-scaler using a 'raw tick counter' and a
> >> 'raw tick rate' supplied by the low level architecture. We define this weak
> > What are "raw" ticks?  And what are "cooked" ticks, then?
> Hi all,
>       FWIW,  "cooked" ticks would be 1 ms ticks, although we never 
> really use them as such.

Sorry, but I disagree here.

A tick is defined as the smallest increment of system time as measured by a
computer system (see http://en.wikipedia.org/wiki/System_time):

	System time is measured by a system clock, which is typically
	implemented as a simple count of the number of ticks that have
	transpired since some arbitrary starting date, called the
	epoch.

There is no such thing as "raw ticks", a tick is inherently "raw" and
needs scaling.

> I have looked at it as a reference. However, there is one disadvantage 
> in using the PPC code as a reference. It has a 64 bit timestamp. Many 
> systems do not have a 64 bit timestamp, but rather a 32 bit timestamp.  
> It is possible to extend the 32 bit timestamp to a 64 bit timestamp if 
> get_timer is called often enough that there will only be a single 
> rollover of the bottom 32 bits  between uses. However, if that condition 

Or if there re other methods to detect and handle such a situation. On
many systems, the timer can generate an interrupt, so it would be
trivial enough to implement the handling of this in the interrupt
handler.

> is met, there is no need to extend the timer to 64 bits. Instead, just 
> convert the elapsed time since the last call (which you know) to ms and 
> be done with it.  As Wolfgang said above, any counter that has better 
> than 1 ms resolution  is adequate to the task. The additional 
> requirement that we have stated is that the counter be long enough that 
> it does not overflow between calls to get_timer. If the counter is 64 

The design should not make any assumptions about when or how often
get_timer() is being called.  It should just work :-)

> can get that working in all cases quite easily I think. We can avoid the 
> "no divide" optimization until everybody is satisfied with what we have.

We should first get a common API and a working implementation for all
architectures before we consider any optimizations.

<insert quote Donald Knuth about premature optimization>


> That is fine with me. The reason this was being done was to attempt to 
> emulate, as much as possible, the power PC, where the 64 bit timestamp 
> counter allows calls to get_timer separated by many minutes and several 
> console commands to work properly. These get timer commands will NOT 
> work properly on systems that have a 32 bit counter that overflows every 
> 200 seconds or so. The call in the idle loop was an attempt to make the 
> 32 bit systems work more like the 64 bit systems. One may then either

Can you show me any system where it is not possible to implement a 64
bit periodic timer with sufficient resolution?

Please note:  even on PowerPC where we have a 64 bit time base
register for free, the timer services are not implemented on this
base.  Instead, the interrupt handler for the decrementer will
increment the "timestamp" counter variable (see timer_interrupt() in
arch/powerpc/lib/interrupts.c).

I bet that functionally equivalent code is available on all systems.

Note2: this is a fundamental difference between get_timer() and
udelay().  udelay() has to be available very early, but needs to be
good for a few hundred microsecods or so.  get_timer() is a high level
interface that should not suffer from any restrictions.


>    1.   Define calls to get_timer to measure an elapsed interval
>       separated by any returns to the command processor as broken.

No.

>    2. Require the use of interrupts to extend the 32 bit timestamp.
>       (This may not be possible on all systems as the timer used for
>       performance monitoring does not interrupt, etc.)

This is definitely an option.  It works fine on some systems.
For those systems where it doesn't work, there are probably other
alternatives.


>    3. Allow the call in the idle loop under the assumption that we are
>       talking about timing in the minutes range, not a few seconds.

We must not make any such assumptions.  Assume someone is running a
standalone application (like some burn-in test software), which runs
for a couple of hours and then returns to U-Boot.

> If get_timer is used to timeout failing hardware operations, the CPU is 
> usually in a reasonably tight loop and get_timer will certainly be 
> called at least once a minute. In this case, all will be well. If 
> get_timer is used to obtain a timestamp during one u-boot command to be 
> compared with a timestamp taken by a later command (say inside a 
> script), it will not function properly if the total delay (or the delay 
> in any one command) exceeds the hardware timer rollover interval. The 

get_timer() is defined to return milliseconds.  It returns an unsigned
long, so it is good for UINT32_MAX/1000 = 4294967 seconds or more than
49 days before the timer rolls over.

It is up to the architecture specific implementation to warranty such
behaviour.  I don't think this is an overly complicated task.

> When you say a "common base", consider that all systems do not have 64 
> bit timers, and extending the 32 bit timer that they do have to 64 bits 
> in software is not possible if the number of rollovers between calls to 
> the timer update routine is unknown. OTOH, if the number of rollovers is 

Then let's handle all rollovers? Are there systems out there where we
cannot either have a free runnign 64 bit timer, or cascaded 32 bit
timers, or a timer that is capable of generating interrupts?  Does
U-Boot really support any such CPU?


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"The pathology is to want control, not that you ever get it,  because
of course you never do."                            - Gregory Bateson

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 18:27                       ` J. William Campbell
@ 2011-05-23 19:33                         ` Wolfgang Denk
  2011-05-23 20:26                           ` J. William Campbell
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-23 19:33 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDAA705.1040702@comcast.net> you wrote:
>
>       My apologies for being a little (perhaps more than a little) 
> dense. As they say, "after further review", I think the key aspect of 
> the PPC timer system is that it uses the decrementer register to 
> generate an interrupt at a 1 KHz rate. What I have been attempting here 
> is to produce a timer system that does not use interrupts at all. This 
> is a fundamental design question. Naturally, systems that can generate 

No, it is not.  It is an implementation detail which is irrelevant to
almost all users of U-Boot.

Or do you actucally care if your UART driver uses polling or
interrupts?

> an interrupt at a 1 KHz rate (or at any (reasonable) higher rate for 
> that matter) using the decrementer register can produce a 1 ms 
> resolution software counter that updates "by magic". If my understanding 
> of this PPC  code is incorrect, somebody please stop me before I make a 
> further fool of myself!  Is it then a design requirement that the timer 
> system use interrupts? Is that what is meant by using the PPC system as 

No, it is not a design requirement.  It is just one possible
implementation.  Any other method that achieves the same or similar
results is as good.  As noted before, on PowerPC we could have
probably avoided this and just base all timer services on the timebase
register.

[The reason for this dual implementation is historical.  When I wrote
this code, I did not know if we would ever need any fancy timer-
controlled callbacks or similar.  And I needed to implement interrupt
handling for a few other purposes (for example for use in standalone
applications; this was an explicit requirement at that time).  And the
timer was something that made a good and simple example.]

> a model? If so, is it possible/reasonable on all the u-boots that are 
> out there to generate and process timer interrupts at some (hopefully 
> but not necessarily) programmable rate?

I consider this an implementation detail.  On all architectures it
should be possible to use interrupts, so if the hardware supports a
timer that can generate interrupts it should be possible to use this.
But it is not a requirement that all implementations must work like
this.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
In theory, there is no difference between  theory  and  practice.  In
practice, however, there is.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 19:33                         ` Wolfgang Denk
@ 2011-05-23 20:26                           ` J. William Campbell
  2011-05-23 21:51                             ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-23 20:26 UTC (permalink / raw)
  To: u-boot

On 5/23/2011 12:33 PM, Wolfgang Denk wrote:
> Dear "J. William Campbell",
>
> In message<4DDAA705.1040702@comcast.net>  you wrote:
>>        My apologies for being a little (perhaps more than a little)
>> dense. As they say, "after further review", I think the key aspect of
>> the PPC timer system is that it uses the decrementer register to
>> generate an interrupt at a 1 KHz rate. What I have been attempting here
>> is to produce a timer system that does not use interrupts at all. This
>> is a fundamental design question. Naturally, systems that can generate
> No, it is not.  It is an implementation detail which is irrelevant to
> almost all users of U-Boot.
>
> Or do you actucally care if your UART driver uses polling or
> interrupts?
Hi All,
       I might care a lot if I expect typeahead to work, or if I am 
sending a command script via a terminal emulator and I don't want to 
loose characters while u-boot is off executing a command. One might 
(correctly) say that that is too much to expect of a boot loader, and 
define polling as "good enough", which I advocate, or not. YMMV.
>> an interrupt at a 1 KHz rate (or at any (reasonable) higher rate for
>> that matter) using the decrementer register can produce a 1 ms
>> resolution software counter that updates "by magic". If my understanding
>> of this PPC  code is incorrect, somebody please stop me before I make a
>> further fool of myself!  Is it then a design requirement that the timer
>> system use interrupts? Is that what is meant by using the PPC system as
> No, it is not a design requirement.  It is just one possible
> implementation.  Any other method that achieves the same or similar
> results is as good.  As noted before, on PowerPC we could have
> probably avoided this and just base all timer services on the timebase
> register.
>
> [The reason for this dual implementation is historical.  When I wrote
> this code, I did not know if we would ever need any fancy timer-
> controlled callbacks or similar.  And I needed to implement interrupt
> handling for a few other purposes (for example for use in standalone
> applications; this was an explicit requirement at that time).  And the
> timer was something that made a good and simple example.]
>
>> a model? If so, is it possible/reasonable on all the u-boots that are
>> out there to generate and process timer interrupts at some (hopefully
>> but not necessarily) programmable rate?
> I consider this an implementation detail.  On all architectures it
> should be possible to use interrupts, so if the hardware supports a
> timer that can generate interrupts it should be possible to use this.
> But it is not a requirement that all implementations must work like
       Ok, this is very nice to understand. I will attempt to summarize 
what I think this email and the previous one means. First, the required 
properties of the get_timer routine.

   1. It must have 1 millisecond resolution and accuracy (more or less).
      For instance, the old NIOS timer that incremented the timestamp by
      10 every 10 milliseconds in response to an interrupt is not compliant.
   2. The get_timer routine must have full period accuracy without any
      assumptions regarding what is going on in u-boot. This period is
      4294967 seconds or so.

I then suggest that the minimum system requirements to support the 
u-boot timer are as follows:

    * Either there exists a free-running timer whose period is > 4294967
      and whose resolution is 1 millisecond or better. This probably
      includes all 64 bit timestamp counters.
    * Or there exists a method of generating interrupts at a known rate
      of 1 millisecond or faster. This is a superset of  the current PPC
      method.
    * Or there exists a method of generating interrupts at a known fixed
      rate slower than once a millisecond AND there exists a readable
      free running counter whose period is longer or the same as the
      interrupt rate AND whose resolution is at least 1 ms. This would
      include N bit counters that generate an interrupt when they
      overflow, or some long timestamp counter with another, possibly 
      unrelated interrupt generating methodology that is faster than the
      counter overflow interval.

There are many systems that are able to do all three cases, or two of 
three, so they have a choice on how to implement get_timer(). I claim 
that these are sufficient conditions. I also claim they are necessary. 
If a hardware system does not meet these criteria, I claim it can't meet 
the get_timer requirements. Do such systems exist today that use u-boot? 
I think probably so, but maybe they are corner cases. Note that you 
cannot extend a 32 bit counter to a 64 bit counter reliably without 
using interrupts to do so when get_timer is not being called.

Systems using the first approach above have essentially all their logic 
in the get_timer routine, but MUST use at least some 64 bit arithmetic 
(actually 33 bit arithmetic if you don't count shifts) to do so because 
the delta time between calls can be very large. The routine is not too 
complex to write however.

Systems using the second approach have a real simple get_timer routine 
but a more complex interrupt routine. The interrupt routine is still 
quite simple, it being either a single 32 bit add or 2 32 bit adds (if 
the update rate is a fraction of a ms).

Systems using the last approach are the most complex. They need a 
routine like the get_timer routine I provided yesterday that can be 
called in the interrupt routine to kick the timer up to present day, 
plus a version of the routine called by the user that disables 
interrupts, updates the timestamp, and re-enables interrupts. Are there 
any such systems out there? Probably, but I will wait for someone to 
identify them before I dive in! Certainly the other two methods are much 
easier to create.

Does that sound right?

Best Regards,
Bill Campbell
> this.
>
> Best regards,
>
> Wolfgang Denk
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 13:19                     ` Wolfgang Denk
  2011-05-23 17:30                       ` J. William Campbell
  2011-05-23 18:27                       ` J. William Campbell
@ 2011-05-23 20:48                       ` Graeme Russ
  2 siblings, 0 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-23 20:48 UTC (permalink / raw)
  To: u-boot

On 23/05/11 23:19, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <4DDA5334.4060308@gmail.com> you wrote:
>>
>>>>  - A helper function in /lib/ u32 get_raw_ms() which uses get_raw_ticks()
>>>>    and get_tick_rate() to correctly maintain the ms counter used by
>>>>    get_timer() - This function can be weak (so next point)
>>>
>>> Ditto.  What would that do?  If it gets milliseconds as the name
>>> suggest, that's already the function needed for get_timer()?
>>
>> OK, there appears to be a consensus that not all hardware actually supports
>> a free-running timer with 1ms resolution. To overcome this, the idea is to
> 
> Indeed.  I guess most of them do not.
> 
>> create a common library function which maintains the free running counter.
>> The library function acts as a pre-scaler using a 'raw tick counter' and a
>> 'raw tick rate' supplied by the low level architecture. We define this weak
> 
> What are "raw" ticks?  And what are "cooked" ticks, then?
> 

We never talked about cooked tick - I agree 'raw' is superfluous

>> so that if the architecture can provide a free running 1ms counter, there
>> is no (code size) penalty
> 
> Why do we need a free running 1ms counter at all?  Any free running
> counter of at least millisecoind resolution should be good enough.
> 

Because it get_timer() is 1ms - Yes, get_timer() can calculate it from a
higher resolution source, but that creates multiple implementations of the
pre-scaler of multiple arches - The goal is to reduce code duplication
here. get_timer() calls get_raw_ms() (ok, we could just call that get_ms)
which is a common library routine which does the pre-scaling. Arches which
can maintain this 1ms counter (via interrupts or native hardware counters
for example) don't need it.

>> This approach eliminates all the existing per-arch code which (attempts) to
>> manage the time base behind get time. So we simplify each arch down to it's
>> bare essentials - Provide a counter which increments at a natural fixed
>> rate and what the rate is - Let common library code deal with the rest.
> 
> Did you have a look at the PowerPC implementation?  I'd like to see
> this used as reference.
> 
>>>>  - Calling of get_raw_ticks() regularly in the main loop (how ofter will
>>>>    depend on the raw tick rate, but I image it will never be necessary
>>>>    to call more often than once every few minutes)
>>>
>>> NAK. This concept is fundamentally broken.  I will not accept it.
>>
>> Some existing timers are fundamentally broken - The glitch at the
>> 0xffffffff to 0x00000000 rollover or rollover early - The method discussed
>> in this thread eliminates all such glitches. Provided pre-scaler in /lib/
>> (triggered by get_timer() usually) is called often enough (71 minutes for a
>> 32-bit 1MHz counter) then there is no need. Even then, it is only important
> 
> We already have this nightmare of code for triggering the watchdog on
> systems that use it.
> 
> Assuming there are places in the main loop that get executed often
> enough is a broken concept, and I will not accept any such code.
> 
>> over the time period you are measuring (i.e. two independent 5s delays 2
>> hours apart will not be a problem)
> 
> What is the practical purpose of get_timer()?  What is the longest
> interval we have to cover?  And what is the problem with a rollover?
> 
>>>>  - If the hardware implements a native 32-bit 1ms counter, no call in
>>>>    the main loop is required
>>>
>>> We should make no such requirements.
>>
>> No such requirement of what?
> 
> Of making any calls in the main loop.
> 
>>> Can we not start simple, say by a plain free-runnign 64 bit counter,
>>> be it implemented in hardwar eor in software?  On PowerPC, we have
>>
>> That's exactly what we are suggesting - Let the hardware be free to
>> implement the counter at whatever frequency suits it. 64-bit is not needed
>> in reality
> 
> It may not be needed on some systems, but may be needed on others
> where 32 bit is too short.  Let's use the common base that is know to
> work on all systems, even if it's not strictly needed on all of them.
> 
>>> this immediately in form of the time base register (or more precisely
>>> in form of the two 32 bit registers tbu and tbl representing time base
>>> upper and time base lower).
>>>
>>> Modelling a similar interface using _any_ kind of timer service should
>>> be trivial.  And from there, we can just use the existing code again.
>>
>> Yes, have the library function manage the actual '1ms' aspect
> 
> This is what PPC is doing. And I understand that Reinhard did the same
> in software for AT91.

Yes, duplicate code - lets 'libify' it

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-23 20:26                           ` J. William Campbell
@ 2011-05-23 21:51                             ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-23 21:51 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDAC2F5.7060202@comcast.net> you wrote:
>
> Does that sound right?


I think so.

> --------------000308010205050804040502
> Content-Type: text/html; charset=ISO-8859-1
> Content-Transfer-Encoding: 7bit

Could you please stop posting HTML?  Thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
No more blah, blah, blah!
	-- Kirk, "Miri", stardate 2713.6

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-21 12:38 [U-Boot] [RFC] Review of U-Boot timer API Graeme Russ
       [not found] ` <4DD7DB64.70605@comcast.net>
  2011-05-22  4:26 ` Reinhard Meyer
@ 2011-05-24  3:42 ` Mike Frysinger
  2011-05-24  4:07 ` Graeme Russ
  3 siblings, 0 replies; 101+ messages in thread
From: Mike Frysinger @ 2011-05-24  3:42 UTC (permalink / raw)
  To: u-boot

On Saturday, May 21, 2011 08:38:29 Graeme Russ wrote:
> NOTE: http://lists.denx.de/pipermail/u-boot/2010-June/073024.html appears
> to imply the following implementation of get_timer() is wrong:
> 
> 	ulong get_timer(ulong base)
> 	{
> 		return get_timer_masked() - base;
> 	}

while this specific code might be wrong due to assumed timer rollover 
behavior, i think the code is wrong to ignore "base" completely.  but maybe it 
doesnt matter after we rewrite things :).

> blackfin
>  - Provides a 64-bit get_ticks() which simply returns 32-bit get_timer(0)

seems to me that most arches do this

>  - get_usec_timer_64() could offer a longer period (584942 years!)

if the hardware can support that large of a timer ...

otherwise, i'd love to see the whole timer API reduced to just get_timer() and 
a proper doc/README.timer written.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110523/866118e4/attachment.pgp 

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-21 12:38 [U-Boot] [RFC] Review of U-Boot timer API Graeme Russ
                   ` (2 preceding siblings ...)
  2011-05-24  3:42 ` Mike Frysinger
@ 2011-05-24  4:07 ` Graeme Russ
  2011-05-24  4:24   ` Mike Frysinger
  3 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-24  4:07 UTC (permalink / raw)
  To: u-boot

Hi All,

OK, here goes - A much more in-depth generic analysis for a timer API

I hope this highlights why the current discussion thread has ended
up where is has

Regards,

Graeme

Definitions:
 'register' - A storage element - Can be:
   - A dedicated CPU register
   - A location in memory (as defined by a C variable for example)
   - A memory mapped storage location
   - A port-mapped storage location
   - etc

 'platform' - A complete hardware configuration which is capable of
   running U-Boot. An operation performed by 'the plaform' (such as
   incrementing a counter) is assumed to occur without software
   intervention (although initial setup and configuration may be
   required)

 'fixed' - Same across all platforms

 'constant' - Does not change between any two pre-determined events. For
   example 'between power up and power down', 'after being configured to
   the next time it is configured'

 'tick' - A constant period of time - The tick period is not fixed (see
   'fixed' above)

 'counter' - A register which increments by 1 in response to a given
   stimulus (an interupt, a programmed clock, a user pressing a button,
   a character recieved on a serial port etc)

 'tick counter' - A register which is incremented every tick (typically
   by the platform)

 'timer' - A register which stores a value representing a number of
   fixed time intervals (1ms unless otherwise noted)

 'ISR' - Interrupt Service Routine - A function which is called by the CPU
   in response to an interrupt

 'interrupt' - A asynchronous signal which causes the CPU to suspent the
   current flow of program execution and execute an ISR - Upon completion
   of the ISR, control is returned to the suspended program flow

Assumptions:
 - Every platform has a tick counter
 - Not all platforms support interrupts
 - The size of the tick counter is not fixed

Mandatory Platform Requirements:
 - A tick counter MUST exist
 - ticks MUST occur at least once every one millisecond
 - A means of reading the tick counter register MUST be provided
 - A means of obtaining the tick frequency MUST be provided
 - The tick counter MUST be unsigned
 - The tick counter MUST use the entire range of the tick counter register
   (i.e. from 'All 0's' to 'All 1's')
 - The tick counter MUST overflow from "all 1's" to "all 0's"

Goal:
 - Maintain a 1ms time base which can be obtained via a simple call to
   get_timer()
 - The timer MUST use the entire range of it's register (i.e. from
   'All 0's' to 'All 1's')
 - The timer MUST overflow from "all 1's" to "all 0's"
 - Reduce the amount of code duplication between platforms

So what do we need in order to implement a good[1] timer API?
 1. A tick counter
 2. If #1 does not have a period of 1ms, a prescaler to convert
    the tick counter to a 1ms timer
 3. If #2 is a software implementation, a way of regularly calling
    the prescaler

Lets look at each of these in detail:

The tick counter
----------------
There are a wide variety of implementations which can be divided into two
categories:
 Hardware Counters:
 - A non-programmable read-only hardware counter. An example is a simple
   hardware counter that is tick'd by the CPU clock starting at zero when
   the platform is powered-up
 - A non-programmable read-only hardware counter that can be reset to zero
   by writting to a control register
 - A non-programmable hardware counter which can be reset to any arbitrary
   value
 - A programmable hardware counter - Examples include:
   - A prescaler which increments the counter every 'x' CPU clocks where
     'x' is set programatically by writing to reserved control registers
   - A programmable clock source independent of the CPU clock

 Software Counters:
 - Implemented in U-Boot software (C or assembler)
 - Must be regularly triggered (usually by an interrupt)
 - Interrupt period can be programmable (arch/x86/cpu/sc520 has a good
   example) or non-programmable

If the period of the hardware counter or the interrupt generator can be
programmed to 1ms (or is fixed at 1ms) then there is no need to implement
#2 (or, therefore, #3)

Here is a list of some typical tick counter rollover durations. The
following intervals have been rounded down to the nearest whole number and
therefore represent a realistic minimum interval at which the tick counter
must be read to prevent timing glitches caused by multiple roll-overs.

 - 1ms (1kHz), 16-bit - 65 seconds
 - 1ms (1kHz), 32-bit - 49 days
 - 1ms (1kHz), 64-bit - 584,942,417 years
 - 1us (1MHz), 32-bit - 71 minutes
 - 1us (1MHz), 64-bit - 584,942 years
 - 1ns (1GHz), 32-bit - 4 seconds
 - 1ns (1GHz), 64-bit - 584 years

The Prescaler
-------------
The prescaler converts the tick counter (with period <1ms) to a timer with
period = 1ms. As with the tick counter, the prescaler may be implemented
in either hardware or software. Where the prescaler is implemented in
hardware (and provides a 1ms counter) there is no need to implement a
software prescaler. However, if no hardware prescaler exists (or the
hardware presaler does not increase the counter period to 1ms) a software
prescaler is required.

Currently, any required software prescaler is implented per-platform. We
now have a function (thanks Bill Campbell) which implements a software
prescaler by periodically reading the tick counter. This function MUST be
called more frequently that the roll-over period of the tick counter
provided. This function has a few 'nice' features:

 - It can be implemented in /lib/ thus elliminating a lot of platform
   specific implementations
 - It does not require the tick frequency to be known at compile time
 - Is not effected by roll-over of the tick-counter
 - Does not need to be called@contanst rate (only needs to be within
   the rollover period listed above)
 - Optionally does not use divides for platforms where divides are either
   slow or non-exitent
 - Optionally handles a tick period which is not an integer multiple of
   1ms

Regularly Servicing the Software Prescaler
------------------------------------------
If the prescaler is implemented in software, it must be called often
enough to avoid tiemr glitches due to multiple rollovers of the tick
counter between prescaler calls. There are several ways this can be
achieved:
 - Inside get_timer() - Taking into consideration the roll-over periods
   listed earlier (and the fact the common scenario is implementing
   time-outs in the order of a few seconds or so) this may not be such a
   bad approach on most platforms. Any platform with a 64-bit tick
   counter will be fine. Even a 32-bit 1us tick counter could be OK
   (when would we ever need to measure a 71 minute period?). Actually,
   this method should always be used to ensure the timer is up-to-date
   get_timer() returns the current timer value.
 - An ISR - If the platform supports interrupts. Because get_timer() calls
   the prescaler as well, the ISR only needs to be triggered once every
   tick rollover period (actually, slightly quicker to account for ISR
   latency)
 - Main Loop - Last resort option - Breaks when calling stand-alone
   applications such as burn-in test beds etc.


So, provided the platform can provide a tick counter, and the tick counter
can be serviced regularly[2], we can implement a timer API for which the
platform can COMPLETELY disregard the fact that a 1ms time base is
required[3].

[1]An implementation with minimal code duplication across platforms and
   requires as little design and implementation per platform as
   practicalibly possible
[2]During the interval over which a timing operation is being actively
   performed. It does not matter if the timer 'glitches' while it is not
   in use.
[3]Well not quite - The platform does need to make sure the tick period is
   less than 1ms

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  4:07 ` Graeme Russ
@ 2011-05-24  4:24   ` Mike Frysinger
  2011-05-24  4:35     ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Mike Frysinger @ 2011-05-24  4:24 UTC (permalink / raw)
  To: u-boot

rather than inventing our own set of terms, how about piggybacking what Linux 
has already done ?  they have "cycle counters" and "timer counters" (which 
bubble up into "clock sources", but i dont think we need those).

further, Linux probably already has implementations we can steal for the arch-
specific "cycle counters", and the common code which takes care of scaling 
those into actual measurements of time.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110524/f782b20c/attachment.pgp 

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  4:24   ` Mike Frysinger
@ 2011-05-24  4:35     ` Graeme Russ
  2011-05-24  5:31       ` Reinhard Meyer
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-24  4:35 UTC (permalink / raw)
  To: u-boot

Mike,

On Tue, May 24, 2011 at 2:24 PM, Mike Frysinger <vapier@gentoo.org> wrote:
> rather than inventing our own set of terms, how about piggybacking what Linux
> has already done ? ?they have "cycle counters" and "timer counters" (which
> bubble up into "clock sources", but i dont think we need those).

I only put the terms in to clarify them within the scope of the document
to avoid the inevitable 'but that means x' arguments ;)

> further, Linux probably already has implementations we can steal for the arch-
> specific "cycle counters", and the common code which takes care of scaling
> those into actual measurements of time.

Maybe - but I think the Linux implementation might be a bit too heavy
handed - We only need a very lightweight, simple implementation. Despite
the appearance of my write-up, the suggested implementation is very
simple:

 - A common software prescaler in /lib/ (not needed if hardware provides
   an exact 1ms period counter)
 - Arch specific implementation of tick counter (already there)
 - Arch specific hook into prescaler (not needed if tick counter has a
   'long enough' roll-over period or is 1ms, otherwise a tiny ISR which
   simply calls the prescaler)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  4:35     ` Graeme Russ
@ 2011-05-24  5:31       ` Reinhard Meyer
  2011-05-24  5:43         ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Reinhard Meyer @ 2011-05-24  5:31 UTC (permalink / raw)
  To: u-boot

I know its futile to repeat what I suggested about 9 months ago...

Since get_timer() is only used (to my knowledge) to break out of
loops that do not terminate normally because an expected event does
not occur, the following API would be simpler and take less time per
loop:

(I use the names A and B to avoid nitpicking on real function names
which can be later chosen arbitrarily if this idea prevails...)

uint timeout = A(timeout_in_ms);

do {...} while (!B(timeout));

OR

for (;;) {
   dowhatever...
   if (B(timeout)) {
     error_handling...
     break;
   }
}

Internally both functions would be rather trival:

uint A(uint timeout_in_ms):

return current_tick + timeout_in_ms * ticks_per_ms;

or - for better precision if ticks_per_ms is not a whole number:

return current_tick + (timeout_in_ms * ticks_per_second) / 1000;

or any fractional method to more exactly calculate that equation
without needing a 64 bit divide.

bool B(uint end_tick):

a simple unsigned subtraction of end_tick minus current_tick,
evaluating the carry flag. Since we don't get a carry flag in C
a simple methods will do:
return ((int)(end_tick - current_tick)) < 0;

options:
current_tick needs only to be uint32, to get to the largest possible timeout
any 64 bit tick counter can be right shifted to get a 32 bit value that
increments just faster than 1ms.

features:
the only complicated calculation is done before the loop starts, the loop
itself is not made significantly slower since only a subtraction (and maybe
shift to scale down a high speed tick) is required.

Reinhard

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  5:31       ` Reinhard Meyer
@ 2011-05-24  5:43         ` Graeme Russ
  2011-05-24  6:11           ` Albert ARIBAUD
  2011-05-24 13:29           ` Scott McNutt
  0 siblings, 2 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-24  5:43 UTC (permalink / raw)
  To: u-boot

Dear Reinhard,

On Tue, May 24, 2011 at 3:31 PM, Reinhard Meyer
<u-boot@emk-elektronik.de> wrote:
> I know its futile to repeat what I suggested about 9 months ago...
>
> Since get_timer() is only used (to my knowledge) to break out of
> loops that do not terminate normally because an expected event does
> not occur, the following API would be simpler and take less time per
> loop:
>
> (I use the names A and B to avoid nitpicking on real function names
> which can be later chosen arbitrarily if this idea prevails...)
>
> uint timeout = A(timeout_in_ms);
>
> do {...} while (!B(timeout));
>
> OR
>
> for (;;) {
> ?dowhatever...
> ?if (B(timeout)) {
> ? ?error_handling...
> ? ?break;
> ?}
> }
>
> Internally both functions would be rather trival:
>
> uint A(uint timeout_in_ms):
>
> return current_tick + timeout_in_ms * ticks_per_ms;
>
> or - for better precision if ticks_per_ms is not a whole number:
>
> return current_tick + (timeout_in_ms * ticks_per_second) / 1000;
>
> or any fractional method to more exactly calculate that equation
> without needing a 64 bit divide.
>
> bool B(uint end_tick):
>
> a simple unsigned subtraction of end_tick minus current_tick,
> evaluating the carry flag. Since we don't get a carry flag in C
> a simple methods will do:
> return ((int)(end_tick - current_tick)) < 0;
>

Elegant and simple but precludes using get_timer() to perform any
meaningful time measurement - However this can be resolved by
doing

	start = get_current_tick();
	...
	duration = get_elapsed_ms(start);

get_elapsed_ms() converts (current_tick - start) to ms. It can still be
a common library routine which calls a HAL function get_tick_frequency()

> options:
> current_tick needs only to be uint32, to get to the largest possible timeout
> any 64 bit tick counter can be right shifted to get a 32 bit value that
> increments just faster than 1ms.
>
> features:
> the only complicated calculation is done before the loop starts, the loop
> itself is not made significantly slower since only a subtraction (and maybe
> shift to scale down a high speed tick) is required.
>

But we run into problems when the tick counter is only 32-bit and the tick
frequency very fast so we would need to extend the tick counter to 64-bit
and have to periodically update it.

Nevertheless, I think we have two very viable options :)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  5:43         ` Graeme Russ
@ 2011-05-24  6:11           ` Albert ARIBAUD
  2011-05-24  7:10             ` Graeme Russ
  2011-05-24 14:12             ` Wolfgang Denk
  2011-05-24 13:29           ` Scott McNutt
  1 sibling, 2 replies; 101+ messages in thread
From: Albert ARIBAUD @ 2011-05-24  6:11 UTC (permalink / raw)
  To: u-boot

Le 24/05/2011 07:43, Graeme Russ a ?crit :
> Dear Reinhard,
>
> On Tue, May 24, 2011 at 3:31 PM, Reinhard Meyer
> <u-boot@emk-elektronik.de>  wrote:
>> I know its futile to repeat what I suggested about 9 months ago...
>>
>> Since get_timer() is only used (to my knowledge) to break out of
>> loops that do not terminate normally because an expected event does
>> not occur, the following API would be simpler and take less time per
>> loop:
>>
>> (I use the names A and B to avoid nitpicking on real function names
>> which can be later chosen arbitrarily if this idea prevails...)
>>
>> uint timeout = A(timeout_in_ms);
>>
>> do {...} while (!B(timeout));
>>
>> OR
>>
>> for (;;) {
>>   dowhatever...
>>   if (B(timeout)) {
>>     error_handling...
>>     break;
>>   }
>> }
>>
>> Internally both functions would be rather trival:
>>
>> uint A(uint timeout_in_ms):
>>
>> return current_tick + timeout_in_ms * ticks_per_ms;
>>
>> or - for better precision if ticks_per_ms is not a whole number:
>>
>> return current_tick + (timeout_in_ms * ticks_per_second) / 1000;
>>
>> or any fractional method to more exactly calculate that equation
>> without needing a 64 bit divide.
>>
>> bool B(uint end_tick):
>>
>> a simple unsigned subtraction of end_tick minus current_tick,
>> evaluating the carry flag. Since we don't get a carry flag in C
>> a simple methods will do:
>> return ((int)(end_tick - current_tick))<  0;
>>
>
> Elegant and simple but precludes using get_timer() to perform any
> meaningful time measurement - However this can be resolved by
> doing
>
> 	start = get_current_tick();
> 	...
> 	duration = get_elapsed_ms(start);
>
> get_elapsed_ms() converts (current_tick - start) to ms. It can still be
> a common library routine which calls a HAL function get_tick_frequency()
>
>> options:
>> current_tick needs only to be uint32, to get to the largest possible timeout
>> any 64 bit tick counter can be right shifted to get a 32 bit value that
>> increments just faster than 1ms.
>>
>> features:
>> the only complicated calculation is done before the loop starts, the loop
>> itself is not made significantly slower since only a subtraction (and maybe
>> shift to scale down a high speed tick) is required.
>>
>
> But we run into problems when the tick counter is only 32-bit and the tick
> frequency very fast so we would need to extend the tick counter to 64-bit
> and have to periodically update it.
>
> Nevertheless, I think we have two very viable options :)


Not sure I still follow what the two options are -- a heads up is welcome.

However, I do like the simplicity in having a single time unit (ticks) 
for the timer API -- asuming it covers all needs -- and providing other 
time units only as helper functions.

 > Regards,
 >
 > Graeme

> Regards,
>
> Graeme

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  6:11           ` Albert ARIBAUD
@ 2011-05-24  7:10             ` Graeme Russ
  2011-05-24 14:15               ` Wolfgang Denk
  2011-05-24 14:12             ` Wolfgang Denk
  1 sibling, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-24  7:10 UTC (permalink / raw)
  To: u-boot

On 24/05/11 16:11, Albert ARIBAUD wrote:
> Le 24/05/2011 07:43, Graeme Russ a ?crit :
>> Dear Reinhard,
>>
>> On Tue, May 24, 2011 at 3:31 PM, Reinhard Meyer
>> <u-boot@emk-elektronik.de>  wrote:
>>> I know its futile to repeat what I suggested about 9 months ago...
>>>
>>> Since get_timer() is only used (to my knowledge) to break out of
>>> loops that do not terminate normally because an expected event does
>>> not occur, the following API would be simpler and take less time per
>>> loop:
>>>
>>> (I use the names A and B to avoid nitpicking on real function names
>>> which can be later chosen arbitrarily if this idea prevails...)
>>>
>>> uint timeout = A(timeout_in_ms);
>>>
>>> do {...} while (!B(timeout));
>>>
>>> OR
>>>
>>> for (;;) {
>>>   dowhatever...
>>>   if (B(timeout)) {
>>>     error_handling...
>>>     break;
>>>   }
>>> }
>>>
>>> Internally both functions would be rather trival:
>>>
>>> uint A(uint timeout_in_ms):
>>>
>>> return current_tick + timeout_in_ms * ticks_per_ms;
>>>
>>> or - for better precision if ticks_per_ms is not a whole number:
>>>
>>> return current_tick + (timeout_in_ms * ticks_per_second) / 1000;
>>>
>>> or any fractional method to more exactly calculate that equation
>>> without needing a 64 bit divide.
>>>
>>> bool B(uint end_tick):
>>>
>>> a simple unsigned subtraction of end_tick minus current_tick,
>>> evaluating the carry flag. Since we don't get a carry flag in C
>>> a simple methods will do:
>>> return ((int)(end_tick - current_tick))<  0;
>>>
>>
>> Elegant and simple but precludes using get_timer() to perform any
>> meaningful time measurement - However this can be resolved by
>> doing
>>
>>     start = get_current_tick();
>>     ...
>>     duration = get_elapsed_ms(start);
>>
>> get_elapsed_ms() converts (current_tick - start) to ms. It can still be
>> a common library routine which calls a HAL function get_tick_frequency()
>>
>>> options:
>>> current_tick needs only to be uint32, to get to the largest possible
>>> timeout
>>> any 64 bit tick counter can be right shifted to get a 32 bit value that
>>> increments just faster than 1ms.
>>>
>>> features:
>>> the only complicated calculation is done before the loop starts, the loop
>>> itself is not made significantly slower since only a subtraction (and maybe
>>> shift to scale down a high speed tick) is required.
>>>
>>
>> But we run into problems when the tick counter is only 32-bit and the tick
>> frequency very fast so we would need to extend the tick counter to 64-bit
>> and have to periodically update it.
>>
>> Nevertheless, I think we have two very viable options :)
> 
> 
> Not sure I still follow what the two options are -- a heads up is welcome.

1) get_timer() returning milliseconds
2) get_current_ticks() + ticks_to_ms()

> However, I do like the simplicity in having a single time unit (ticks) for
> the timer API -- asuming it covers all needs -- and providing other time
> units only as helper functions.

My preference is to expose SI (and derivative) units of time measurement
(seconds, milliseconds, microseconds) only to the outside world (drivers,
stand alone applications etc)

The truth of the matter is, the proposed API will expose both - There will
be a HAL function get_ticks() which is used by the prescaler and a
get_tick_frequency() HAL function. So there will be nothing stopping
someone (apart from a mandate not to) using 'ticks'

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  5:43         ` Graeme Russ
  2011-05-24  6:11           ` Albert ARIBAUD
@ 2011-05-24 13:29           ` Scott McNutt
  2011-05-24 14:19             ` Wolfgang Denk
  1 sibling, 1 reply; 101+ messages in thread
From: Scott McNutt @ 2011-05-24 13:29 UTC (permalink / raw)
  To: u-boot

Graeme Russ wrote:
> Dear Reinhard,
> 
> On Tue, May 24, 2011 at 3:31 PM, Reinhard Meyer
> <u-boot@emk-elektronik.de> wrote:
>> I know its futile to repeat what I suggested about 9 months ago...
>>
>> Since get_timer() is only used (to my knowledge) to break out of
>> loops that do not terminate normally because an expected event does
>> not occur, the following API would be simpler and take less time per
>> loop:
...

> Elegant and simple but precludes using get_timer() to perform any
> meaningful time measurement

...

Why must get_timer() be used to perform "meaningful time measurement?"

If all of this is about time measurement, why not start with your dream
time measurement API, and go from there? And make it an optional
feature.

If the existing API, that has been used successfully for years,
primarily as a mechanism for detecting a time-out, has issues,
then let's resolve _those_ issues and avoid the "car-boat" ... the
vehicle that floats like a car and handles like a boat. ;-)

Regards,
--Scott

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  6:11           ` Albert ARIBAUD
  2011-05-24  7:10             ` Graeme Russ
@ 2011-05-24 14:12             ` Wolfgang Denk
  2011-05-24 15:23               ` J. William Campbell
  1 sibling, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-24 14:12 UTC (permalink / raw)
  To: u-boot

Dear Albert ARIBAUD,

In message <4DDB4C1C.7030301@aribaud.net> you wrote:
>
> Not sure I still follow what the two options are -- a heads up is welcome.
> However, I do like the simplicity in having a single time unit (ticks)
> for the timer API -- asuming it covers all needs -- and providing other
> time units only as helper functions.

I don't think using ticks is a good idea.  You would need to change
all definitiuons of timeouts and delays and such.

Why not using a scaled unit like microsecods or the currently used
milliseconds?

I wonder why we suddenly have to change everything that has been
working fine for more than a decade (ignoring the large number of
incorrect, incomplete or broken implementations).  But so far we
really never needed anything else but  udelay()  for the typical short
device related timeouts, and  get_time()  for longer, often protocol
defined,  timeouts.

Is there anything wrong with these two solutions, based on standard
units (us and ms) ?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Do not follow where the path may lead....go instead where there is no
path and leave a trail.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24  7:10             ` Graeme Russ
@ 2011-05-24 14:15               ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-24 14:15 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDB59CD.2020009@gmail.com> you wrote:
>
> My preference is to expose SI (and derivative) units of time measurement
> (seconds, milliseconds, microseconds) only to the outside world (drivers,
> stand alone applications etc)

Please delete the "to the outside world ..." part.

> The truth of the matter is, the proposed API will expose both - There will
> be a HAL function get_ticks() which is used by the prescaler and a
> get_tick_frequency() HAL function. So there will be nothing stopping
> someone (apart from a mandate not to) using 'ticks'

I am tempted to NAK this right here.  I would like to see ticks as an
internal implementation detail only, and only be used as far as it is
necessary to provide proper scaled timer services.  All public
interfaces shall always only used scaled units.

Again: what's wrong with the us based udelay() and the ms based
get_timer() we have now?


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Syntactic sugar causes cancer of the semicolon.
                - Epigrams in Programming, ACM SIGPLAN Sept. 1982

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 13:29           ` Scott McNutt
@ 2011-05-24 14:19             ` Wolfgang Denk
  2011-05-24 16:51               ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-24 14:19 UTC (permalink / raw)
  To: u-boot

Dear Scott McNutt,

In message <4DDBB29D.2050102@psyent.com> you wrote:
>
> Why must get_timer() be used to perform "meaningful time measurement?"

Excellent question!  It was never intended to be used as such.

Also, neither udelay() nor get_timer() make any warranties about
accuracy or precision. If they are a few percent off, that's perfectly
fine. Even if they are 10% off this is not a big problem anywhere.

> If all of this is about time measurement, why not start with your dream
> time measurement API, and go from there? And make it an optional
> feature.

D'acore.

> If the existing API, that has been used successfully for years,
> primarily as a mechanism for detecting a time-out, has issues,
> then let's resolve _those_ issues and avoid the "car-boat" ... the
> vehicle that floats like a car and handles like a boat. ;-)

:-)

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Sometimes a man will tell his bartender things he'll never tell his doctor.
	-- Dr. Phillip Boyce, "The Menagerie" ("The Cage"),
	   stardate unknown.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 14:12             ` Wolfgang Denk
@ 2011-05-24 15:23               ` J. William Campbell
  2011-05-24 19:09                 ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-24 15:23 UTC (permalink / raw)
  To: u-boot

On 5/24/2011 7:12 AM, Wolfgang Denk wrote:
> Dear Albert ARIBAUD,
>
> In message<4DDB4C1C.7030301@aribaud.net>  you wrote:
>> Not sure I still follow what the two options are -- a heads up is welcome.
>> However, I do like the simplicity in having a single time unit (ticks)
>> for the timer API -- asuming it covers all needs -- and providing other
>> time units only as helper functions.
> I don't think using ticks is a good idea.  You would need to change
> all definitiuons of timeouts and delays and such.
>
> Why not using a scaled unit like microsecods or the currently used
> milliseconds?
>
> I wonder why we suddenly have to change everything that has been
> working fine for more than a decade (ignoring the large number of
> incorrect, incomplete or broken implementations).  But so far we
> really never needed anything else but  udelay()  for the typical short
> device related timeouts, and  get_time()  for longer, often protocol
> defined,  timeouts.
>
> Is there anything wrong with these two solutions, based on standard
> units (us and ms) ?
Hi All,
         After really looking into this, I think I agree with Wolfgang 
that using ms for a get_timer timebase is the best way to go. This 
thinking is heavily influenced (in my case anyway) by the fact that in 
the interrupt driven cases (and these are the ONLY fully compliant cases 
ATM I think), the "cost" of using ms is 0, because that is the "native" 
unit in which the timer ticks. This makes everything real simple. We 
can, right today, produce an API that supports u32 get_time_ms(void) for 
all CPUs in use. This would allow u32 get_timer(u32 base) to continue to 
exist as-is. These implementations would still be technically "broken" 
in the non-interrupt case, but they would work at least as well as they 
presently do. In fact, they would operate better because they would all 
use a single routine, not a bunch of different routines (some of which I 
am pretty sure have errors). Wolfgang would need to accept the fact that 
we are not yet "fixing" all the non-interrupt cases. This needs to be 
done, but is a different problem (I hope). In the non-interrupt case 
there is some cost in converting to ms from the native units, but we are 
in a timout loop, so a few extra instructions do not matter much. It is 
only a few 32 bit multiplies, which these days are real fast. If we can 
figure out how to use interrupts eventually, even this will go away.

         Then, we can ADD an optional performance measuring API like 
Scott suggests. This API would be something similar to the following:
struct ticks
{
     u32    tickmsb;
     u32   ticklsb;
} ;
struct time_value
{
   u32 seconds;
   u 32 nano_seconds;
};


and the functions would be get_ticks(struct ticks * p) , 
get_tick_delta(struct ticks * minuend, struct ticks * subtrahend),  
and   cvt_tick_delta(struct time_value * result, struct ticks *input). I 
didn't use u64 on purpose, because I don't want any un-necessary 
functions pulled from the library. get_ticks reads a "hi precision" 
counter. How high the precision is depends on the hardware. 
get_tick_delta subtracts two tick values, leaving the difference in the 
first operand. Yes, this is may be simple to do in open code but it is 
better to hide the details. (What if msb is seconds and lsb is 
nanoseconds, then it is not so simple). cvt_tick_delta converts from 
ticks to seconds and nano_seconds. We also need a u32 
get_tick_resolution, which would return the tick resolution in ns. The 
user never needs to do any arithmetic on ticks, so that makes his life 
much easier. However, the user may want to know the resolution of these 
measurements. All these functions are quite fast except possibly 
cvt_tick_delta, which is only needed for printing anyway.
         If the hardware has a performance monitoring counter, 
implementing these functions is quite simple. The PPC and the x86 
certainly do (well, any x86 pentium and above anyway). This is a whole 
lot of chips off our plate. In cases where no such counter exists, we 
will use whatever counters there are available already. Some of the ARM 
counters are running at 32 kHz, so their resolution won't be great, but 
it is what it is. If we find out that some of these other CPUs have a 
performance counter, we will use it. This API will be completely 
optional in u-boot and can be removed by changing a #define.
Thoughts welcome.

Best Regards,
Bill Campbell

> Best regards,
>
> Wolfgang Denk
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 14:19             ` Wolfgang Denk
@ 2011-05-24 16:51               ` Graeme Russ
  2011-05-24 18:59                 ` J. William Campbell
                                   ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-24 16:51 UTC (permalink / raw)
  To: u-boot

On 25/05/11 00:19, Wolfgang Denk wrote:
> Dear Scott McNutt,
> 
> In message <4DDBB29D.2050102@psyent.com> you wrote:
>>
>> Why must get_timer() be used to perform "meaningful time measurement?"
> 
> Excellent question!  It was never intended to be used as such.

Because get_timer() as it currently stands can as it is assumed to return
milliseconds

> Also, neither udelay() nor get_timer() make any warranties about
> accuracy or precision. If they are a few percent off, that's perfectly
> fine. Even if they are 10% off this is not a big problem anywhere.
> 
>> If all of this is about time measurement, why not start with your dream
>> time measurement API, and go from there? And make it an optional
>> feature.
> 
> D'acore.
> 
>> If the existing API, that has been used successfully for years,
>> primarily as a mechanism for detecting a time-out, has issues,
>> then let's resolve _those_ issues and avoid the "car-boat" ... the
>> vehicle that floats like a car and handles like a boat. ;-)
> 
> :-)

OK, let's wind back - My original suggestion made no claim towards changing
what the API is used for, or how it looks to those who use it (for all
practical intents and purposes). I suggested:
 - Removing set_timer() and reset_timer()
 - Implement get_timer() as a platform independent function

Lets look at two real-world implementations of my suggested solution - One
which 'exposes' ticks and one which does not..

=============
Exposing ticks and tick_frequency to everyone via a 'tick' HAL

In /lib/timer.c

void prescaler(void)
{
	u32 ticks = get_ticks();
	u32 tick_frequency = get_tick_frequency();

	/* Bill's algorithm */

	/* result stored in gd->timer_in_ms; */
}

u32 get_timer(u32 base)
{
	prescaler(ticks, tick_frequency);

	return gd->timer_in_ms - base;
}

In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c

u32 get_ticks(void)
{
	u32 ticks;

	/* Get ticks from hardware counter */

	return ticks;
}

u32 get_tick_frequency(void)
{
	u32 tick_frequency;

	/* Determine tick frequency - likely very trivial */

	return tick_frequency;
}

=======================
Not exposing ticks and tick_frequency to everyone

In /lib/timer.c

void prescaler(u32 ticks, u32 tick_frequency)
{
	u32 current_ms;

	/* Bill's algorithm */

	/* result stored in gd->timer_in_ms; */
}

In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c

static u32 get_ticks(void)
{
	u32 ticks;

	/* Get ticks from hardware counter */

	return ticks;
}

static u32 get_tick_frequency(void)
{
	u32 tick_frequency;

	/* Determine tick frequency */

	return tick_frequency;
}

u32 get_timer(u32 base)
{
	u32 ticks = get_ticks();
	u32 tick_frequency = get_tick_frequency();

	prescaler(ticks, tick_frequency);

	return gd->timer_in_ms - base;
}

===============
I personally prefer the first - There is only one implementation of
get_timer() in the entire code and the platform implementer never has to
concern themselves with what the tick counter is used for. If the API gets
extended to include get_timer_in_seconds() there is ZERO impact on
platforms. Using the second method, any new feature would have to be
implemented on all platforms - and we all know how well that works ;)

And what about those few platforms that are actually capable of generating
a 1ms timebase (either via interrupts or natively in a hardware counter)
without the prescaler? Well, with prescaler() declared weak, all you need
to do in /arch/cpu/soc/timer.c or /arch/cpu/timer.c or
/board/<board>/timer.c is:

For platforms with a 1ms hardware counter:
void prescaler(void /* or u32 ticks, u32 tick_frequency*/)
{
	gd->timer_in_ms = get_milliseconds();
}

For platforms with a 1ms interrupt source:
void timer_isr(void *unused)
{
	gd->timer_in_ms++;
}

void prescaler(void /* or u32 ticks, u32 tick_frequency*/)
{
}


And finally, if the platform supports interrupts but either the hardware
counter has better accuracy than the interrupt generator or the interrupt
generator cannot generate 1ms interrupts, configure the interrupt generator
to fire at any rate better than the tick counter rollover listed in
previous post and:

void timer_isr(void *unused)
{
	/*
	 * We are here to stop the tick counter rolling over. All we
	 * need to do is kick the prescaler - get_timer() does that :)
	 */
	get_timer(0);
}

In summary, platform specific code reduces to:
 - For a platform that cannot generate 1ms interrupts AND the hardware
   counter is not in ms
   - Implement get_ticks() and get_tick_frequency()
   - Optionally implement as ISR to kick the prescaler
 - For a platform that can generate 1ms interrupts, or the hardware
   counter is in ms
   - Override the prescaler() function to do nothing

If none of the above not look 'simple', I invite you to have a look in
arch/arm ;)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 16:51               ` Graeme Russ
@ 2011-05-24 18:59                 ` J. William Campbell
  2011-05-24 19:31                   ` Wolfgang Denk
  2011-05-24 19:19                 ` Wolfgang Denk
  2011-05-25 12:36                 ` Scott McNutt
  2 siblings, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-24 18:59 UTC (permalink / raw)
  To: u-boot

On 5/24/2011 9:51 AM, Graeme Russ wrote:
> On 25/05/11 00:19, Wolfgang Denk wrote:
> =============
<snip>
Hi all,
         I have a few of questions.
First, it seems that the get_timer interface is expected to work 
properly only after relocation and only when bss is available. I say 
this because the PPC version uses an (initialized) variable, timestamp, 
to hold the time. If that is the case, there is no need to hold the 
timer static data in gd, as I have been doing up to  now. Am I correct ?
      Second, udelay is expected to be available before  bss is 
available, very early in the startup process. There a comments to that 
effect in several places in the code. Therefore, udelay cannot use 
global or static variables. Is this true?
     And third, udelay is only expected/required to work correctly for 
"short", like say 10 seconds. I say this based on comments contained in 
powerpr/lib/time.c. Please ack or nak this as well.

I have a couple of "small" changes to the previously submitted code, 
based partly on the above
> Exposing ticks and tick_frequency to everyone via a 'tick' HAL
>
> In /lib/timer.c

ulong timestamp = 0;
/*
      This routine is called to initialize the timer after BSS is available
*/
void  __weak prescaler_init(void)
{
     u32 tick_frequency = get_tick_frequency();
      /* initialize prescaler variables */
}

> void __weak prescaler(void)
> {
> 	u32 ticks = get_ticks();
                     /* Bill's algorithm */
                    /* result stored in timestamp; */
> }
>
> u32 get_timer(u32 base)
> {
#if defined(CONFIG_SYS_NEED_PRESCALER)
> 	prescaler();
#endif
> 	return timestamp - base;
> }
>
> In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c
>
> u32 get_ticks(void)
> {
> 	u32 ticks;
>
> 	/* Get ticks from hardware counter */
>
> 	return ticks;
> }
>
> u32 get_tick_frequency(void)
> {
> 	u32 tick_frequency;
>
> 	/* Determine tick frequency - likely very trivial */
>
> 	return tick_frequency;
> }
or instead the user may override prescaler_init and prescaler if, for 
some reason, a highly optimized version is desired. Note also that if 
the configuration variable CONFIG_SYS_NEED_PRESCALER is not defined, the 
additional prescaler routines will not be called anywhere so the 
routines should not be loaded. Yes, it it a #define to manage, but it 
should allow the existing u-boots to be the same size as before, with no 
unused code. This size matters to some people a lot!
> =======================
> Not exposing ticks and tick_frequency to everyone
>
> In /lib/timer.c
>
> void prescaler(u32 ticks, u32 tick_frequency)
> {
> 	u32 current_ms;
>
> 	/* Bill's algorithm */
>
> 	/* result stored in gd->timer_in_ms; */
> }
>
> In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c
>
> static u32 get_ticks(void)
> {
> 	u32 ticks;
>
> 	/* Get ticks from hardware counter */
>
> 	return ticks;
> }
>
> static u32 get_tick_frequency(void)
> {
> 	u32 tick_frequency;
>
> 	/* Determine tick frequency */
>
> 	return tick_frequency;
> }
>
> u32 get_timer(u32 base)
> {
> 	u32 ticks = get_ticks();
> 	u32 tick_frequency = get_tick_frequency();
>
> 	prescaler(ticks, tick_frequency);
>
> 	return gd->timer_in_ms - base;
> }
>
> ===============
> I personally prefer the first - There is only one implementation of
> get_timer() in the entire code and the platform implementer never has to
> concern themselves with what the tick counter is used for. If the API gets
> extended to include get_timer_in_seconds() there is ZERO impact on
> platforms. Using the second method, any new feature would have to be
> implemented on all platforms - and we all know how well that works ;)
>
> And what about those few platforms that are actually capable of generating
> a 1ms timebase (either via interrupts or natively in a hardware counter)
> without the prescaler? Well, with prescaler() declared weak, all you need
> to do in /arch/cpu/soc/timer.c or /arch/cpu/timer.c or
> /board/<board>/timer.c is:
>
> For platforms with a 1ms hardware counter:
> void prescaler(void /* or u32 ticks, u32 tick_frequency*/)
> {
> 	gd->timer_in_ms = get_milliseconds();
> }
>
> For platforms with a 1ms interrupt source:
> void timer_isr(void *unused)
> {
> 	gd->timer_in_ms++;
> }
>
> void prescaler(void /* or u32 ticks, u32 tick_frequency*/)
> {
> }
>
>
> And finally, if the platform supports interrupts but either the hardware
> counter has better accuracy than the interrupt generator or the interrupt
> generator cannot generate 1ms interrupts, configure the interrupt generator
> to fire at any rate better than the tick counter rollover listed in
> previous post and:
>
> void timer_isr(void *unused)
> {
> 	/*
> 	 * We are here to stop the tick counter rolling over. All we
> 	 * need to do is kick the prescaler - get_timer() does that :)
> 	 */
> 	get_timer(0);
> }
>
> In summary, platform specific code reduces to:
>   - For a platform that cannot generate 1ms interrupts AND the hardware
>     counter is not in ms
>     - Implement get_ticks() and get_tick_frequency()
>     - Optionally implement as ISR to kick the prescaler
>   - For a platform that can generate 1ms interrupts, or the hardware
>     counter is in ms
>     - Override the prescaler() function to do nothing
>
> If none of the above not look 'simple', I invite you to have a look in
> arch/arm ;)
>
> Regards,
>
> Graeme
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 15:23               ` J. William Campbell
@ 2011-05-24 19:09                 ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-24 19:09 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDBCD69.9090408@comcast.net> you wrote:
>
>          After really looking into this, I think I agree with Wolfgang 
> that using ms for a get_timer timebase is the best way to go. This 
> thinking is heavily influenced (in my case anyway) by the fact that in 
> the interrupt driven cases (and these are the ONLY fully compliant cases 
> ATM I think), the "cost" of using ms is 0, because that is the "native" 
> unit in which the timer ticks. This makes everything real simple. We 
> can, right today, produce an API that supports u32 get_time_ms(void) for 
> all CPUs in use. This would allow u32 get_timer(u32 base) to continue to 
> exist as-is. These implementations would still be technically "broken" 
> in the non-interrupt case, but they would work at least as well as they 
> presently do. In fact, they would operate better because they would all 
> use a single routine, not a bunch of different routines (some of which I 
> am pretty sure have errors). Wolfgang would need to accept the fact that 
> we are not yet "fixing" all the non-interrupt cases. This needs to be 
> done, but is a different problem (I hope). In the non-interrupt case 

I see this as you do, so this there will be no problems for me to
"accept" this.

Thanks!

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
You know that feeling when you're leaning back  on  a  stool  and  it
starts to tip over? Well, that's how I feel all the time.
- Steven Wright

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 16:51               ` Graeme Russ
  2011-05-24 18:59                 ` J. William Campbell
@ 2011-05-24 19:19                 ` Wolfgang Denk
  2011-05-24 22:32                   ` J. William Campbell
  2011-05-25  0:17                   ` Graeme Russ
  2011-05-25 12:36                 ` Scott McNutt
  2 siblings, 2 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-24 19:19 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDBE22D.6050806@gmail.com> you wrote:
>
> >> Why must get_timer() be used to perform "meaningful time measurement?"
> > 
> > Excellent question!  It was never intended to be used as such.
> 
> Because get_timer() as it currently stands can as it is assumed to return
> milliseconds

Yes, but without any guarantee for accuracy or resolution.
This is good enough for timeouts, but nothing for time measurements.

> OK, let's wind back - My original suggestion made no claim towards changing
> what the API is used for, or how it looks to those who use it (for all
> practical intents and purposes). I suggested:
>  - Removing set_timer() and reset_timer()
>  - Implement get_timer() as a platform independent function

Trying to remember what I have read in this thread I believe we have
an agreement on these.

> Exposing ticks and tick_frequency to everyone via a 'tick' HAL

I skip this.  I don't even read it.

> =======================
> Not exposing ticks and tick_frequency to everyone
> 
> In /lib/timer.c
> 
> void prescaler(u32 ticks, u32 tick_frequency)
> {
> 	u32 current_ms;
> 
> 	/* Bill's algorithm */
> 
> 	/* result stored in gd->timer_in_ms; */
> }
> 
> In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c
> 
> static u32 get_ticks(void)

Currently we have unsigned long long get_ticks(void)  which is better
as it matches existing hardware.

Note that we also have void wait_ticks(u32) as needed for udelay().

> static u32 get_tick_frequency(void)
> {
> 	u32 tick_frequency;
> 
> 	/* Determine tick frequency */
> 
> 	return tick_frequency;
> }

Note that we also have u32 usec2ticks(u32 usec) and u32 ticks2usec(u32 ticks).

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Madness has no purpose.  Or reason.  But it may have a goal.
	-- Spock, "The Alternative Factor", stardate 3088.7

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 18:59                 ` J. William Campbell
@ 2011-05-24 19:31                   ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-24 19:31 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDBFFF5.1020601@comcast.net> you wrote:
>
> First, it seems that the get_timer interface is expected to work 
> properly only after relocation and only when bss is available. I say 
> this because the PPC version uses an (initialized) variable, timestamp, 
> to hold the time. If that is the case, there is no need to hold the 
> timer static data in gd, as I have been doing up to  now. Am I correct ?

Yes.

>       Second, udelay is expected to be available before  bss is 
> available, very early in the startup process. There a comments to that 
> effect in several places in the code. Therefore, udelay cannot use 
> global or static variables. Is this true?

Yes.

>      And third, udelay is only expected/required to work correctly for 
> "short", like say 10 seconds. I say this based on comments contained in 
> powerpr/lib/time.c. Please ack or nak this as well.

Depending on CPU type and clock, it may be as low as 1 second, or
less. udelay() is based on wait_ticks(), which receives a u32
argument. Assume we have a tick rate of 1 GHz or so, and be prepared
for faster processors.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"IBM uses what I like to call the 'hole-in-the-ground  technique'  to
destroy  the  competition.....  IBM digs a big HOLE in the ground and
covers it with leaves. It then puts a big POT OF GOLD nearby. Then it
gives the call, 'Hey, look at all this gold, get over here fast.'  As
soon  as  the competitor approaches the pot, he falls into the pit"
                                                     - John C. Dvorak

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 19:19                 ` Wolfgang Denk
@ 2011-05-24 22:32                   ` J. William Campbell
  2011-05-25  5:17                     ` Wolfgang Denk
  2011-05-25  0:17                   ` Graeme Russ
  1 sibling, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-24 22:32 UTC (permalink / raw)
  To: u-boot

On 5/24/2011 12:19 PM, Wolfgang Denk wrote:
> Dear Graeme Russ,
>
> In message<4DDBE22D.6050806@gmail.com>  you wrote:
>>>> Why must get_timer() be used to perform "meaningful time measurement?"
>>> Excellent question!  It was never intended to be used as such.
>> Because get_timer() as it currently stands can as it is assumed to return
>> milliseconds
> Yes, but without any guarantee for accuracy or resolution.
> This is good enough for timeouts, but nothing for time measurements.
>
>> OK, let's wind back - My original suggestion made no claim towards changing
>> what the API is used for, or how it looks to those who use it (for all
>> practical intents and purposes). I suggested:
>>   - Removing set_timer() and reset_timer()
>>   - Implement get_timer() as a platform independent function
> Trying to remember what I have read in this thread I believe we have
> an agreement on these.
>
>> Exposing ticks and tick_frequency to everyone via a 'tick' HAL
> I skip this.  I don't even read it.
>
>> =======================
>> Not exposing ticks and tick_frequency to everyone
>>
>> In /lib/timer.c
>>
>> void prescaler(u32 ticks, u32 tick_frequency)
>> {
>> 	u32 current_ms;
>>
>> 	/* Bill's algorithm */
>>
>> 	/* result stored in gd->timer_in_ms; */
>> }
>>
>> In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c
>>
>> static u32 get_ticks(void)
> Currently we have unsigned long long get_ticks(void)  which is better
> as it matches existing hardware.
>
> Note that we also have void wait_ticks(u32) as needed for udelay().
Hi All,
        I didn't comment before on the definition of ticks, but I fear 
that was unwise. The stated definition  was:

A tick is defined as the smallest increment of system time as measured by a
computer system (seehttp://en.wikipedia.org/wiki/System_time):

	System time is measured by a system clock, which is typically
	implemented as a simple count of the number of ticks that have
	transpired since some arbitrary starting date, called the
	epoch.


Unfortunately, this definition is obsolete, and has been for quite some 
years.  When computers had a single timer, the above definition worked, 
but it no longer does, as many (most?) computers have several hardware 
timers. A "tick" today is the time increment of any particular timer of 
a computer system. So, when one writes a function called get_ticks on a 
PPC, does one mean read the decrementer, or does one read the RTC or 
does one read the TB register(s) A similar situation exists on the 
Blackfin BF531/2/3, that has a preformance counter, a real-time clock, 
and three programmable timers. Which tick do you want? For each u-boot 
implementation, we can pick one timer as the "master" timer, but it may 
not be the one with the most rapid tick rate. It may be the one with the 
most USEFUL tick rate for get_timer. If you take the above definition at 
face value, only the fastest counter value has ticks, and all other 
counters time increments are not ticks. If they are not ticks, what are 
they?

This is one of the reasons I favor the performance monitoring system be 
separate from the get_timer timing methodology, as it will often use a 
different counter and time base anyway. That is also why I prefer to 
have a conversion routine that converts timer values to seconds and 
nano-seconds without reference to "tick" rates, so the user never has to 
deal with these ambiguities. Yes, "under the hood", somebody does, but 
that need not be specified in the external interface. )Nobody has yet 
commented on my proposed performance measuring functions, and I know 
this group well enough not to assume that silence implies consent! )

The prescaler function defined by Graeme needs to read some timer value. 
It turns out that a u32 value is the most appropriate value for the 
get_timer operation.  The value desired is usually not of hardware timer 
tick resolution. It should be the specific bits in the timer, such that 
the LSB resolution is between 1 ms and 0.5 ms. We use greater resolution 
that this only when the counter is short enough that we need lower 
significance bits to make the counter 32 bits. For that reason, the 
function should probably be call something like u32 
read_timer_value(void). I really don't much care what it is called as 
long as we understand what it does.

Best Regards,
Bill Campbell


>> static u32 get_tick_frequency(void)
>> {
>> 	u32 tick_frequency;
>>
>> 	/* Determine tick frequency */
>>
>> 	return tick_frequency;
>> }
> Note that we also have u32 usec2ticks(u32 usec) and u32 ticks2usec(u32 ticks).
>
> Best regards,
>
> Wolfgang Denk
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 19:19                 ` Wolfgang Denk
  2011-05-24 22:32                   ` J. William Campbell
@ 2011-05-25  0:17                   ` Graeme Russ
  2011-05-25  2:53                     ` J. William Campbell
  2011-05-25  5:25                     ` Wolfgang Denk
  1 sibling, 2 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-25  0:17 UTC (permalink / raw)
  To: u-boot

On Wed, May 25, 2011 at 5:19 AM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Graeme Russ,
>
> In message <4DDBE22D.6050806@gmail.com> you wrote:
>>
>> >> Why must get_timer() be used to perform "meaningful time measurement?"
>> >
>> > Excellent question! ?It was never intended to be used as such.
>>
>> Because get_timer() as it currently stands can as it is assumed to return
>> milliseconds
>
> 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.

(*)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.

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.

>> OK, let's wind back - My original suggestion made no claim towards changing
>> what the API is used for, or how it looks to those who use it (for all
>> practical intents and purposes). I suggested:
>> ?- Removing set_timer() and reset_timer()
>> ?- Implement get_timer() as a platform independent function
>
> Trying to remember what I have read in this thread I believe we have
> an agreement on these.
>
>> Exposing ticks and tick_frequency to everyone via a 'tick' HAL
>
> I skip this. ?I don't even read it.

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

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

>> =======================
>> Not exposing ticks and tick_frequency to everyone
>>
>> In /lib/timer.c
>>
>> void prescaler(u32 ticks, u32 tick_frequency)
>> {
>> ? ? ? u32 current_ms;
>>
>> ? ? ? /* Bill's algorithm */
>>
>> ? ? ? /* result stored in gd->timer_in_ms; */
>> }
>>
>> In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c
>>
>> static u32 get_ticks(void)
>
> Currently we have unsigned long long get_ticks(void) ?which 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

>
> Note that we also have void wait_ticks(u32) as needed for udelay().
>
>> static u32 get_tick_frequency(void)
>> {
>> ? ? ? u32 tick_frequency;
>>
>> ? ? ? /* Determine tick frequency */
>>
>> ? ? ? return tick_frequency;
>> }
>
> Note that we also have u32 usec2ticks(u32 usec) and u32 ticks2usec(u32 ticks).

Yes, they are better names

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  0:17                   ` Graeme Russ
@ 2011-05-25  2:53                     ` J. William Campbell
  2011-05-25  3:21                       ` Graeme Russ
  2011-05-25  5:28                       ` Wolfgang Denk
  2011-05-25  5:25                     ` Wolfgang Denk
  1 sibling, 2 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-25  2:53 UTC (permalink / raw)
  To: u-boot

On 5/24/2011 5:17 PM, Graeme Russ wrote:
> On Wed, May 25, 2011 at 5:19 AM, Wolfgang Denk<wd@denx.de>  wrote:
>> Dear Graeme Russ,
>>
>> In message<4DDBE22D.6050806@gmail.com>  you wrote:
>>>>> Why must get_timer() be used to perform "meaningful time measurement?"
>>>> Excellent question!  It was never intended to be used as such.
>>> Because get_timer() as it currently stands can as it is assumed to return
>>> milliseconds
>> 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.
Hi All,
        Well, it is not quite that simple. The "accuracy" of the 1 ms 
interrupt rate is controlled in all cases I know about by the resolution 
of the programmable divider used to produce it. It appears that the x86 
uses a 1.19318 MHz crystal oscillator to produce the nominal 1 ms timer 
tick. (There is a typo in line 30 of arch/x86/lib/pcat_timer.c that says 
1.9318. I couldn't make any of the numbers work until I figured this 
out). The tick is produced by dividing the 1.19318 rate999.313 by 1194, 
which produces an interrupt rate of 999.3 Hz, or about 0.068% error. 
However, the performance counter on an x86 is as exact as the crystal 
frequency of the CPU is. FWIW, you can read the performance counter with 
rdtsc on a 386/486 and the CYCLES and CYCLES2 registers on later 
Intel/AMD chips. So yes, there is at least one example of a cpu that 
does not use it's most accurate (or highest resolution) time source.
> (*)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.
>
> 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.
Are you sure of this? From what I see in arch/x86/lib/pcat_timer.c, the 
timer 0 is programmed to produce the 1 kHz rate timer tick and is also 
read repeatedly in __udelay to produce the delay value. They even 
preserve the 1194 inaccuracy, for some strange reason. I see that the 
sc520 does appear to use different timers for the interrupt source, and 
it would appear that it may be "exact", but I don't know what the input 
to the prescaler is so I can't be sure. Is the input to the prescaler 
really 8.3 MHz exactly? Also, is the same crystal used for the input to 
the prescaler counter and the "software timer millisecond count". If 
not, then we may have different accuracies in this case as well.

Also of note, it appears that the pcat_timer.c, udelay is not available 
intil interrupts are enabled. That is technically non-compliant, 
although it obviously seems not to matter.

Best Regards,
Bill Campbell
>>> OK, let's wind back - My original suggestion made no claim towards changing
>>> what the API is used for, or how it looks to those who use it (for all
>>> practical intents and purposes). I suggested:
>>>   - Removing set_timer() and reset_timer()
>>>   - Implement get_timer() as a platform independent function
>> Trying to remember what I have read in this thread I believe we have
>> an agreement on these.
>>
>>> Exposing ticks and tick_frequency to everyone via a 'tick' HAL
>> I skip this.  I don't even read it.
> 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
>
> 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
>
>>> =======================
>>> Not exposing ticks and tick_frequency to everyone
>>>
>>> In /lib/timer.c
>>>
>>> void prescaler(u32 ticks, u32 tick_frequency)
>>> {
>>>        u32 current_ms;
>>>
>>>        /* Bill's algorithm */
>>>
>>>        /* result stored in gd->timer_in_ms; */
>>> }
>>>
>>> In /arch/cpu/soc/timer.c or /arch/cpu/timer.c or /board/<board>/timer.c
>>>
>>> static u32 get_ticks(void)
>> Currently we have unsigned long long get_ticks(void)  which 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
>
>> Note that we also have void wait_ticks(u32) as needed for udelay().
>>
>>> static u32 get_tick_frequency(void)
>>> {
>>>        u32 tick_frequency;
>>>
>>>        /* Determine tick frequency */
>>>
>>>        return tick_frequency;
>>> }
>> Note that we also have u32 usec2ticks(u32 usec) and u32 ticks2usec(u32 ticks).
> Yes, they are better names
>
> Regards,
>
> Graeme
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  2:53                     ` J. William Campbell
@ 2011-05-25  3:21                       ` Graeme Russ
  2011-05-25  5:28                       ` Wolfgang Denk
  1 sibling, 0 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-25  3:21 UTC (permalink / raw)
  To: u-boot

On Wed, May 25, 2011 at 12:53 PM, J. William Campbell
<jwilliamcampbell@comcast.net> wrote:
> On 5/24/2011 5:17 PM, Graeme Russ wrote:
>>
>> On Wed, May 25, 2011 at 5:19 AM, Wolfgang Denk<wd@denx.de> ?wrote:
>>>
>>> Dear Graeme Russ,
>>>
>>> In message<4DDBE22D.6050806@gmail.com> ?you wrote:
>>>>>>
>>>>>> Why must get_timer() be used to perform "meaningful time measurement?"
>>>>>
>>>>> Excellent question! ?It was never intended to be used as such.
>>>>
>>>> Because get_timer() as it currently stands can as it is assumed to
>>>> return
>>>> milliseconds
>>>
>>> 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.
>
> Hi All,
> ? ? ? Well, it is not quite that simple. The "accuracy" of the 1 ms
> interrupt rate is controlled in all cases I know about by the resolution of
> the programmable divider used to produce it. It appears that the x86 uses a
> 1.19318 MHz crystal oscillator to produce the nominal 1 ms timer tick.
> (There is a typo in line 30 of arch/x86/lib/pcat_timer.c that says 1.9318. I

Thanks, I will fix that (although pcat_timer.c is not used by any current x86
board)

> couldn't make any of the numbers work until I figured this out). The tick is
> produced by dividing the 1.19318 rate999.313 by 1194, which produces an
> interrupt rate of 999.3 Hz, or about 0.068% error. However, the performance
> counter on an x86 is as exact as the crystal frequency of the CPU is. FWIW,
> you can read the performance counter with rdtsc on a 386/486 and the CYCLES

Hmm, I hadn't thought of that

> and CYCLES2 registers on later Intel/AMD chips. So yes, there is at least
> one example of a cpu that does not use it's most accurate (or highest
> resolution) time source.
>>
>> (*)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.
>>
>> 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.
>
> Are you sure of this? From what I see in arch/x86/lib/pcat_timer.c, the

Well, the only x86 board is an sc520 and does not used pcat_timer.c :)

Look in arch/x86/cpu/sc520/ and you might get a better picture

> timer 0 is programmed to produce the 1 kHz rate timer tick and is also read
> repeatedly in __udelay to produce the delay value. They even preserve the
> 1194 inaccuracy, for some strange reason. I see that the sc520 does appear
> to use different timers for the interrupt source, and it would appear that

Ah, you did ;)

> it may be "exact", but I don't know what the input to the prescaler is so I
> can't be sure. Is the input to the prescaler really 8.3 MHz exactly? Also,
> is the same crystal used for the input to the prescaler counter and the
> "software timer millisecond count". If not, then we may have different
> accuracies in this case as well.

Yes, they are both derived from the onboard xtal which can be either
33.000MHz or 33.333MHz (there is a system register that must be written
to to tell the sc520 what crystal is installed)

> Also of note, it appears that the pcat_timer.c, udelay is not available
> intil interrupts are enabled. That is technically non-compliant, although it
> obviously seems not to matter.

OK, it looks like x86 needs a bit of a timer overhaul - Thanks for the
heads-up

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 22:32                   ` J. William Campbell
@ 2011-05-25  5:17                     ` Wolfgang Denk
  2011-05-25 16:50                       ` J. William Campbell
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25  5:17 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDC31EB.6040609@comcast.net> you wrote:
...
> A tick is defined as the smallest increment of system time as measured by a
> computer system (seehttp://en.wikipedia.org/wiki/System_time):
> 
> 	System time is measured by a system clock, which is typically
> 	implemented as a simple count of the number of ticks that have
> 	transpired since some arbitrary starting date, called the
> 	epoch.
> 
> Unfortunately, this definition is obsolete, and has been for quite some 

Do you have any proof for such a claim?

> years.  When computers had a single timer, the above definition worked, 
> but it no longer does, as many (most?) computers have several hardware 
> timers. A "tick" today is the time increment of any particular timer of 
> a computer system. So, when one writes a function called get_ticks on a 
> PPC, does one mean read the decrementer, or does one read the RTC or 
> does one read the TB register(s) A similar situation exists on the 
> Blackfin BF531/2/3, that has a preformance counter, a real-time clock, 
> and three programmable timers. Which tick do you want? For each u-boot 

Please re-read the definition.  At least as far as U-Boot and Linux
are concerned, there is only a single clock source used to implement
the _system_time_.  And I doubt that other OS do different.

> implementation, we can pick one timer as the "master" timer, but it may 
> not be the one with the most rapid tick rate. It may be the one with the 
> most USEFUL tick rate for get_timer. If you take the above definition at 
> face value, only the fastest counter value has ticks, and all other 
> counters time increments are not ticks. If they are not ticks, what are 
> they?

Clocks, timers?


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Don't put off for tomorrow what you can  do  today,  because  if  you
enjoy it today you can do it again tomorrow.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  0:17                   ` Graeme Russ
  2011-05-25  2:53                     ` J. William Campbell
@ 2011-05-25  5:25                     ` Wolfgang Denk
  2011-05-25  6:02                       ` Graeme Russ
  1 sibling, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25  5:25 UTC (permalink / raw)
  To: u-boot

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).

> (*)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.

> 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.

> 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?

> 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.

> > 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.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
When in doubt, mumble;   when in trouble, delegate;  when in  charge,
ponder.                                             -- James H. Boren

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  2:53                     ` J. William Campbell
  2011-05-25  3:21                       ` Graeme Russ
@ 2011-05-25  5:28                       ` Wolfgang Denk
  2011-05-25  6:06                         ` Graeme Russ
  1 sibling, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25  5:28 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDC6F46.4090809@comcast.net> you wrote:
>
>         Well, it is not quite that simple. The "accuracy" of the 1 ms 
> interrupt rate is controlled in all cases I know about by the resolution 
> of the programmable divider used to produce it. It appears that the x86 

I mentioned a couple of times before that accuracy has never been a
design criterion.  Please also keep in mind that there are areas in
the code where we block interrupts, and we make zero efforts to detect
or compensate for this in the timer code.  This simply is not
important.  We are not talking about ppm here, we are talking about
somting that is just good enough for what it is being used, and that
allows easily for +/- 10% tolerances.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"We don't care.  We don't have to.  We're the Phone Company."

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  5:25                     ` Wolfgang Denk
@ 2011-05-25  6:02                       ` Graeme Russ
  2011-05-25  8:06                         ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25  6:02 UTC (permalink / raw)
  To: u-boot

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

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  5:28                       ` Wolfgang Denk
@ 2011-05-25  6:06                         ` Graeme Russ
  2011-05-25  8:08                           ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25  6:06 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

On Wed, May 25, 2011 at 3:28 PM, Wolfgang Denk <wd@denx.de> wrote:
> Dear "J. William Campbell",
>
> In message <4DDC6F46.4090809@comcast.net> you wrote:
>>
>> ? ? ? ? Well, it is not quite that simple. The "accuracy" of the 1 ms
>> interrupt rate is controlled in all cases I know about by the resolution
>> of the programmable divider used to produce it. It appears that the x86
>
> I mentioned a couple of times before that accuracy has never been a
> design criterion. ?Please also keep in mind that there are areas in
> the code where we block interrupts, and we make zero efforts to detect
> or compensate for this in the timer code. ?This simply is not
> important. ?We are not talking about ppm here, we are talking about
> somting that is just good enough for what it is being used, and that
> allows easily for +/- 10% tolerances.

With the prescaler design we are discussing, as long as we have access to
a free-running tick counter, it does not matter one iota if the interrupt
is delayed by one tick, a hundred ticks or a thousand ticks privided it
eventually happens within the roll-over interval of the tick counter

And if get_timer() is called in the meantime, the roll-over interval gets
reset

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  6:02                       ` Graeme Russ
@ 2011-05-25  8:06                         ` Wolfgang Denk
  2011-05-25  8:26                           ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25  8:06 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <BANLkTi==emvE+2Xu-R=hzh3TgFJXs9DnmA@mail.gmail.com> you wrote:
> 
> 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.

Please assume "no" to both questions.

Even more important: stop worrying about this.  The implementation is
noit supposed to make ANY such assumptions.

> 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)

You really should not care about those low-level details.  They can
and shall be ignored.

> > 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

But then you may significantly reduce the available time-span; you may
see the counter wrapping around every few seconds. You will not be
able to implement - say - a 10 second delay because you cannot know if
there were 1, 2, or more rollovers inbetween.


I see two options:

1) either we can have some signal when the timer wrapes around (like
   an interrupt); in this case it does not matter how big the counter
   itself is, we just increment our own local 64 bit timestamp.

2) Alternatively, I could imagine we use a 64 bit container plus a
   mask which specifiec how many bits are actually used - then we can 
   accommodate counters with any numbers of valid bits.



Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PUBLIC NOTICE AS REQUIRED BY LAW:  Any Use of This  Product,  in  Any
Manner  Whatsoever,  Will  Increase  the  Amount  of  Disorder in the
Universe. Although No Liability Is Implied Herein,  the  Consumer  Is
Warned  That  This  Process Will Ultimately Lead to the Heat Death of
the Universe.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  6:06                         ` Graeme Russ
@ 2011-05-25  8:08                           ` Wolfgang Denk
  2011-05-25  8:38                             ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25  8:08 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <BANLkTinZ_q8_vqd9mzm7BY64Hi=zuyFZTQ@mail.gmail.com> you wrote:
> 
> With the prescaler design we are discussing, as long as we have access to
> a free-running tick counter, it does not matter one iota if the interrupt
> is delayed by one tick, a hundred ticks or a thousand ticks privided it
> eventually happens within the roll-over interval of the tick counter

I don't get you.  In such a system, the interrupt would be the tick
(see the PPC implementation).  If you miss interrupts, you miss ticks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Real computer scientists don't comment their  code.  The  identifiers
are so long they can't afford the disk space.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  8:06                         ` Wolfgang Denk
@ 2011-05-25  8:26                           ` Graeme Russ
  2011-05-25 11:32                             ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25  8:26 UTC (permalink / raw)
  To: u-boot

On 25/05/11 18:06, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <BANLkTi==emvE+2Xu-R=hzh3TgFJXs9DnmA@mail.gmail.com> you wrote:
>>
>> 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.
> 
> Please assume "no" to both questions.

Thought so

> 
> Even more important: stop worrying about this.  The implementation is
> noit supposed to make ANY such assumptions.

I'm not really worrying about from the perspective of the new timer API,
it's idle curiosity and getting a better understanding

>> 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)
> 
> You really should not care about those low-level details.  They can
> and shall be ignored.

Yes, but you find that there is another level of simplification available...

>>> 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
> 
> But then you may significantly reduce the available time-span; you may
> see the counter wrapping around every few seconds. You will not be
> able to implement - say - a 10 second delay because you cannot know if
> there were 1, 2, or more rollovers inbetween.
> 
> 
> I see two options:
> 
> 1) either we can have some signal when the timer wrapes around (like
>    an interrupt); in this case it does not matter how big the counter
>    itself is, we just increment our own local 64 bit timestamp.
> 
> 2) Alternatively, I could imagine we use a 64 bit container plus a
>    mask which specifiec how many bits are actually used - then we can 
>    accommodate counters with any numbers of valid bits.
> 

3) Keep calling get_timer() (which you do when checking protocol time-outs)
- This keeps kicking the prescaler

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  8:08                           ` Wolfgang Denk
@ 2011-05-25  8:38                             ` Graeme Russ
  2011-05-25 11:37                               ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25  8:38 UTC (permalink / raw)
  To: u-boot

On 25/05/11 18:08, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <BANLkTinZ_q8_vqd9mzm7BY64Hi=zuyFZTQ@mail.gmail.com> you wrote:
>>
>> With the prescaler design we are discussing, as long as we have access to
>> a free-running tick counter, it does not matter one iota if the interrupt
>> is delayed by one tick, a hundred ticks or a thousand ticks privided it
>> eventually happens within the roll-over interval of the tick counter
> 
> I don't get you.  In such a system, the interrupt would be the tick
> (see the PPC implementation).  If you miss interrupts, you miss ticks.

Yes, you miss ticks, but if the hardware is keeping the tick counter
current in the background (i.e. without software or interrupts) then this
does not matter - The prescaler takes care of this...

The key is the prescaler takes a 'tick delta' between the last time it was
called and now, uses the 'tick frequency' to calculate a corresponding
'timer delta' which it adds to the current timer

So the frequency of calling the prescaler _does not matter_ (it does not
even need to be a regular frequency) provided the tick-counter does not do
a complete wrap (at 4GHz this is 4 seconds for a 32-bit counter) - So as
long as you call the prescaler at least every 4 seconds (and get_timer()
calls the prescaler) then you will never have a timer glitch in your timing
loop.

This relies on the tick counter wrapping properly.

So, if your tick counter is accurate, your timer is accurate even if you
are using an ISR to call the prescaler and temporarily disable interrupts

How many platforms have no hardware counter whatsoever? - These will have
to implement the timer using interrupts and suffer the accuracy loss when
interrupts are disabled (and how would these implement udelay() anyway -
hard loops I guess)

And now for the kicker - If your tick counter is microsecond resolution or
better, you can maintain microsecond, millisecond (second, minute etc)
timers trivially with a new prescaler

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  8:26                           ` Graeme Russ
@ 2011-05-25 11:32                             ` Wolfgang Denk
  2011-05-25 11:53                               ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 11:32 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDCBD3D.4080409@gmail.com> you wrote:
>
> > I see two options:
> > 
> > 1) either we can have some signal when the timer wrapes around (like
> >    an interrupt); in this case it does not matter how big the counter
> >    itself is, we just increment our own local 64 bit timestamp.
> > 
> > 2) Alternatively, I could imagine we use a 64 bit container plus a
> >    mask which specifiec how many bits are actually used - then we can 
> >    accommodate counters with any numbers of valid bits.
> > 
> 
> 3) Keep calling get_timer() (which you do when checking protocol time-outs)
> - This keeps kicking the prescaler

We cannot guarantee for this, so this is not really an option.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A door is what a dog is perpetually on the wrong side of.
                                                        - Ogden Nash

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  8:38                             ` Graeme Russ
@ 2011-05-25 11:37                               ` Wolfgang Denk
  2011-05-25 11:52                                 ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 11:37 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDCBFF4.40002@gmail.com> you wrote:
>
> > I don't get you.  In such a system, the interrupt would be the tick
> > (see the PPC implementation).  If you miss interrupts, you miss ticks.
> 
> Yes, you miss ticks, but if the hardware is keeping the tick counter
> current in the background (i.e. without software or interrupts) then this
> does not matter - The prescaler takes care of this...

I think you don't want to understand.

Look at the PPC implementation.  The decrementer causes an interrupt
every millisecond.  This is our tick.  We never ever actually read the
decrementer register itself.  We just use the interrupt.

> The key is the prescaler takes a 'tick delta' between the last time it was
> called and now, uses the 'tick frequency' to calculate a corresponding
> 'timer delta' which it adds to the current timer

The "tick frequency" in above example is 1,000 Hz, and determined by
the frequency of the interrupts.  There is not any "timer count
register" we are accessing here.

> This relies on the tick counter wrapping properly.

The "tick counter" is already in the higher level, i. e. implemented
in software, without any hardware based registers.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Diplomacy is the art of saying "nice doggy" until you can find a rock.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 11:37                               ` Wolfgang Denk
@ 2011-05-25 11:52                                 ` Graeme Russ
  2011-05-25 12:26                                   ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 11:52 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

On 25/05/11 21:37, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <4DDCBFF4.40002@gmail.com> you wrote:
>>
>>> I don't get you.  In such a system, the interrupt would be the tick
>>> (see the PPC implementation).  If you miss interrupts, you miss ticks.
>>
>> Yes, you miss ticks, but if the hardware is keeping the tick counter
>> current in the background (i.e. without software or interrupts) then this
>> does not matter - The prescaler takes care of this...
> 
> I think you don't want to understand.
> 
> Look at the PPC implementation.  The decrementer causes an interrupt
> every millisecond.  This is our tick.  We never ever actually read the
> decrementer register itself.  We just use the interrupt.

x86 is the same - a 1ms interrupt which increments the timer

>> The key is the prescaler takes a 'tick delta' between the last time it was
>> called and now, uses the 'tick frequency' to calculate a corresponding
>> 'timer delta' which it adds to the current timer
> 
> The "tick frequency" in above example is 1,000 Hz, and determined by
> the frequency of the interrupts.  There is not any "timer count
> register" we are accessing here.
> 
>> This relies on the tick counter wrapping properly.
> 
> The "tick counter" is already in the higher level, i. e. implemented
> in software, without any hardware based registers.

And in the PPC case - No prescaler and life is easy

BUT - I just found something very disturbing in /board/zylonite/flash.c -
Interrupts are disables before the timer is used to detect a timeout!

Yes, this is in a board specific flash driver which is bad but who knows
where else this might (quite unintentionally) occur

No if you have:

	start = get_timer(0)

	while (hardware_busy) {
		if (get_timer(start) > TIMEOUT) {
			/* deal with timeout */
			break;
		}
		/* Do stuf (poll hardware etc) */
	}

Now every time get_timer() is called, the prescaler updates the timer from
the current tick count - This cannot fail if interrupts are inadvertently
disabled.

And if you do not care about the timer updating while you are not 'using
it' (i.e. checking for a timeout) - it doesn't really matter - You will get
a glitch, but this glitch is 'reset' by the call to get_timer() and your
timeout check starts a new timer increment afresh

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 11:32                             ` Wolfgang Denk
@ 2011-05-25 11:53                               ` Graeme Russ
  2011-05-25 12:27                                 ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 11:53 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

On 25/05/11 21:32, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <4DDCBD3D.4080409@gmail.com> you wrote:
>>
>>> I see two options:
>>>
>>> 1) either we can have some signal when the timer wrapes around (like
>>>    an interrupt); in this case it does not matter how big the counter
>>>    itself is, we just increment our own local 64 bit timestamp.
>>>
>>> 2) Alternatively, I could imagine we use a 64 bit container plus a
>>>    mask which specifiec how many bits are actually used - then we can 
>>>    accommodate counters with any numbers of valid bits.
>>>
>>
>> 3) Keep calling get_timer() (which you do when checking protocol time-outs)
>> - This keeps kicking the prescaler
> 
> We cannot guarantee for this, so this is not really an option.
> 

You can when you are waiting for a timeout

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 11:52                                 ` Graeme Russ
@ 2011-05-25 12:26                                   ` Wolfgang Denk
  2011-05-25 12:42                                     ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 12:26 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDCED75.8030906@gmail.com> you wrote:
> 
> >>> I don't get you.  In such a system, the interrupt would be the tick
> >>> (see the PPC implementation).  If you miss interrupts, you miss ticks.
...
> > The "tick counter" is already in the higher level, i. e. implemented
> > in software, without any hardware based registers.
...

> Now every time get_timer() is called, the prescaler updates the timer from
> the current tick count - This cannot fail if interrupts are inadvertently
> disabled.

Arghh... But in this szenario, if interrupts are disabled, then the
ISR will not run, so the tick count will not be incremented BECAUSE
THE TICK COUNTER IS A VARIABLE THAT GETS INCREMENTED BY ONE EACH TIME
THE ISR RUNS.  So your prescaler will read a constant value.

Sorry for shouting, but I feel either you are not listening to me or I
cannot make myself understood to you.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Violence in reality is quite different from theory.
	-- Spock, "The Cloud Minders", stardate 5818.4

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 11:53                               ` Graeme Russ
@ 2011-05-25 12:27                                 ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 12:27 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDCEDA1.2010101@gmail.com> you wrote:
> 
> >> 3) Keep calling get_timer() (which you do when checking protocol time-outs)
> >> - This keeps kicking the prescaler
> > 
> > We cannot guarantee for this, so this is not really an option.
> 
> You can when you are waiting for a timeout

We may not be waiting for any timeouts for arbitrary long times.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Men will always be men -- no matter where they are.
	-- Harry Mudd, "Mudd's Women", stardate 1329.8

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-24 16:51               ` Graeme Russ
  2011-05-24 18:59                 ` J. William Campbell
  2011-05-24 19:19                 ` Wolfgang Denk
@ 2011-05-25 12:36                 ` Scott McNutt
  2011-05-25 12:43                   ` Graeme Russ
  2 siblings, 1 reply; 101+ messages in thread
From: Scott McNutt @ 2011-05-25 12:36 UTC (permalink / raw)
  To: u-boot

Graeme Russ wrote:
> OK, let's wind back - My original suggestion made no claim towards changing
> what the API is used for, or how it looks to those who use it (for all
> practical intents and purposes). I suggested:
>  - Removing set_timer() and reset_timer()
>  - Implement get_timer() as a platform independent function

Why do you suggest removing set_timer() and reset_timer() ?

--Scott

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 12:26                                   ` Wolfgang Denk
@ 2011-05-25 12:42                                     ` Graeme Russ
  2011-05-25 12:59                                       ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 12:42 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

On 25/05/11 22:26, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <4DDCED75.8030906@gmail.com> you wrote:
>>
>>>>> I don't get you.  In such a system, the interrupt would be the tick
>>>>> (see the PPC implementation).  If you miss interrupts, you miss ticks.
> ...
>>> The "tick counter" is already in the higher level, i. e. implemented
>>> in software, without any hardware based registers.
> ...
> 
>> Now every time get_timer() is called, the prescaler updates the timer from
>> the current tick count - This cannot fail if interrupts are inadvertently
>> disabled.
> 
> Arghh... But in this szenario, if interrupts are disabled, then the
> ISR will not run, so the tick count will not be incremented BECAUSE
> THE TICK COUNTER IS A VARIABLE THAT GETS INCREMENTED BY ONE EACH TIME
> THE ISR RUNS.  So your prescaler will read a constant value.
> 
> Sorry for shouting, but I feel either you are not listening to me or I
> cannot make myself understood to you.

What you are saying is 100% correct - For PPC. Now please - step back from
PPC for a minute

Many platforms have a hardware counter which is incremented without
assistance from software - not by an ISR, nothing (I mentioned this before,
but I can't track down the exact email) - THIS is the tick counter returned
by get_ticks() which the prescaler uses to update the timer when you either:

 - Explicitly call get_timer()
 - Call the prescaler from an ISR

The thing is, I have now highlighted that relying on interrupts to keep
get_timer() working is a really bad idea - We have no way of stopping
anyone from calling disable_interrupts() before using the timer

The suggested architecture makes ISR servicing of the timer 'nice' for long
delays where the tick counter might wrap and 'always works' for timeout
loops which repeatedly call get_timer()

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 12:36                 ` Scott McNutt
@ 2011-05-25 12:43                   ` Graeme Russ
  2011-05-25 13:08                     ` Scott McNutt
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 12:43 UTC (permalink / raw)
  To: u-boot

Hi Scott,

On 25/05/11 22:36, Scott McNutt wrote:
> Graeme Russ wrote:
>> OK, let's wind back - My original suggestion made no claim towards changing
>> what the API is used for, or how it looks to those who use it (for all
>> practical intents and purposes). I suggested:
>>  - Removing set_timer() and reset_timer()
>>  - Implement get_timer() as a platform independent function
> 
> Why do you suggest removing set_timer() and reset_timer() ?
> 

Because if the timer API is done right, they are not needed

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 12:42                                     ` Graeme Russ
@ 2011-05-25 12:59                                       ` Wolfgang Denk
  2011-05-25 13:14                                         ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 12:59 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDCF926.1050904@gmail.com> you wrote:
> 
> Many platforms have a hardware counter which is incremented without
> assistance from software - not by an ISR, nothing (I mentioned this before,
> but I can't track down the exact email) - THIS is the tick counter returned
> by get_ticks() which the prescaler uses to update the timer when you either:
> 
>  - Explicitly call get_timer()
>  - Call the prescaler from an ISR
> 
> The thing is, I have now highlighted that relying on interrupts to keep
> get_timer() working is a really bad idea - We have no way of stopping
> anyone from calling disable_interrupts() before using the timer

There may be code which doe snot call get_timer() for _long_ times.
And somebody disables interrupts. What's then?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Your csh still thinks true is false. Write to your vendor  today  and
tell them that next year Configure ought to "rm /bin/csh" unless they
fix  their blasted shell. :-)
                 - Larry Wall in Configure from the perl distribution

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 12:43                   ` Graeme Russ
@ 2011-05-25 13:08                     ` Scott McNutt
  2011-05-25 13:16                       ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Scott McNutt @ 2011-05-25 13:08 UTC (permalink / raw)
  To: u-boot

Graeme Russ wrote:
> Hi Scott,
> 
> On 25/05/11 22:36, Scott McNutt wrote:
>> Graeme Russ wrote:
>>> OK, let's wind back - My original suggestion made no claim towards changing
>>> what the API is used for, or how it looks to those who use it (for all
>>> practical intents and purposes). I suggested:
>>>  - Removing set_timer() and reset_timer()
>>>  - Implement get_timer() as a platform independent function
>> Why do you suggest removing set_timer() and reset_timer() ?
>>
> 
> Because if the timer API is done right, they are not needed

To continue the wind back ...

In several implementations, reset_timer() actually reloads
or re-initializes the hardware timer. This has the effect of
synchronizing get_timer() calls with subsequent interrupts.
This prevents the early timeouts if the implementer chooses
to use an interrupt rate less than 1 ms.

So my original question was, how do we address this issue?

--Scott

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 12:59                                       ` Wolfgang Denk
@ 2011-05-25 13:14                                         ` Graeme Russ
  2011-05-25 13:38                                           ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 13:14 UTC (permalink / raw)
  To: u-boot

On Wednesday, May 25, 2011, Wolfgang Denk <wd@denx.de> wrote:
> Dear Graeme Russ,
>
> In message <4DDCF926.1050904@gmail.com> you wrote:
>>
>> Many platforms have a hardware counter which is incremented without
>> assistance from software - not by an ISR, nothing (I mentioned this before,
>> but I can't track down the exact email) - THIS is the tick counter returned
>> by get_ticks() which the prescaler uses to update the timer when you either:
>>
>> ?- Explicitly call get_timer()
>> ?- Call the prescaler from an ISR
>>
>> The thing is, I have now highlighted that relying on interrupts to keep
>> get_timer() working is a really bad idea - We have no way of stopping
>> anyone from calling disable_interrupts() before using the timer
>
> There may be code which doe snot call get_timer() for _long_ times.
> And somebody disables interrupts. What's then?
>
We're hosed, but at least we are one better than relying on interrupts alone ;)

And what about platforms that do not support interrupts? Are you
mandating that get_timer() MUST always be supported by a timer updated
by an ISR?

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 13:08                     ` Scott McNutt
@ 2011-05-25 13:16                       ` Graeme Russ
  2011-05-25 13:46                         ` Scott McNutt
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 13:16 UTC (permalink / raw)
  To: u-boot

Hi Scott,

On Wednesday, May 25, 2011, Scott McNutt <smcnutt@psyent.com> wrote:
> Graeme Russ wrote:
>
> Hi Scott,
>
> On 25/05/11 22:36, Scott McNutt wrote:
>
> Graeme Russ wrote:
>
> OK, let's wind back - My original suggestion made no claim towards changing
> what the API is used for, or how it looks to those who use it (for all
> practical intents and purposes). I suggested:
> ?- Removing set_timer() and reset_timer()
> ?- Implement get_timer() as a platform independent function
>
> Why do you suggest removing set_timer() and reset_timer() ?
>
>
>
> Because if the timer API is done right, they are not needed
>
>
> To continue the wind back ...
>
> In several implementations, reset_timer() actually reloads
> or re-initializes the hardware timer. This has the effect of
> synchronizing get_timer() calls with subsequent interrupts.
> This prevents the early timeouts if the implementer chooses
> to use an interrupt rate less than 1 ms.
>
> So my original question was, how do we address this issue?

We fix them dear Liza dear Liza ;)

That is what this thread is trying to figure out

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 13:14                                         ` Graeme Russ
@ 2011-05-25 13:38                                           ` Wolfgang Denk
  2011-05-25 21:11                                             ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 13:38 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <BANLkTimhtqYNWgvwr6w8kNOSV4U_tZs7yw@mail.gmail.com> you wrote:
>
> And what about platforms that do not support interrupts? Are you
> mandating that get_timer() MUST always be supported by a timer updated
> by an ISR?

No, not at all. And I already answered this. For example on PPC, just
reading the timebase would be perfectly sufficient, and simpler and
more reliable than the current interrupt based approach.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Ein weiser Herrscher kann in einem gro?en Land  mehr  Gutes  bewirken
als  in  einem kleinen - ein dummer Herrscher aber auch viel mehr Un-
fug. Da weise Herrscher seltener sind als dumme, war ich schon  immer
gegen gro?e Reiche skeptisch.                   - Herbert Rosendorfer

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 13:16                       ` Graeme Russ
@ 2011-05-25 13:46                         ` Scott McNutt
  2011-05-25 14:21                           ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Scott McNutt @ 2011-05-25 13:46 UTC (permalink / raw)
  To: u-boot

Graeme Russ wrote:
> Hi Scott,
> 
> On Wednesday, May 25, 2011, Scott McNutt <smcnutt@psyent.com> wrote:
>> Graeme Russ wrote:
>>
>> Hi Scott,
>>
>> On 25/05/11 22:36, Scott McNutt wrote:
>>
>> Graeme Russ wrote:
>>
>> OK, let's wind back - My original suggestion made no claim towards changing
>> what the API is used for, or how it looks to those who use it (for all
>> practical intents and purposes). I suggested:
>>  - Removing set_timer() and reset_timer()
>>  - Implement get_timer() as a platform independent function
>>
>> Why do you suggest removing set_timer() and reset_timer() ?
>>
>>
>>
>> Because if the timer API is done right, they are not needed
>>
>>
>> To continue the wind back ...
>>
>> In several implementations, reset_timer() actually reloads
>> or re-initializes the hardware timer. This has the effect of
>> synchronizing get_timer() calls with subsequent interrupts.
>> This prevents the early timeouts if the implementer chooses
>> to use an interrupt rate less than 1 ms.
>>
>> So my original question was, how do we address this issue?
> 
> We fix them dear Liza dear Liza ;)
> 
> That is what this thread is trying to figure out

I'm getting a bit frustrated here as I can see we're going
in circles. So I'll just make a few statements a leave well
enough alone.

- I'm not convinced that reset_timer() and set_timer() should be
removed simply because you state that "if the timer API is done
right, they are not needed."

- If an implementation can't use interrupts that occur less
frequently than 1 msec to satisfy the prevailing use of
get_timer(), without breaking existing capability, I consider
the interface that "is done right" to be wrong.

Best Regards,
--Scott

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 13:46                         ` Scott McNutt
@ 2011-05-25 14:21                           ` Graeme Russ
  2011-05-25 19:46                             ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 14:21 UTC (permalink / raw)
  To: u-boot

Hi Scott,

On Wednesday, May 25, 2011, Scott McNutt <smcnutt@psyent.com> wrote:
> Graeme Russ wrote:
>
> Hi Scott,
>
> On Wednesday, May 25, 2011, Scott McNutt <smcnutt@psyent.com> wrote:
>
> Graeme Russ wrote:
>
> Hi Scott,
>
> On 25/05/11 22:36, Scott McNutt wrote:
>
> Graeme Russ wrote:
>
> OK, let's wind back - My original suggestion made no claim towards changing
> what the API is used for, or how it looks to those who use it (for all
> practical intents and purposes). I suggested:
> ?- Removing set_timer() and reset_timer()
> ?- Implement get_timer() as a platform independent function
>
> Why do you suggest removing set_timer() and reset_timer() ?
>
>
>
> Because if the timer API is done right, they are not needed
>
>
> To continue the wind back ...
>
> In several implementations, reset_timer() actually reloads
> or re-initializes the hardware timer. This has the effect of
> synchronizing get_timer() calls with subsequent interrupts.
> This prevents the early timeouts if the implementer chooses
> to use an interrupt rate less than 1 ms.
>
> So my original question was, how do we address this issue?
>
>
> We fix them dear Liza dear Liza ;)
>
> That is what this thread is trying to figure out
>
>
> I'm getting a bit frustrated here as I can see we're going
> in circles. So I'll just make a few statements a leave well
> enough alone.
>
> - I'm not convinced that reset_timer() and set_timer() should be
> removed simply because you state that "if the timer API is done
> right, they are not needed."

Sorry, I should have been more specific - get and reset break nested
loops. Some implementations (mostly ARM) also do a silent reset in
udelay(), which breaks loops containing udelay.

>
> - If an implementation can't use interrupts that occur less
> frequently than 1 msec to satisfy the prevailing use of
> get_timer(), without breaking existing capability, I consider
> the interface that "is done right" to be wrong.
>
Sorry, I don't understand what you mean here

I hope to get an implementation agreed upon that does not require
interrupts at all, provided a tick counter with sufficiently long roll
over time is available (longer than the maximum expected period
between 'related' get_timer() calls, for example calls to get_timer()
in a timeout testing while loop). This 'bare minimum' implementation
can be optionally augmented with an ISR which kicks the timer
calculation in the background (typically by just calling get_timer())

It really is quite simple in the end.

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25  5:17                     ` Wolfgang Denk
@ 2011-05-25 16:50                       ` J. William Campbell
  2011-05-25 19:56                         ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-25 16:50 UTC (permalink / raw)
  To: u-boot

On 5/24/2011 10:17 PM, Wolfgang Denk wrote:
> Dear "J. William Campbell",
>
> In message<4DDC31EB.6040609@comcast.net>  you wrote:
> ...
>> A tick is defined as the smallest increment of system time as measured by a
>> computer system (seehttp://en.wikipedia.org/wiki/System_time):
>>
>> 	System time is measured by a system clock, which is typically
>> 	implemented as a simple count of the number of ticks that have
>> 	transpired since some arbitrary starting date, called the
>> 	epoch.
>>
>> Unfortunately, this definition is obsolete, and has been for quite some
> Do you have any proof for such a claim?
Hi Wolfgang,
      Well, yes, in fact the same reference you used. Note that the 
statement "A tick is defined as the smallest increment of system time as 
measured by a computer system" is NOT found in 
http://en.wikipedia.org/wiki/System_time. That page is defining system 
time, and what we are discussing is the definition of a "tick". In fact, 
on the same wiki page you cite, there IS the statement "Windows NT 
<http://en.wikipedia.org/wiki/Windows_NT> counts the number of 
100-nanosecond ticks since 1 January 1601 00:00:00 UT as reckoned in the 
proleptic Gregorian calendar 
<http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar>, but returns 
the current time to the nearest millisecond". Here 100 nanosecond ticks 
clearly does not refer to any "hardware" 100 ns clock that exists on the 
pc. The 100 ns is a computed (dare I say virtual) "tick" value. The 
point here is that the definition of tick is yours, not wikipedia.org's. 
(Although we all are aware if it is wikipedia, it MUST be so).  Further, 
http://en.wikipedia.org/wiki/Jiffy_%28time%29#Use_in_computing contains 
the statement "In computing <http://en.wikipedia.org/wiki/Computing>, a 
jiffy is the duration of one tick of the system timer 
<http://en.wikipedia.org/wiki/System_time> interrupt 
<http://en.wikipedia.org/wiki/Interrupt>.". If a tick is the smallest 
increment of system time as measured by the computer system, the "of the 
system timer interrupt" part of the statement would be unnecessary. The 
fact it IS present indicates there are other kinds of ticks present in 
the universe.
     AFAIK, all timers "tick", and the definition of the tick rate is 
1/timer resolution. The concept of "timer ticks" and "clock ticks" has 
been around forever, and exists independent of System Time. For example, 
there may be a watchdog timer on a system that does not measure time at 
all, yet the watchdog still ticks. When you read a value from a timer 
that was not the "system timer", what do you call the value you read? I 
would call it ticks, and I bet just about everybody else would too.
     The only reason I feel this point matters at all is that when one 
refers to a routine called "get_ticks", it is not obvious to me which 
timer ticks are being referenced. You are saying that, by definition, it 
refers to the "system clock".  My feeling is that it is not obvious why 
that is so on a system that has many clocks. The name of the function or 
an argument to the function should, IMNSHO,  specify which timer ticks 
are being returned.

Best Regards,
Bill Campbell
>> years.  When computers had a single timer, the above definition worked,
>> but it no longer does, as many (most?) computers have several hardware
>> timers. A "tick" today is the time increment of any particular timer of
>> a computer system. So, when one writes a function called get_ticks on a
>> PPC, does one mean read the decrementer, or does one read the RTC or
>> does one read the TB register(s) A similar situation exists on the
>> Blackfin BF531/2/3, that has a preformance counter, a real-time clock,
>> and three programmable timers. Which tick do you want? For each u-boot
> Please re-read the definition.  At least as far as U-Boot and Linux
> are concerned, there is only a single clock source used to implement
> the _system_time_.  And I doubt that other OS do different.
>
>> implementation, we can pick one timer as the "master" timer, but it may
>> not be the one with the most rapid tick rate. It may be the one with the
>> most USEFUL tick rate for get_timer. If you take the above definition at
>> face value, only the fastest counter value has ticks, and all other
>> counters time increments are not ticks. If they are not ticks, what are
>> they?
> Clocks, timers?
>
>
> Best regards,
>
> Wolfgang Denk
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 14:21                           ` Graeme Russ
@ 2011-05-25 19:46                             ` Wolfgang Denk
  2011-05-25 20:40                               ` J. William Campbell
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 19:46 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <BANLkTikM3LPynzckNP64KjEQ5v+tE7yUhQ@mail.gmail.com> you wrote:
> 
> I hope to get an implementation agreed upon that does not require
> interrupts at all, provided a tick counter with sufficiently long roll
> over time is available (longer than the maximum expected period
> between 'related' get_timer() calls, for example calls to get_timer()
> in a timeout testing while loop). This 'bare minimum' implementation
> can be optionally augmented with an ISR which kicks the timer
> calculation in the background (typically by just calling get_timer())
> 
> It really is quite simple in the end.

The length of this thread shows that it is not as simple as you want
to make us believe.



If all you have in mind are timeouts, then we don't need get_timer()
at all.  We can implement all types of timeout where we wait for some
eent to happen using udelay() alone.

Need a 10 second timeout? Here we go:

	int cnt = 0;
	int limit = 10 * 1000;
	while (!condition) {
		usleep(1000); /* wait 1 millisec */
		if (++cnt > limit)
			break;
	}
	if (cnt > limit)
		error("timeout");

get_timer() comes into play only if we want to calculate a time
difference, for example if we want to run some code where we don't
know how long it runs, and later come back and check if a certain
amount of time has passed.

When we don't know how long this code runs, we also cannot know (and
espeically not in advance) wether or not this time will be longer or
not than the rollover time of the tick counter.


Your plan to require that get_timer() gets called "often enough" to
prevent or detect tick counter overflows is putting things on their
head.  It should be the opposite:  The implementation of get_timer()
should be such that it becomes independent from such low level
details.


I have stated this before:  I consider any design that requires
get_timer() to be called "often enough" broken.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Well, the way I see it, logic is only a way of being ignorant by num-
bers.                                 - Terry Pratchett, _Small Gods_

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 16:50                       ` J. William Campbell
@ 2011-05-25 19:56                         ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 19:56 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDD3354.8030801@comcast.net> you wrote:
>
> >> A tick is defined as the smallest increment of system time as measured by a
> >> computer system (seehttp://en.wikipedia.org/wiki/System_time):
> >>
> >> 	System time is measured by a system clock, which is typically
> >> 	implemented as a simple count of the number of ticks that have
> >> 	transpired since some arbitrary starting date, called the
> >> 	epoch.
> >>
> >> Unfortunately, this definition is obsolete, and has been for quite some
> > Do you have any proof for such a claim?
> Hi Wolfgang,
>       Well, yes, in fact the same reference you used. Note that the 
> statement "A tick is defined as the smallest increment of system time as 
> measured by a computer system" is NOT found in 
> http://en.wikipedia.org/wiki/System_time. That page is defining system 

I derived this from
http://en.wikipedia.org/wiki/Tick_%28disambiguation%29: "Tick, the
smallest increment of system time as measured by a computer system"

> the current time to the nearest millisecond". Here 100 nanosecond ticks 
> clearly does not refer to any "hardware" 100 ns clock that exists on the 

Above definition nowhere requres that the tick must be a "hardware"
clock.

> pc. The 100 ns is a computed (dare I say virtual) "tick" value. The 
> point here is that the definition of tick is yours, not wikipedia.org's. 

Not quite.

But while I do now want to claim authorship for words I just copied &
pasted, I think the definition is still a good one.  Let's say it's
the definition I want to see used to this discussion here :-)

> <http://en.wikipedia.org/wiki/Interrupt>.". If a tick is the smallest 
> increment of system time as measured by the computer system, the "of the 
> system timer interrupt" part of the statement would be unnecessary. The 
> fact it IS present indicates there are other kinds of ticks present in 
> the universe.

I disagree here.

>      AFAIK, all timers "tick", and the definition of the tick rate is 
> 1/timer resolution. The concept of "timer ticks" and "clock ticks" has 
> been around forever, and exists independent of System Time. For example, 
> there may be a watchdog timer on a system that does not measure time at 
> all, yet the watchdog still ticks. When you read a value from a timer 
> that was not the "system timer", what do you call the value you read? I 
> would call it ticks, and I bet just about everybody else would too.

I have no reason to argument about this.

But we don't care about any timers that may be present or even in use
for one pourpose or anothe rin the system.

All we care about her ein this discussion is a single time, and a
single timer, and a single tick: the one that represents the system
time.

>      The only reason I feel this point matters at all is that when one 
> refers to a routine called "get_ticks", it is not obvious to me which 
> timer ticks are being referenced. You are saying that, by definition, it 
> refers to the "system clock".  My feeling is that it is not obvious why 
> that is so on a system that has many clocks. The name of the function or 
> an argument to the function should, IMNSHO,  specify which timer ticks 
> are being returned.

THe reason is simply that it is the only clock that is being used
anywhere in U-Boot.  We have a only one system time, or clock.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I mean, I . . . think to understand you, I just don't know  what  you
are saying ...                        - Terry Pratchett, _Soul Music_

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 19:46                             ` Wolfgang Denk
@ 2011-05-25 20:40                               ` J. William Campbell
  2011-05-25 20:48                                 ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-25 20:40 UTC (permalink / raw)
  To: u-boot

On 5/25/2011 12:46 PM, Wolfgang Denk wrote:
> Dear Graeme Russ,
>
> In message<BANLkTikM3LPynzckNP64KjEQ5v+tE7yUhQ@mail.gmail.com>  you wrote:
>> I hope to get an implementation agreed upon that does not require
>> interrupts at all, provided a tick counter with sufficiently long roll
>> over time is available (longer than the maximum expected period
>> between 'related' get_timer() calls, for example calls to get_timer()
>> in a timeout testing while loop). This 'bare minimum' implementation
>> can be optionally augmented with an ISR which kicks the timer
>> calculation in the background (typically by just calling get_timer())
>>
>> It really is quite simple in the end.
> The length of this thread shows that it is not as simple as you want
> to make us believe.
>
>
>
> If all you have in mind are timeouts, then we don't need get_timer()
> at all.  We can implement all types of timeout where we wait for some
> eent to happen using udelay() alone.
>
> Need a 10 second timeout? Here we go:
>
> 	int cnt = 0;
> 	int limit = 10 * 1000;
> 	while (!condition) {
> 		usleep(1000); /* wait 1 millisec */
> 		if (++cnt>  limit)
> 			break;
> 	}
> 	if (cnt>  limit)
> 		error("timeout");
>
> get_timer() comes into play only if we want to calculate a time
> difference, for example if we want to run some code where we don't
> know how long it runs, and later come back and check if a certain
> amount of time has passed.
>
> When we don't know how long this code runs, we also cannot know (and
> espeically not in advance) wether or not this time will be longer or
> not than the rollover time of the tick counter.
>
>
> Your plan to require that get_timer() gets called "often enough" to
> prevent or detect tick counter overflows is putting things on their
> head.  It should be the opposite:  The implementation of get_timer()
> should be such that it becomes independent from such low level
> details.
>
HI all,
       We also cannot know if this code disables interrupts. If it does, 
the existing PPC design is broken. If interrupts are disabled during the 
entire code being executed, the elapsed run time will be 0. You can say 
that disabling interrupts in the code is not allowed. Fine, then that 
becomes a constraint on the code. Calling get_timer explicitly often 
enough is also a constraint on the code. One constraint is acceptable to 
you, the other is not. Ok, that's fine too. If the interrupt routine 
calls get_timer, then get_timer is called "often enough" and everything 
works the same as it presently does on PPC, It is not different than 
requiring the interrupt routine to be executed "often enough". The two 
methods are functionally identical. The only problems arise on systems 
that don't support interrupts and don't have any timers with enough bits 
available to meet the 4294967 seconds maximum interval requirement. 
Those systems will be "broken" no matter what we do, as we have all agreed.

     Right now, almost all ARM cases are broken, because they have short 
timers and don't use interrupts. In some cases, there are actual bugs 
involved. We can make these cases less broken than they now are with a 
common get_timer approach as outlined previously. However, we cannot fix 
them to the standard Wolfgang is stating here, to be not "broken". So, 
back to what I was asking before, is the improvement worth the effort if 
the result is still broken?

Best Regards,
Bill Campbell
> I have stated this before:  I consider any design that requires
> get_timer() to be called "often enough" broken.
>
> Best regards,
>
> Wolfgang Denk
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 20:40                               ` J. William Campbell
@ 2011-05-25 20:48                                 ` Wolfgang Denk
  0 siblings, 0 replies; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 20:48 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDD6930.2080202@comcast.net> you wrote:
>
> methods are functionally identical. The only problems arise on systems 
> that don't support interrupts and don't have any timers with enough bits 
> available to meet the 4294967 seconds maximum interval requirement. 

Where exactly is this requirement coming from?

>      Right now, almost all ARM cases are broken, because they have short 
> timers and don't use interrupts. In some cases, there are actual bugs 
> involved. We can make these cases less broken than they now are with a 
> common get_timer approach as outlined previously. However, we cannot fix 

We could also make them use interrupts for this type of timer service?

How do these systems implement system time in other environments, say
in Linux?  Or in Barebox?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Human beings were created by water to transport it uphill.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 13:38                                           ` Wolfgang Denk
@ 2011-05-25 21:11                                             ` Graeme Russ
  2011-05-25 21:16                                               ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 21:11 UTC (permalink / raw)
  To: u-boot

On 25/05/11 23:38, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <BANLkTimhtqYNWgvwr6w8kNOSV4U_tZs7yw@mail.gmail.com> you wrote:
>>
>> And what about platforms that do not support interrupts? Are you
>> mandating that get_timer() MUST always be supported by a timer updated
>> by an ISR?
> 
> No, not at all. And I already answered this. For example on PPC, just
> reading the timebase would be perfectly sufficient, and simpler and
> more reliable than the current interrupt based approach.

I assume by 'timebase' you mean the 64-bit tick counter. If so, that is
_exactly_ what I am suggesting we do (and what does already happen on ARM).
The big change is, the prescaler is common code rather than haven dozens
(some of them broken) implementations

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 21:11                                             ` Graeme Russ
@ 2011-05-25 21:16                                               ` Wolfgang Denk
  2011-05-25 23:13                                                 ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-25 21:16 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <4DDD7066.4000505@gmail.com> you wrote:
>
> > No, not at all. And I already answered this. For example on PPC, just
> > reading the timebase would be perfectly sufficient, and simpler and
> > more reliable than the current interrupt based approach.
> 
> I assume by 'timebase' you mean the 64-bit tick counter. If so, that is

By timebase I mean the timebase register, implemented as two 32 bit
registers tbu and tbl, holding the upper and the lower 32 bits of the
free-running 64 bit counter, respective.

> _exactly_ what I am suggesting we do (and what does already happen on ARM).

I don't think so.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"...this does not mean that some of us should not want, in  a  rather
dispassionate sort of way, to put a bullet through csh's head."
                   - Larry Wall in <1992Aug6.221512.5963@netlabs.com>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 21:16                                               ` Wolfgang Denk
@ 2011-05-25 23:13                                                 ` Graeme Russ
  2011-05-26  0:15                                                   ` J. William Campbell
  2011-05-26  4:19                                                   ` Reinhard Meyer
  0 siblings, 2 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-25 23:13 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang

On Thu, May 26, 2011 at 7:16 AM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Graeme Russ,
>
> In message <4DDD7066.4000505@gmail.com> you wrote:
>>
>> > No, not at all. And I already answered this. For example on PPC, just
>> > reading the timebase would be perfectly sufficient, and simpler and
>> > more reliable than the current interrupt based approach.
>>
>> I assume by 'timebase' you mean the 64-bit tick counter. If so, that is
>
> By timebase I mean the timebase register, implemented as two 32 bit
> registers tbu and tbl, holding the upper and the lower 32 bits of the
> free-running 64 bit counter, respective.

And remember, not all platforms have this implementation. The AMD sc520
for example has a microsecond register which counts 0-999 that ticks a
16-bit millisecond register and resets to zero. And the millisecond
register latches the value of the microsecond register and resets
(the millisecond register) back to zero.

The thing is, this can all be abstracted away via get_tick() which
(provided it is called every 65 seconds or so) can maintain a software
version of the timebase register. So, every 65 seconds, the prescaler
needs to be kicked. Now, if all we want to use get_timer() for is to
monitor a timeout (which I think might be every single use in U-Boot
to date) then the while (get_timer(start) < timeout) loop will work. If
get_timer() is needed to measure time between two arbitrary events (which
I 100% agree it should be able to do) then the prescaler will need to be
kicked (typically by an interrupt)

>
>> _exactly_ what I am suggesting we do (and what does already happen on ARM).
>
> I don't think so.

On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2)
do. at91 is odd - It looks like it uses interrupts, but get_timer() and
udelay() both end up calling get_timer_raw() (with udelay only having
millisecond resolution it seems). Some others can be configured to
increment the timer using an interrupt. ARM is, quite frankly, a complete
mess - It has a mass of *_timer_masked() functions which the core timer
functions are 'wafer thin' wrapper around, udelay() silently resets
the timebase trashing get_timer() loops etc.

So let's wind back and distill the approach I am suggesting:

 1) A common prescaler function in /lib/ - It's purpose is to maintain
    a 1ms resolution timer (if the platform cannot otherwise do so)[1]
    The prescaler utilises a platform provided get_ticks()[2]
 2) A get_ticks() function provided by the platform - This function must
    return an unsigned counter which wraps from all 1's to all 0's - It
    DOES NOT have to be initialised to zero at system start. get_ticks()
    hides the low-level tick counter implementation - The sc520 example
    above is a classic example, so is your PPC tbu/tbl example.
 3) [Optional]An ISR which calls the prescaler[3]

Now there is an optimisation if your tick counter has a 1ms resolution
and is not small (i.e. 64-bits) - The prescaler is defined weak, so in
the platform code, re-implement the prescaler to simply copy the tick
counter to the timer variable.

And what are the specific implementation types (in decending order of
preference)? I think:
 1) A 64-bit micro-second tick counter[5]
      - No interrupts needed
      - Can be used by udelay() and get_timer() trivially
 2) A 64-bit sub-micro-second tick counter
      - Interrupts most likely undeeded unless the tick frequency is
        insanely high
      - Can be used by udelay() and get_timer() trivially
 3) A 64-bit milli-second tick counter
      - No interrupts needed
      - No prescaler needed
      - Can be used by get_timer() trivially
      - udelay() needs another tick source (if available) or be reduced
        to millisecond resolution
 4) A 32-bit milli-second tick counter
      - No prescaler needed[6]
      - Max 'glitch free' duration is ~50 days
      - ISR needed to kick prescaler if events longer than 50 days need
        to be timed
      - Can be used by get_timer() trivially
      - udelay() needs another tick source (if available) or be reduced
        to millisecond resolution
 5) A 24-bit milli-second tick counter
      - No prescaler needed[6]
      - Max 'glitch free' duration is ~4.5 hours
      - ISR needed to kick prescaler if events longer than 4.5 hours need
        to be timed
      - Can be used by get_timer() trivially
      - udelay() needs another tick source (if available) or be reduced
        to millisecond resolution
 6) A 32-bit micro-second tick counter
      - No prescaler needed[6]
      - Max 'glitch free' duration is 71 minutes
      - ISR needed to kick prescaler if events longer than 71 minutes need
        to be timed
      - Can be used by get_timer() trivially
      - udelay() needs another tick source (if available) or be reduced
        to millisecond resolution

Any implementation which does not fit withing the above is going to
require an ISR to kick the prescaler in order to support timing of 'long
events' (i.e. not just simple timeout loops)

[1]The prescaler would still be needed by platforms which has a 64-bit
tick counter which ticks at a rate greater than 1ms
[2]Exposing get_ticks() reduces code duplication
[3]Only required if the rollover time of the tick counter (i.e. the maximum
permissible time between any two get_ticks() calls) is 'small'[4]
[4]'small' is at the discretion of the implementer - 1 second is always
small, 1 hour might be, 500 years is not
[5]A tick counter is something maintained by the underlying platform
independent of any U-Boot code
[6]Although wise to override the prescaler function so the timer ISR is
consistent with all other platforms

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 23:13                                                 ` Graeme Russ
@ 2011-05-26  0:15                                                   ` J. William Campbell
  2011-05-26  0:33                                                     ` Graeme Russ
  2011-05-26  4:19                                                   ` Reinhard Meyer
  1 sibling, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-26  0:15 UTC (permalink / raw)
  To: u-boot

On 5/25/2011 4:13 PM, Graeme Russ wrote:
> Hi Wolfgang
>
> On Thu, May 26, 2011 at 7:16 AM, Wolfgang Denk<wd@denx.de>  wrote:
>> Dear Graeme Russ,
>>
>> In message<4DDD7066.4000505@gmail.com>  you wrote:
>>>> No, not at all. And I already answered this. For example on PPC, just
>>>> reading the timebase would be perfectly sufficient, and simpler and
>>>> more reliable than the current interrupt based approach.
>>> I assume by 'timebase' you mean the 64-bit tick counter. If so, that is
>> By timebase I mean the timebase register, implemented as two 32 bit
>> registers tbu and tbl, holding the upper and the lower 32 bits of the
>> free-running 64 bit counter, respective.
> And remember, not all platforms have this implementation. The AMD sc520
> for example has a microsecond register which counts 0-999 that ticks a
> 16-bit millisecond register and resets to zero. And the millisecond
> register latches the value of the microsecond register and resets
> (the millisecond register) back to zero.
>
> The thing is, this can all be abstracted away via get_tick() which
> (provided it is called every 65 seconds or so) can maintain a software
> version of the timebase register. So, every 65 seconds, the prescaler
> needs to be kicked. Now, if all we want to use get_timer() for is to
> monitor a timeout (which I think might be every single use in U-Boot
> to date) then the while (get_timer(start)<  timeout) loop will work. If
> get_timer() is needed to measure time between two arbitrary events (which
> I 100% agree it should be able to do) then the prescaler will need to be
> kicked (typically by an interrupt)
>
>>> _exactly_ what I am suggesting we do (and what does already happen on ARM).
>> I don't think so.
Hi All,
       Just to be clear, while ARMv7 has a 64 bit performance counter, 
it is not presently used by get_time. This is a change we want to make 
correct?
> On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2)
> do. at91 is odd - It looks like it uses interrupts, but get_timer() and
> udelay() both end up calling get_timer_raw() (with udelay only having
> millisecond resolution it seems).
I am not sure why you say at91 appears to use interrupts. There is a 
comment in arch/arm/cpu/arm930t/at91/timer.c that says "timer without 
interrupts" (line 73). There is the same comment in 
arch/arm/cpu/arm930t/at91rm9200/timer.c Nothing in either routine refers 
to interrupts, so I would say the timer doesn't use them. I could be 
wrong of course.
>   Some others can be configured to
> increment the timer using an interrupt. ARM is, quite frankly, a complete
> mess - It has a mass of *_timer_masked() functions which the core timer
> functions are 'wafer thin' wrapper around, udelay() silently resets
> the timebase trashing get_timer() loops etc.
I sure agree with this last part. The only arm timer I found that 
clearly thought it could use interrupts was in arch/arm/cpu/ixp, and 
that was conditional, not mandatory.
> So let's wind back and distill the approach I am suggesting:
>
>   1) A common prescaler function in /lib/ - It's purpose is to maintain
>      a 1ms resolution timer (if the platform cannot otherwise do so)[1]
>      The prescaler utilises a platform provided get_ticks()[2]
>   2) A get_ticks() function provided by the platform - This function must
>      return an unsigned counter which wraps from all 1's to all 0's - It
>      DOES NOT have to be initialised to zero at system start. get_ticks()
>      hides the low-level tick counter implementation - The sc520 example
>      above is a classic example, so is your PPC tbu/tbl example.
>   3) [Optional]An ISR which calls the prescaler[3]
>
> Now there is an optimisation if your tick counter has a 1ms resolution
> and is not small (i.e. 64-bits) - The prescaler is defined weak, so in
> the platform code, re-implement the prescaler to simply copy the tick
> counter to the timer variable.
>
> And what are the specific implementation types (in decending order of
> preference)? I think:
>   1) A 64-bit micro-second tick counter[5]
>        - No interrupts needed
>        - Can be used by udelay() and get_timer() trivially
>   2) A 64-bit sub-micro-second tick counter
>        - Interrupts most likely undeeded unless the tick frequency is
>          insanely high
>        - Can be used by udelay() and get_timer() trivially
>   3) A 64-bit milli-second tick counter
>        - No interrupts needed
>        - No prescaler needed
>        - Can be used by get_timer() trivially
>        - udelay() needs another tick source (if available) or be reduced
>          to millisecond resolution
>   4) A 32-bit milli-second tick counter
>        - No prescaler needed[6]
>        - Max 'glitch free' duration is ~50 days
>        - ISR needed to kick prescaler if events longer than 50 days need
>          to be timed
>        - Can be used by get_timer() trivially
>        - udelay() needs another tick source (if available) or be reduced
>          to millisecond resolution
>   5) A 24-bit milli-second tick counter
>        - No prescaler needed[6]
>        - Max 'glitch free' duration is ~4.5 hours
>        - ISR needed to kick prescaler if events longer than 4.5 hours need
>          to be timed
>        - Can be used by get_timer() trivially
>        - udelay() needs another tick source (if available) or be reduced
>          to millisecond resolution
>   6) A 32-bit micro-second tick counter
>        - No prescaler needed[6]
>        - Max 'glitch free' duration is 71 minutes
>        - ISR needed to kick prescaler if events longer than 71 minutes need
>          to be timed
>        - Can be used by get_timer() trivially
I think this should be "Can be used by udelay and get_timer trivially"
Best Regards,
Bill Campbell
>        - udelay() needs another tick source (if available) or be reduced
>          to millisecond resolution
>
> Any implementation which does not fit withing the above is going to
> require an ISR to kick the prescaler in order to support timing of 'long
> events' (i.e. not just simple timeout loops)
>
> [1]The prescaler would still be needed by platforms which has a 64-bit
> tick counter which ticks at a rate greater than 1ms
> [2]Exposing get_ticks() reduces code duplication
> [3]Only required if the rollover time of the tick counter (i.e. the maximum
> permissible time between any two get_ticks() calls) is 'small'[4]
> [4]'small' is at the discretion of the implementer - 1 second is always
> small, 1 hour might be, 500 years is not
> [5]A tick counter is something maintained by the underlying platform
> independent of any U-Boot code
> [6]Although wise to override the prescaler function so the timer ISR is
> consistent with all other platforms
>
> Regards,
>
> Graeme
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  0:15                                                   ` J. William Campbell
@ 2011-05-26  0:33                                                     ` Graeme Russ
  0 siblings, 0 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-26  0:33 UTC (permalink / raw)
  To: u-boot

On Thu, May 26, 2011 at 10:15 AM, J. William Campbell
<jwilliamcampbell@comcast.net> wrote:
> On 5/25/2011 4:13 PM, Graeme Russ wrote:
>>
>> Hi Wolfgang
>>
>> On Thu, May 26, 2011 at 7:16 AM, Wolfgang Denk<wd@denx.de> ?wrote:
>>>
>>> Dear Graeme Russ,
>>>
>>> In message<4DDD7066.4000505@gmail.com> ?you wrote:
>>>>>

[snip]

>>>> _exactly_ what I am suggesting we do (and what does already happen on
>>>> ARM).
>>>
>>> I don't think so.
>
> Hi All,
> ? ? ?Just to be clear, while ARMv7 has a 64 bit performance counter, it is
> not presently used by get_time. This is a change we want to make correct?

If it is a constant time-base then yes, that would be preferable - But I
doubt all ARM CPUs have these, so these need to be enabled on a case by
case basis - get_ticks() can then use them trivially

>>
>> On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2)
>> do. at91 is odd - It looks like it uses interrupts, but get_timer() and
>> udelay() both end up calling get_timer_raw() (with udelay only having
>> millisecond resolution it seems).
>
> I am not sure why you say at91 appears to use interrupts. There is a comment
> in arch/arm/cpu/arm930t/at91/timer.c that says "timer without interrupts"
> (line 73). There is the same comment in
> arch/arm/cpu/arm930t/at91rm9200/timer.c Nothing in either routine refers to
> interrupts, so I would say the timer doesn't use them. I could be wrong of
> course.

You are correct

[snip]

>> ?6) A 32-bit micro-second tick counter
>> ? ? ? - No prescaler needed[6]
>> ? ? ? - Max 'glitch free' duration is 71 minutes
>> ? ? ? - ISR needed to kick prescaler if events longer than 71 minutes need
>> ? ? ? ? to be timed
>> ? ? ? - Can be used by get_timer() trivially
>
> I think this should be "Can be used by udelay and get_timer trivially"

Yes, you are again correct

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-25 23:13                                                 ` Graeme Russ
  2011-05-26  0:15                                                   ` J. William Campbell
@ 2011-05-26  4:19                                                   ` Reinhard Meyer
  2011-05-26  4:40                                                     ` Graeme Russ
  2011-05-26  4:54                                                     ` J. William Campbell
  1 sibling, 2 replies; 101+ messages in thread
From: Reinhard Meyer @ 2011-05-26  4:19 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,
> On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2)
> do. at91 is odd - It looks like it uses interrupts, but get_timer() and
> udelay() both end up calling get_timer_raw() (with udelay only having
> millisecond resolution it seems). Some others can be configured to
> increment the timer using an interrupt. ARM is, quite frankly, a complete
> mess - It has a mass of *_timer_masked() functions which the core timer
> functions are 'wafer thin' wrapper around, udelay() silently resets
> the timebase trashing get_timer() loops etc.

Please look at current master for at91.

http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/cpu/arm926ejs/at91/timer.c;h=a0876879d3907af553d832bea187a062a22b9bd4;hb=5d1ee00b1fe1180503f6dfc10e87a6c6e74778f3

AT91 uses a 32 bit hardware register that by means of a prescaler is made
to increment at a rate in the low megahertz range.

This results in a wrap approximately every 1000 seconds.
Actually this would be sufficient for all known uses of udelay() and get_timer()
timeout loops. However, this hardware register is extended to 64 bits by software
every time it is read (by detecting rollovers).

Since a wrap of that 64 bit "tick" would occur after the earth has ended,
it is simple to obtain milliseconds from it by doing a 64 bit division.

Best Regards,
Reinhard

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  4:19                                                   ` Reinhard Meyer
@ 2011-05-26  4:40                                                     ` Graeme Russ
  2011-05-26  5:03                                                       ` J. William Campbell
  2011-05-26  4:54                                                     ` J. William Campbell
  1 sibling, 1 reply; 101+ messages in thread
From: Graeme Russ @ 2011-05-26  4:40 UTC (permalink / raw)
  To: u-boot

On Thu, May 26, 2011 at 2:19 PM, Reinhard Meyer
<u-boot@emk-elektronik.de> wrote:
>
> Dear Graeme Russ,
>>
>> On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2)
>> do. at91 is odd - It looks like it uses interrupts, but get_timer() and
>> udelay() both end up calling get_timer_raw() (with udelay only having
>> millisecond resolution it seems). Some others can be configured to
>> increment the timer using an interrupt. ARM is, quite frankly, a complete
>> mess - It has a mass of *_timer_masked() functions which the core timer
>> functions are 'wafer thin' wrapper around, udelay() silently resets
>> the timebase trashing get_timer() loops etc.
>
> Please look at current master for at91.
>
> http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/cpu/arm926ejs/at91/timer.c;h=a0876879d3907af553d832bea187a062a22b9bd4;hb=5d1ee00b1fe1180503f6dfc10e87a6c6e74778f3
>
> AT91 uses a 32 bit hardware register that by means of a prescaler is made
> to increment at a rate in the low megahertz range.

Yes, I see that now

> This results in a wrap approximately every 1000 seconds.
> Actually this would be sufficient for all known uses of udelay() and get_timer()
> timeout loops. However, this hardware register is extended to 64 bits by software
> every time it is read (by detecting rollovers).

Which makes it 100% compatible with my proposed solution - The software
prescaler will trigger the 64-bit extension and rollover detection

> Since a wrap of that 64 bit "tick" would occur after the earth has ended,
> it is simple to obtain milliseconds from it by doing a 64 bit division.

Which would be done in the common prescaler in /lib/

Currently, most ARM specific utilisations of get_timer() enforce a reset
of the tick counter by calling reset_timer() - Subsequent calls to
get_timer() then assume a start time of zero. Provided the internal timer
rolls over currectly, the initial call of get_timer(0) will reset the ms
timer and remove and 'glitch' present due to not calling the 'extender'
function between 32-bit rollovers which makes the reset_timer() call
unneccessary - I believe at91 behaves correctly in this regard.

In any case, the underlying assumption made by the ARM timer interface
(call reset_timer() first always) is inherently broken as not all users
of the timer API do this - They assume a sane behaviour of:

	start = get_timer(0);
	elapsed_time = get_timer(start);

Add to this udelay() resetting the timer make the following very broken:

	start = get_timer(0);
	while(condition) {
		udelay(delay);
	}
	elapsed_time = get_timer(start);

NOTE: In this case, if udelay() also calls the prescaler then no interrupt
triggered every 1000s would be required in the above example to get
correct elapsed_time even if the loop ran for several hours (provided
udelay() is called at least every 1000s

However, to allow timing of independent events with no intervening
udelay() or get_timer() calls, an 1000s interrupt to kick the prescaler is
all that is needed to make this particular implementation behave correctly.
Of course disabling interruts and not calling get_timer() or udelay() will
break the timer - But there is nothing that can be done about that)

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  4:19                                                   ` Reinhard Meyer
  2011-05-26  4:40                                                     ` Graeme Russ
@ 2011-05-26  4:54                                                     ` J. William Campbell
  1 sibling, 0 replies; 101+ messages in thread
From: J. William Campbell @ 2011-05-26  4:54 UTC (permalink / raw)
  To: u-boot

On 5/25/2011 9:19 PM, Reinhard Meyer wrote:
> Dear Graeme Russ,
>> On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2)
>> do. at91 is odd - It looks like it uses interrupts, but get_timer() and
>> udelay() both end up calling get_timer_raw() (with udelay only having
>> millisecond resolution it seems). Some others can be configured to
>> increment the timer using an interrupt. ARM is, quite frankly, a 
>> complete
>> mess - It has a mass of *_timer_masked() functions which the core timer
>> functions are 'wafer thin' wrapper around, udelay() silently resets
>> the timebase trashing get_timer() loops etc.
>
> Please look at current master for at91.
>
> http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/cpu/arm926ejs/at91/timer.c;h=a0876879d3907af553d832bea187a062a22b9bd4;hb=5d1ee00b1fe1180503f6dfc10e87a6c6e74778f3 
>
>
> AT91 uses a 32 bit hardware register that by means of a prescaler is made
> to increment at a rate in the low megahertz range.
>
> This results in a wrap approximately every 1000 seconds.
>
> Actually this would be sufficient for all known uses of udelay() and 
> get_timer()
Hi All
       Yes, you are correct. It would be sufficient for all known uses 
of udelay and get_timer(). However, Wolfgang has indicated a strong 
desire that the performance of the new API work properly over the full 
32 bit range of the millisecond delay time. That has been the basic 
issue for some time here.
> timeout loops. However, this hardware register is extended to 64 bits 
> by software
> every time it is read (by detecting rollovers).
Yes, but this extension ONLY happens if get_ticks is called via udelay 
or get_timer. It doesn't happen if you are sitting at the command prompt 
or off executing a downloaded stand alone program. You might ask "who 
cares", and I would answer that Wolfgang cares, at least to some level. 
If the timer overflow triggered an interrupt, we could call get_ticks to 
update the extended time inside the interrupt routine. But, as far as I 
know, it doesn't. There are some other ARM processors that have a 32 bit 
clock derived from a 32 kHz crystal, The will work much as you example 
does up to 134217 seconds, in fact much longer than your AT91 example 
does. However, that doesn't touch the 4294967 seconds that the PPC can 
manage. Without interrupts, the 32 bit (or smaller) counters will NEVER 
get to the PPC standard if their tick rate exceeds 1 msec. It may be 
that we need a lower standard, perhaps saying 1000 seconds is enough. 
But that is not my decision to make.
>
> Since a wrap of that 64 bit "tick" would occur after the earth has ended,
> it is simple to obtain milliseconds from it by doing a 64 bit division.
True, but moot because of the above.
Best Regards,
Bill Campbell
>
> Best Regards,
> Reinhard
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  4:40                                                     ` Graeme Russ
@ 2011-05-26  5:03                                                       ` J. William Campbell
  2011-05-26  5:16                                                         ` Wolfgang Denk
  0 siblings, 1 reply; 101+ messages in thread
From: J. William Campbell @ 2011-05-26  5:03 UTC (permalink / raw)
  To: u-boot

On 5/25/2011 9:40 PM, Graeme Russ wrote:
> On Thu, May 26, 2011 at 2:19 PM, Reinhard Meyer
> <u-boot@emk-elektronik.de>  wrote:
>> Dear Graeme Russ,
>>> On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2)
>>> do. at91 is odd - It looks like it uses interrupts, but get_timer() and
>>> udelay() both end up calling get_timer_raw() (with udelay only having
>>> millisecond resolution it seems). Some others can be configured to
>>> increment the timer using an interrupt. ARM is, quite frankly, a complete
>>> mess - It has a mass of *_timer_masked() functions which the core timer
>>> functions are 'wafer thin' wrapper around, udelay() silently resets
>>> the timebase trashing get_timer() loops etc.
>> Please look at current master for at91.
>>
>> http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/cpu/arm926ejs/at91/timer.c;h=a0876879d3907af553d832bea187a062a22b9bd4;hb=5d1ee00b1fe1180503f6dfc10e87a6c6e74778f3
>>
>> AT91 uses a 32 bit hardware register that by means of a prescaler is made
>> to increment at a rate in the low megahertz range.
> Yes, I see that now
>
>> This results in a wrap approximately every 1000 seconds.
>> Actually this would be sufficient for all known uses of udelay() and get_timer()
>> timeout loops. However, this hardware register is extended to 64 bits by software
>> every time it is read (by detecting rollovers).
> Which makes it 100% compatible with my proposed solution - The software
> prescaler will trigger the 64-bit extension and rollover detection
>
>> Since a wrap of that 64 bit "tick" would occur after the earth has ended,
>> it is simple to obtain milliseconds from it by doing a 64 bit division.
> Which would be done in the common prescaler in /lib/
>
> Currently, most ARM specific utilisations of get_timer() enforce a reset
> of the tick counter by calling reset_timer() - Subsequent calls to
> get_timer() then assume a start time of zero. Provided the internal timer
> rolls over currectly, the initial call of get_timer(0) will reset the ms
> timer and remove and 'glitch' present due to not calling the 'extender'
> function between 32-bit rollovers which makes the reset_timer() call
> unneccessary - I believe at91 behaves correctly in this regard.
>
> In any case, the underlying assumption made by the ARM timer interface
> (call reset_timer() first always) is inherently broken as not all users
> of the timer API do this - They assume a sane behaviour of:
>
> 	start = get_timer(0);
> 	elapsed_time = get_timer(start);
>
> Add to this udelay() resetting the timer make the following very broken:
>
> 	start = get_timer(0);
> 	while(condition) {
> 		udelay(delay);
> 	}
> 	elapsed_time = get_timer(start);
>
> NOTE: In this case, if udelay() also calls the prescaler then no interrupt
> triggered every 1000s would be required in the above example to get
> correct elapsed_time even if the loop ran for several hours (provided
> udelay() is called at least every 1000s
>
> However, to allow timing of independent events with no intervening
> udelay() or get_timer() calls, an 1000s interrupt to kick the prescaler is
> all that is needed to make this particular implementation behave correctly.
Hi All,
       True, if the processor supports timer interrupts. The problem is 
that the existing u-boots in many cases do not. I think that is really 
the crux of the problem. So what are we going to do? I am open to ideas 
here.

Best Regards,
Bill Campbell

> Of course disabling interruts and not calling get_timer() or udelay() will
> break the timer - But there is nothing that can be done about that)
>
> Regards,
>
> Graeme
>
>

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  5:03                                                       ` J. William Campbell
@ 2011-05-26  5:16                                                         ` Wolfgang Denk
  2011-05-26  5:25                                                           ` Graeme Russ
  0 siblings, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-26  5:16 UTC (permalink / raw)
  To: u-boot

Dear "J. William Campbell",

In message <4DDDDF2E.8070602@comcast.net> you wrote:
>
>        True, if the processor supports timer interrupts. The problem is 
> that the existing u-boots in many cases do not. I think that is really 
> the crux of the problem. So what are we going to do? I am open to ideas 
> here.

Which of the processors we're discussing here does not support timer
interrupts?  If there is any, how is the Linux system time implemented
on this processor?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
When properly administered, vacations do not  diminish  productivity:
for every week you're away and get nothing done, there's another when
your boss is away and you get twice as much done.  -- Daniel B. Luten

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  5:16                                                         ` Wolfgang Denk
@ 2011-05-26  5:25                                                           ` Graeme Russ
  2011-05-26  5:55                                                             ` Albert ARIBAUD
  2011-05-26  8:48                                                             ` Wolfgang Denk
  0 siblings, 2 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-26  5:25 UTC (permalink / raw)
  To: u-boot

On Thu, May 26, 2011 at 3:16 PM, Wolfgang Denk <wd@denx.de> wrote:
> Dear "J. William Campbell",
>
> In message <4DDDDF2E.8070602@comcast.net> you wrote:
>>
>> ? ? ? ?True, if the processor supports timer interrupts. The problem is
>> that the existing u-boots in many cases do not. I think that is really
>> the crux of the problem. So what are we going to do? I am open to ideas
>> here.
>
> Which of the processors we're discussing here does not support timer
> interrupts? ?If there is any, how is the Linux system time implemented
> on this processor?

Well, they all support timer interrupts - It's just that that support
is not supported in U-Boot (yet)

I think we can still rationalise the timer API as suggested which, as
a minimum will:

 - Not diminish current functionality for any platform
 - Will dramatically reduce the current amount of code duplication
 - Improve functionality on some platforms
 - Simplify the whole API

and then start banging on arch maintainers heads to implement the trivial
ISR to kick the prescaler:

void timer_isr(void *unused)
{
	prescaler();
}

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  5:25                                                           ` Graeme Russ
@ 2011-05-26  5:55                                                             ` Albert ARIBAUD
  2011-05-26  6:18                                                               ` Graeme Russ
  2011-05-26  6:36                                                               ` Reinhard Meyer
  2011-05-26  8:48                                                             ` Wolfgang Denk
  1 sibling, 2 replies; 101+ messages in thread
From: Albert ARIBAUD @ 2011-05-26  5:55 UTC (permalink / raw)
  To: u-boot

Le 26/05/2011 07:25, Graeme Russ a ?crit :

> I think we can still rationalise the timer API as suggested which, as
> a minimum will:
>
>   - Not diminish current functionality for any platform
>   - Will dramatically reduce the current amount of code duplication
>   - Improve functionality on some platforms
>   - Simplify the whole API
>
> and then start banging on arch maintainers heads to implement the trivial
> ISR to kick the prescaler:

I personally am in favor of cooperation rather than coercion, so please, 
ask before banging on heads. :)

> void timer_isr(void *unused)
> {
> 	prescaler();
> }
>
> Regards,
>
> Graeme

Seems like we're asymptotically getting to some kind of agreement. For 
the sake of clarity, could someone summarize what the expected API would 
be, so that I save my scalp and start looking as the order in which 
changes should be done on ARM?

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  5:55                                                             ` Albert ARIBAUD
@ 2011-05-26  6:18                                                               ` Graeme Russ
  2011-05-26  6:36                                                               ` Reinhard Meyer
  1 sibling, 0 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-26  6:18 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On Thu, May 26, 2011 at 3:55 PM, Albert ARIBAUD
<albert.u.boot@aribaud.net> wrote:
> Le 26/05/2011 07:25, Graeme Russ a ?crit :
>
>> I think we can still rationalise the timer API as suggested which, as
>> a minimum will:
>>
>> ?- Not diminish current functionality for any platform
>> ?- Will dramatically reduce the current amount of code duplication
>> ?- Improve functionality on some platforms
>> ?- Simplify the whole API
>>
>> and then start banging on arch maintainers heads to implement the trivial
>> ISR to kick the prescaler:
>
> I personally am in favor of cooperation rather than coercion, so please, ask
> before banging on heads. :)

What, and take all the fun out of it ;)

But yes, giving everyone plenty of warning was all in the plan

>> void timer_isr(void *unused)
>> {
>> ? ? ? ?prescaler();
>> }
>>
>> Regards,
>>
>> Graeme
>
> Seems like we're asymptotically getting to some kind of agreement. For the
> sake of clarity, could someone summarize what the expected API would be, so
> that I save my scalp and start looking as the order in which changes should
> be done on ARM?
>

Here is one I prepared earlier :)

http://lists.denx.de/pipermail/u-boot/2011-May/093290.html

I'll write up another formal specification for the API soon - Got a couple
of things on so it may be another day or two

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  5:55                                                             ` Albert ARIBAUD
  2011-05-26  6:18                                                               ` Graeme Russ
@ 2011-05-26  6:36                                                               ` Reinhard Meyer
  1 sibling, 0 replies; 101+ messages in thread
From: Reinhard Meyer @ 2011-05-26  6:36 UTC (permalink / raw)
  To: u-boot

Dear Albert ARIBAUD,
> Le 26/05/2011 07:25, Graeme Russ a ?crit :
> 
>> I think we can still rationalise the timer API as suggested which, as
>> a minimum will:
>>
>>   - Not diminish current functionality for any platform
>>   - Will dramatically reduce the current amount of code duplication
>>   - Improve functionality on some platforms
>>   - Simplify the whole API
>>
>> and then start banging on arch maintainers heads to implement the trivial
>> ISR to kick the prescaler:
> 
> I personally am in favor of cooperation rather than coercion, so please, 
> ask before banging on heads. :)
> 
>> void timer_isr(void *unused)
>> {
>> 	prescaler();
>> }
>>
>> Regards,
>>
>> Graeme
> 
> Seems like we're asymptotically getting to some kind of agreement. For 
> the sake of clarity, could someone summarize what the expected API would 
> be, so that I save my scalp and start looking as the order in which 
> changes should be done on ARM?

No, I don't think so. We currently have and need only two timer API functions
which are used in u-boot:

(1) void udelay(u32 microseconds)

and

(2) u32 get_timer(u32 base)

******************************************
I think we do not need to change that API.
******************************************

(maybe rename get_timer to get_timer_ms, but really why??)

What needs to be done is to eliminate all other timer functions that are
still used in some places (outside the timer domain) like get_ticks(),
set/reset_timer() and maybe other exotic ones.

And what needs to be fixed is all broken implementations of above TWO
functions.

Exactly how that fixing is done, and maybe generalized, factorized,
needlessly complicazed;), awkwardized;) should be another thread!

What should be specified for thsi API is in what time ranges above
functions MUST work, example: udelay() upto 1 second, get_timer
upto 1 year ;), and for reasons of implementation the maximum time
between two "related" get_timer calls.

Related in that sense means calls that are used to calculate a time difference
between them. Consider the following example:

since_epoch = get_timer(0);
while (get_timer(since_epoch) < timeout1)
	/* whatever1 */

/* other actions */

since_epoch = get_timer(0);
while (get_timer(since_epoch) < timeout2)
	/* whatever2 */

It does not matter whether the internal timer has had any wraps that
went undetected while "other actions" were executed.

And clearly, in all sane case, the "whatever" execution part cannot take
many seconds, so it is futile to think about any undetected wraps that need
tens of seconds or more to occur.

Best Regards,

Reinhard

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  5:25                                                           ` Graeme Russ
  2011-05-26  5:55                                                             ` Albert ARIBAUD
@ 2011-05-26  8:48                                                             ` Wolfgang Denk
  2011-05-26  9:02                                                               ` Graeme Russ
  1 sibling, 1 reply; 101+ messages in thread
From: Wolfgang Denk @ 2011-05-26  8:48 UTC (permalink / raw)
  To: u-boot

Dear Graeme Russ,

In message <BANLkTi=B1BRT-HR23xVPtOqufpdbiTxrRA@mail.gmail.com> you wrote:
>
> and then start banging on arch maintainers heads to implement the trivial
> ISR to kick the prescaler:

I guess a lot of my confusion could be removed if you could think of a
better name for this function.  For me a "prescaler" has a very
definitive meaning, and it is nothing you need to "kick".

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Men will always be men -- no matter where they are.
	-- Harry Mudd, "Mudd's Women", stardate 1329.8

^ permalink raw reply	[flat|nested] 101+ messages in thread

* [U-Boot] [RFC] Review of U-Boot timer API
  2011-05-26  8:48                                                             ` Wolfgang Denk
@ 2011-05-26  9:02                                                               ` Graeme Russ
  0 siblings, 0 replies; 101+ messages in thread
From: Graeme Russ @ 2011-05-26  9:02 UTC (permalink / raw)
  To: u-boot

On Thursday, May 26, 2011, Wolfgang Denk <wd@denx.de> wrote:
> Dear Graeme Russ,
>
> In message <BANLkTi=B1BRT-HR23xVPtOqufpdbiTxrRA@mail.gmail.com> you wrote:
>>
>> and then start banging on arch maintainers heads to implement the trivial
>> ISR to kick the prescaler:
>
> I guess a lot of my confusion could be removed if you could think of a
> better name for this function. ?For me a "prescaler" has a very
> definitive meaning, and it is nothing you need to "kick".

sync_timebase ?

Regards,

Graeme

^ permalink raw reply	[flat|nested] 101+ messages in thread

end of thread, other threads:[~2011-05-26  9:02 UTC | newest]

Thread overview: 101+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-21 12:38 [U-Boot] [RFC] Review of U-Boot timer API Graeme Russ
     [not found] ` <4DD7DB64.70605@comcast.net>
2011-05-22  0:06   ` Graeme Russ
2011-05-22  0:43     ` J. William Campbell
2011-05-22  4:26 ` Reinhard Meyer
2011-05-22  6:23   ` Graeme Russ
2011-05-22  7:21     ` J. William Campbell
2011-05-22  7:44       ` Graeme Russ
2011-05-22  8:15       ` Reinhard Meyer
2011-05-23  0:02         ` Graeme Russ
2011-05-23  0:20           ` J. William Campbell
2011-05-23  0:14         ` J. William Campbell
2011-05-23  1:00           ` Graeme Russ
     [not found]             ` <4DD9B608.7080307@comcast.net>
2011-05-23  1:42               ` Graeme Russ
2011-05-23  5:02                 ` J. William Campbell
2011-05-23  5:25                   ` Graeme Russ
2011-05-23  6:29                     ` Albert ARIBAUD
2011-05-23 10:53                       ` Graeme Russ
2011-05-23 16:22                       ` J. William Campbell
2011-05-23 12:09                 ` Wolfgang Denk
2011-05-23 12:29                   ` Graeme Russ
2011-05-23 13:19                     ` Wolfgang Denk
2011-05-23 17:30                       ` J. William Campbell
2011-05-23 18:24                         ` Albert ARIBAUD
2011-05-23 19:18                         ` Wolfgang Denk
2011-05-23 18:27                       ` J. William Campbell
2011-05-23 19:33                         ` Wolfgang Denk
2011-05-23 20:26                           ` J. William Campbell
2011-05-23 21:51                             ` Wolfgang Denk
2011-05-23 20:48                       ` Graeme Russ
2011-05-23  3:26           ` Reinhard Meyer
2011-05-23  5:20             ` J. William Campbell
2011-05-22  6:57   ` J. William Campbell
2011-05-23 12:13     ` Wolfgang Denk
2011-05-24  3:42 ` Mike Frysinger
2011-05-24  4:07 ` Graeme Russ
2011-05-24  4:24   ` Mike Frysinger
2011-05-24  4:35     ` Graeme Russ
2011-05-24  5:31       ` Reinhard Meyer
2011-05-24  5:43         ` Graeme Russ
2011-05-24  6:11           ` Albert ARIBAUD
2011-05-24  7:10             ` Graeme Russ
2011-05-24 14:15               ` Wolfgang Denk
2011-05-24 14:12             ` Wolfgang Denk
2011-05-24 15:23               ` J. William Campbell
2011-05-24 19:09                 ` Wolfgang Denk
2011-05-24 13:29           ` Scott McNutt
2011-05-24 14:19             ` Wolfgang Denk
2011-05-24 16:51               ` Graeme Russ
2011-05-24 18:59                 ` J. William Campbell
2011-05-24 19:31                   ` Wolfgang Denk
2011-05-24 19:19                 ` Wolfgang Denk
2011-05-24 22:32                   ` J. William Campbell
2011-05-25  5:17                     ` Wolfgang Denk
2011-05-25 16:50                       ` J. William Campbell
2011-05-25 19:56                         ` Wolfgang Denk
2011-05-25  0:17                   ` Graeme Russ
2011-05-25  2:53                     ` J. William Campbell
2011-05-25  3:21                       ` Graeme Russ
2011-05-25  5:28                       ` Wolfgang Denk
2011-05-25  6:06                         ` Graeme Russ
2011-05-25  8:08                           ` Wolfgang Denk
2011-05-25  8:38                             ` Graeme Russ
2011-05-25 11:37                               ` Wolfgang Denk
2011-05-25 11:52                                 ` Graeme Russ
2011-05-25 12:26                                   ` Wolfgang Denk
2011-05-25 12:42                                     ` Graeme Russ
2011-05-25 12:59                                       ` Wolfgang Denk
2011-05-25 13:14                                         ` Graeme Russ
2011-05-25 13:38                                           ` Wolfgang Denk
2011-05-25 21:11                                             ` Graeme Russ
2011-05-25 21:16                                               ` Wolfgang Denk
2011-05-25 23:13                                                 ` Graeme Russ
2011-05-26  0:15                                                   ` J. William Campbell
2011-05-26  0:33                                                     ` Graeme Russ
2011-05-26  4:19                                                   ` Reinhard Meyer
2011-05-26  4:40                                                     ` Graeme Russ
2011-05-26  5:03                                                       ` J. William Campbell
2011-05-26  5:16                                                         ` Wolfgang Denk
2011-05-26  5:25                                                           ` Graeme Russ
2011-05-26  5:55                                                             ` Albert ARIBAUD
2011-05-26  6:18                                                               ` Graeme Russ
2011-05-26  6:36                                                               ` Reinhard Meyer
2011-05-26  8:48                                                             ` Wolfgang Denk
2011-05-26  9:02                                                               ` Graeme Russ
2011-05-26  4:54                                                     ` J. William Campbell
2011-05-25  5:25                     ` Wolfgang Denk
2011-05-25  6:02                       ` Graeme Russ
2011-05-25  8:06                         ` Wolfgang Denk
2011-05-25  8:26                           ` Graeme Russ
2011-05-25 11:32                             ` Wolfgang Denk
2011-05-25 11:53                               ` Graeme Russ
2011-05-25 12:27                                 ` Wolfgang Denk
2011-05-25 12:36                 ` Scott McNutt
2011-05-25 12:43                   ` Graeme Russ
2011-05-25 13:08                     ` Scott McNutt
2011-05-25 13:16                       ` Graeme Russ
2011-05-25 13:46                         ` Scott McNutt
2011-05-25 14:21                           ` Graeme Russ
2011-05-25 19:46                             ` Wolfgang Denk
2011-05-25 20:40                               ` J. William Campbell
2011-05-25 20:48                                 ` Wolfgang Denk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.