[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