Hi Wolfgang On Thu, May 26, 2011 at 7:16 AM, Wolfgang Denk <w...@denx.de> wrote: > Dear Graeme Russ, > > In message <4ddd7066.4000...@gmail.com> you wrote: >> >> > No, not at all. And I already answered this. For example on PPC, just >> > reading the timebase would be perfectly sufficient, and simpler and >> > more reliable than the current interrupt based approach. >> >> I assume by 'timebase' you mean the 64-bit tick counter. If so, that is > > By timebase I mean the timebase register, implemented as two 32 bit > registers tbu and tbl, holding the upper and the lower 32 bits of the > free-running 64 bit counter, respective.
And remember, not all platforms have this implementation. The AMD sc520 for example has a microsecond register which counts 0-999 that ticks a 16-bit millisecond register and resets to zero. And the millisecond register latches the value of the microsecond register and resets (the millisecond register) back to zero. The thing is, this can all be abstracted away via get_tick() which (provided it is called every 65 seconds or so) can maintain a software version of the timebase register. So, every 65 seconds, the prescaler needs to be kicked. Now, if all we want to use get_timer() for is to monitor a timeout (which I think might be every single use in U-Boot to date) then the while (get_timer(start) < timeout) loop will work. If get_timer() is needed to measure time between two arbitrary events (which I 100% agree it should be able to do) then the prescaler will need to be kicked (typically by an interrupt) > >> _exactly_ what I am suggesting we do (and what does already happen on ARM). > > I don't think so. On closer inspection, some do, some don't. All ARMv7 (OMAP, S5P, Tegra2) do. at91 is odd - It looks like it uses interrupts, but get_timer() and udelay() both end up calling get_timer_raw() (with udelay only having millisecond resolution it seems). Some others can be configured to increment the timer using an interrupt. ARM is, quite frankly, a complete mess - It has a mass of *_timer_masked() functions which the core timer functions are 'wafer thin' wrapper around, udelay() silently resets the timebase trashing get_timer() loops etc. So let's wind back and distill the approach I am suggesting: 1) A common prescaler function in /lib/ - It's purpose is to maintain a 1ms resolution timer (if the platform cannot otherwise do so)[1] The prescaler utilises a platform provided get_ticks()[2] 2) A get_ticks() function provided by the platform - This function must return an unsigned counter which wraps from all 1's to all 0's - It DOES NOT have to be initialised to zero at system start. get_ticks() hides the low-level tick counter implementation - The sc520 example above is a classic example, so is your PPC tbu/tbl example. 3) [Optional]An ISR which calls the prescaler[3] Now there is an optimisation if your tick counter has a 1ms resolution and is not small (i.e. 64-bits) - The prescaler is defined weak, so in the platform code, re-implement the prescaler to simply copy the tick counter to the timer variable. And what are the specific implementation types (in decending order of preference)? I think: 1) A 64-bit micro-second tick counter[5] - No interrupts needed - Can be used by udelay() and get_timer() trivially 2) A 64-bit sub-micro-second tick counter - Interrupts most likely undeeded unless the tick frequency is insanely high - Can be used by udelay() and get_timer() trivially 3) A 64-bit milli-second tick counter - No interrupts needed - No prescaler needed - Can be used by get_timer() trivially - udelay() needs another tick source (if available) or be reduced to millisecond resolution 4) A 32-bit milli-second tick counter - No prescaler needed[6] - Max 'glitch free' duration is ~50 days - ISR needed to kick prescaler if events longer than 50 days need to be timed - Can be used by get_timer() trivially - udelay() needs another tick source (if available) or be reduced to millisecond resolution 5) A 24-bit milli-second tick counter - No prescaler needed[6] - Max 'glitch free' duration is ~4.5 hours - ISR needed to kick prescaler if events longer than 4.5 hours need to be timed - Can be used by get_timer() trivially - udelay() needs another tick source (if available) or be reduced to millisecond resolution 6) A 32-bit micro-second tick counter - No prescaler needed[6] - Max 'glitch free' duration is 71 minutes - ISR needed to kick prescaler if events longer than 71 minutes need to be timed - Can be used by get_timer() trivially - udelay() needs another tick source (if available) or be reduced to millisecond resolution Any implementation which does not fit withing the above is going to require an ISR to kick the prescaler in order to support timing of 'long events' (i.e. not just simple timeout loops) [1]The prescaler would still be needed by platforms which has a 64-bit tick counter which ticks at a rate greater than 1ms [2]Exposing get_ticks() reduces code duplication [3]Only required if the rollover time of the tick counter (i.e. the maximum permissible time between any two get_ticks() calls) is 'small'[4] [4]'small' is at the discretion of the implementer - 1 second is always small, 1 hour might be, 500 years is not [5]A tick counter is something maintained by the underlying platform independent of any U-Boot code [6]Although wise to override the prescaler function so the timer ISR is consistent with all other platforms Regards, Graeme _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot