[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