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

Graeme Russ
2011-05-26T13:27:36Z

Hello Everyone,

OK - Starting a new thread to discuss implementation details. This is a
heads-up for arch/platform maintainers - Once this is a bit more stable, I
will put it on the wiki

Assumed Capabilities of the Platform
- Has a 'tick counter' that does not rely on software to increment
- 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'

API Functions (/arch/...)
- void udelay(u32 delay)
- Used for 'short' delays (generally up to several seconds)
- Can use the tick counter if it is fast enough
- MUST NOT RESET THE TICK COUNTER

'Helper' Functions (/lib/timer.c)
- void sync_timebase(void)
- Updates the millisecond timer
- 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
- 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;
}

But it may be trickier if you have a programmable tick frequency

The optional timer ISR is required if the tick counter has a short roll
over duration (short is up to you - 1 second is short, 1 hour might be, 1
century is not)

Regards,

Graeme