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

Bernard Fouché bernard.fouche at kuantic.com
Tue Jul 15 11:04:18 CEST 2008


What about:

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

This because:

- If 'ms' is 'big', and if the compiler evaluates the multiplication first, then an overflow can happen.

- since NutGetTickClock() gives a result in 'ticks per Hertz' then it seems more appropriate to reduce 'ms' to a value in seconds before the next calculation.

    Bernard

Henrik Maier wrote:
> There has be some discussion about a better implementation and bug-fix of
> NutTimerMillisToTicks (refer to posts in 2006, subject "Request for Comment:
> NutTimerMillisToTicks()").
>
> This has been applied in recent Nut/OS releases (>4.2.1 onwards).
>
> However the current implementation does only round for the special case when
> the result would be 0 (see if clause below). However for other cases with
> small ms values it does not round at all and we end up with large errors
> (50%) for small ms values in cases where NutGetTickClock() is just below
> 1000, for example 997. For clock frequencies where NutGetTickClock() is
> greater than 1000 it does not matter but for cases where it is less than
> 1000 it results in unnecessary inaccuracies. 
>
> I came across this issue when recently upgrading from Nut/OS 4.2.1 to 4.4.1
> and some of my time-out calculations did not work anymore as they were too
> short.
> 	
>
> Current implementation:
> -----------------------
>
> u_long NutTimerMillisToTicks(u_long ms)
> {
>     u_long x;
>     
>     x = ms * NutGetTickClock() / 1000UL;
>     if (x == 0) {
>         x = 1;
>     }
>     
>     return (x);
> }
>
> [..snip..]
>
> Suggested implementation:
> -------------------------
> u_long NutTimerMillisToTicks(u_long ms)
> {
>     return (ms * NutGetTickClock() + 500) / 1000UL;
> }
>   



More information about the En-Nut-Discussion mailing list