[U-Boot] [RFC] ARM timing code refactoring
J. William Campbell
jwilliamcampbell at comcast.net
Mon Jan 24 17:23:34 CET 2011
On 1/24/2011 5:02 AM, Wolfgang Denk wrote:
> Dear Albert ARIBAUD,
>
> In message<4D3D2942.4060600 at free.fr> you wrote:
>> That is assuming a 64-bit timebase, isn't it? for CPUs / SoCs that don't>
>> have such a timebase but only a 32-bit timer, the bogo_ms/jiffy would>
>> not go through the full 32-bit range, which would cause issues with the>
>> timing loops on rollover -- and while a timeout of more than 65 sec may>
>> not be too likely, a timeout starting near the wraparound value of>
>> bogo_ms still could happen.
Hi All,
If you use my approach of shifting right by n bits (in order to
get a counter that has "about" 1 ms resolution), zeros are shifted into
the top. The counter would never reach more than (32-n) bits in
magnitude. This is easily fixed by creating a "virtual" n msbs for the
counter, as must be done if a 64 bit counter is to be simulated.
Actually, I only need "n" bits, but in any case it requires detecting
that the counter has "backed up" mod 32 bits and if so, increase the
virtual counter by 1.
If you really, really, really want a timer that "ticks" at a 1 ms rate,
instead of bogo_ms/jiffies, I propose the following:
u32 get_time()
{
u32 delta_t_bogo_ms;
u32 t_save;
#if defined(TIMER_IS_64_BITS)
u64 tick;
read(&tick);
t_save = tick >> gd->timer_shift;
delta_t_bogo_ms = t_bogo_ms - gd->prev_timer;
#else
read(t_save);
delta_t_bogo_ms = (t_save - gd->prev_timer) >> gd->timer_shift;
#endif
gd->prev_timer = t_save; /* save previous counter */
if (delta_t_bogo_ms < gd->bogo_ms_per_65_sec)
{
gd->fract_timer += delta_t_bogo_ms *
gd->cvt_bogo_ms_to_ms; /* accumulate fraction of ms */
gd->timer_in_ms += gd->fract_timer >> 16;
gd->fract_timer &= 0X0000FFFF;
}
else
gd->fract_timer = 0; /* start accumulating from 0 fraction */
return(gd->timer_in_ms)
}
This routine will create a timer in ms, that will be
accurate as long as this routine is called either once about ever 65
seconds or once per time base rollover, whichever is less. Nested timer
use is ok. If the timer is not called frequently enough, it will return
the same value twice, but after that it will start timing normally. This
shouldn't matter, as the second returned value will be the start of a
timing loop. Timeout values can be the full 32 bits, as long as you keep
calling the routine frequently enough. No initialization is required.
Note that you can (and probably should) use the bottom 32
bits of the hardware timebase as a 32 bit timebase unless the clock
would overflow in 65 seconds (running faster than about 66 MHz), or if
you want to relax the 65 seconds.
If you want to save a word in the gd data, use 0X10000 instead of
bogo_ms_per_65_sec (or a more precise value if you know it). Note that
gd->timer_shift and gd->cvt_bogo_ms_to_ms can also be replaced by
constants if the clock speed is fixed.
This is more expensive than using the bogo_ms timer, but does have the
advantage that everything is in ms. FWIW, I think converting from ms to
some other unit for loop control is fine, as long as we have a standard
routine to do that that is "cheap". However, others may not agree. For
sure, passing around 64 bit tick values to do this process is, IMHO,
vast overkill and not a good general solution, as many processors really
don't like to do 64 bit operations.
Best Regards.
Bill Campbell
> Sorry, but I don't get it. What exactly is the problem with a 32 bit
> counter, and why would it not go through the full 32-bit range?
>
> Best regards,
>
> Wolfgang Denk
>
More information about the U-Boot
mailing list