[En-Nut-Discussion] NutGetTickClock rounding (again)

Henrik Maier hmlists at focus-sw.com
Thu Jul 17 08:42:00 CEST 2008


Bernhard,

> equals or closes to 1000. I also share Duane's point of view: the return
> value must never be inferior to the 'real' expected value. Typical

I agree with that view as well. That's the reason I started the discussion
in the first place as the current AVR implementation returns exactly an
inferior value. So far I focused only on my use case where Hz is < 1000. But
this discussion made me aware that there is also a present issue for the
default use case of Hz > 1000. The error is smaller so the side-effect is
less visible and I guess this is the reason it wasn't picked up so far.

> example: having to wait for at least 5ms before writing again into an
> I2C addressed EEPROM. If I call the function with the value 5(ms) and
> the system ticks @997Hz, then I want the value 6(ticks) to be returned
> and not 5(ticks).

Are you sure you want to wait 6 ticks for 997 Hz ? At 997 Hz a tick is
actually longer than 1 ms, it is 1.003 ms. Your EEPROM wait time would be
satisfied with 5 ticks = 5.015 ms.

For a parameter of 5 ms the current implementation in ostimer.c (see below)
returns 4 for 997 Hz and for the Ethernut standard clock of 1024 Hz it
returns 5.

u_long NutTimerMillisToTicks(u_long ms)
{
    u_long x;
    
    x = ms * NutGetTickClock() / 1000UL;
    if (x == 0) {
        x = 1;
    }
    
    return (x);
}

So in the standard Ethernut case (1024Hz) if we waited 5 ticks, we actually
waited 4.88 ms. So a bit less than we expected. Based on previous
discussions from yourself and Duane I understand the function should round
up to 6 ticks in this case which is exactly what the Linux calculation would
do.

> If the Linux calculation is fine, then let's take it: anyway, if the

So are we then back to the following implementation proposal, which is the
generic case of Linux' msecs_to_jiffies function?

---------------------------------------------------
u_long NutTimerMillisToTicks(u_long ms)  
{
   if (ms >= 0x3E8000UL)
      return (ms / 1000UL) * NutGetTickClock();
   else
      return (ms * NutGetTickClock() + 999UL) / 1000UL;  
}
-----------------------------------------------------

PS: I still have no idea where the magic value of 0x3E8000UL comes from.

> tick count function expands to a constant, conditional compilation and
> the optimizer will reduce the instruction count. If the tick count is

For the AVR implementation NutGetTickClock() is constant. For the AT91 ARM
implementation it is not.
 
Henrik





More information about the En-Nut-Discussion mailing list