public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Graeme Russ <graeme.russ@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [RFC] Review of U-Boot timer API
Date: Sun, 22 May 2011 16:23:15 +1000	[thread overview]
Message-ID: <4DD8ABD3.2070506@gmail.com> (raw)
In-Reply-To: <4DD8908E.7040501@emk-elektronik.de>

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

  reply	other threads:[~2011-05-22  6:23 UTC|newest]

Thread overview: 101+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DD8ABD3.2070506@gmail.com \
    --to=graeme.russ@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox