
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.
- 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...
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?
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.
'Helper' Functions (/lib/timer.c)
- void sync_timebase(void)
Can be a macro (to avoid call overhead).
- 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.
- 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().
Best regards,
Wolfgang Denk