[U-Boot] [RFC] Review of U-Boot timer API

Graeme Russ
2011-05-24T07:10:05Z

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