[U-Boot] [RFC][Timer API] Revised Specification - Implementation details

Graeme Russ
2011-05-26T22:51:35Z

On Fri, May 27, 2011 at 3:49 AM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Graeme Russ,
>
> In message <4DDE5548.3020906@gmail.com> you wrote:
>>
>> Assumed Capabilities of the Platform
>> ?- Has a 'tick counter' that does not rely on software to increment
>
> I think we should delete the "does not rely on software to increment"
> part. It is not really essential.

I am sure there has been confusion with a misunderstanding the the
tick counter is NOT interrupt driven

>> ?- tick interval may by a fixed constant which cannot be controlled
>> ? ?via software, or it could be programmable (PIT)
>>
>> API Functions (/lib/timer.c)
>> ?- u32 get_timer(u32 start)
>> ? ? - Returns the number of elapsed milliseconds since 'start'
>
> If you really want to make the code flexible, then say
> ? ? ? ?"returns the number of "1/CONFIG_SYS_HZ" time units since
> ? ? ? ?'start'"
>
> ? ? ? ?The 1 ms resolution is actually tied to the CONFIG_SYS_HZ
> ? ? ? ?definition (which is the reason why I always fought that
> ? ? ? ?CONFIG_SYS_HZ must be defined as 1000).
>
> ? ? ? ?Of course we could also drop this definition completely...
>

I think we should - If CONFIG_SYS_HZ _MUST_ be 1000 anyway, what is the
point. Also, get_timer() utilisation as it stands for the most part already
assumes a 1ms time base. Maybe we should change get_timer() to
get_ms_timer() to avoid any ambiguity

>> API Functions (/arch/...)
>> ?- void udelay(u32 delay)
>> ? ? - Used for 'short' delays (generally up to several seconds)
>
> ? ? ? ?no. ?only good for delays well below one second.
>
>> ? ? - Can use the tick counter if it is fast enough
>> ? ? - MUST NOT RESET THE TICK COUNTER
>
> Should ne not state that the tick counter must never be reset during
> the life-time -f U-Boot?

Yes, I think you are right

> We should also note that neither get_timer() nor udelay() make any
> guarantee for the precision of the returned timing information, except
> that udelay(N) is always supposed to delay for _at_least_ N
> microseconds.

Correct

>> 'Helper' Functions (/lib/timer.c)
>> ?- void sync_timebase(void)
>
> Can be a macro (to avoid call overhead).

True

>> ? ? - Updates the millisecond timer
>
> We need to define that term.. Eventually you want to change the
> definition of get_timer() into "returns the content of the millisecond
> timer" or similar.
>
>> ? ? - Utilises HAL functions to access the platform's tick counter
>> ? ? - Must be called more often than the rollover period of the
>> ? ? ? platform's tick counter
>> ? ? - Does not need to be called with a regular frequency (immune
>> ? ? ? to interrupt skew)
>> ? ? - Is always called by get_timer()
>> ? ? - For platforms with short tick counter rollovers it should
>> ? ? ? be called by an ISR
>> ? ? - Bill Campbell wrote a good example which proved this can be common
>> ? ? ? and arbitrary (and optionally free of divides and capable of
>> ? ? ? maintaining accuracy even if the tick frequency is not an even
>> ? ? ? division of 1ms)
>>
>> HAL Functions (/arch/... or /board/...)
>> ?- u64 get_ticks(void)
>> ? ? - Returns a tick count as an unsigned 64-bit integer
>> ? ? - Abstracts the implementation of the platform tick counter
>> ? ? ? (platform may by 32-bit 3MHz counter, might be a 16-bit
>> ? ? ? 0-999 microsecond plus 16-bit 0-65535 millisecond etc)
>> ?- u64 ticks_per_millisecond()
>> ? ? - Returns the number of ticks (as returned by get_ticks()) per
>> ? ? ? millisecond
>
> I recommend to stick with the existing ticks2usec() and usec2ticks();
> you can then use usec2ticks(1000) to get the ticks per millisecond.

Can do - And that would mean a sync_us_timer() would call usec2ticks(1)

>> ?- void timer_isr()
>> ? ? - Optional (particularly if tick counter rollover period is
>> ? ? ? exceptionally log which is usually the case for native 64-bit tick
>> ? ? ? counters)
>> ? ? - Simply calls sync_timebase()
>> ? ? - For platforms without any tick counter, this can implement one
>> ? ? ? (but accuracy will be harmed due to usage of disable_interrupts() and
>> ? ? ? enable_interrupts() in U-Boot
>>
>> So to get the new API up and running, only two functions are mandatory:
>>
>> get_ticks() which reads the hardware tick counter and deals with any 'funny
>> stuff' including rollovers, short timers (12-bit for example), composite
>> counters (16-bit 0-999 microsecond + 16-bit millisecond) and maintains a
>> 'clean' 64-bit tick counter which rolls over from all 1's to all 0's. The
>> 64-bit tick counter does not need to be reset to zero ever (even on startup
>> - sync_timebase tacks care of all the details)
>>
>> ticks_per_millisecond() simply return the number of ticks in a millisecond
>> - This may as simple as:
>>
>> inline u64 ticks_per_millisecond(void)
>> {
>> ? ? ? return CONFIG_SYS_TICK_PER_MS;
>> }
>
> Better move this part up to the description of usec2ticks() / ticks2usec().

OK

Regards,

Graeme