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

Henrik Maier hmlists at focus-sw.com
Tue Jul 15 13:11:05 CEST 2008


Bernhard,

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

The problem with the current implementation is not an overflow issue but a
rounding issue. It is simply a matter of applying proper rounding to an
integer division. An overflow issue only occurs if "ms" is > 49.7 days (for
a typical NutGetTickClock of ~1000).

However it is probably a good suggestion to document the potential overflow
for NutTimerMillisToTicks and add a caveat to its documentation. 

However my concern with function NutTimerMillisToTicks is small values for
the "ms" parameter, values between 1 and 10 ms for example.

> - 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.

In theory this is correct, but as we don't have floating point math,
impracticable.

Your implementation would return 1 for all ms values < 1000 as anything
smaller than 1000 divided by 1000 equals to 0 in integer land.

Henrik

> -----Original Message-----
> From: en-nut-discussion-bounces at egnite.de [mailto:en-nut-discussion-
> bounces at egnite.de] On Behalf Of Bernard Fouché
> Sent: Tuesday, 15 July 2008 7:04 PM
> To: Ethernut User Chat (English)
> Subject: Re: [En-Nut-Discussion] NutGetTickClock rounding (again)
> 
> 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;
> > }
> >
> _______________________________________________
> http://lists.egnite.de/mailman/listinfo/en-nut-discussion




More information about the En-Nut-Discussion mailing list