[En-Nut-Discussion] NutGetTickClock rounding (again)
Henrik Maier
hmlists at focus-sw.com
Wed Jul 16 03:17:32 CEST 2008
Not a solution to the problem. This code also suffers from the same rounding
issue as the AVR code. The only difference is that is deals better with the
overflow.
Example:
ms = 2
NutGetTickClock = 997
Result is: 1, a 50 % error.
And this error is avoidable by applying standard rounding procedures.
Henrik
> -----Original Message-----
> From: en-nut-discussion-bounces at egnite.de [mailto:en-nut-discussion-
> bounces at egnite.de] On Behalf Of ennut at thezachariasgroup.com
> Sent: Tuesday, 15 July 2008 10:49 PM
> To: Ethernut User Chat (English)
> Subject: Re: [En-Nut-Discussion] NutGetTickClock rounding (again)
>
> In the ARM arch the following code works well:
>
> /*!
> * \brief Calculate system ticks for a given number of milliseconds.
> */
> u_long NutTimerMillisToTicks(u_long ms) {
> if (ms >= 0x3E8000) {
> return (ms / 1000) * NutGetTickClock();
> }
> else {
> return (ms * NutGetTickClock()) / 1000;
> }
> }
>
>
> At 07:11 AM 7/15/2008, you wrote:
> >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
> >
> >_______________________________________________
> >http://lists.egnite.de/mailman/listinfo/en-nut-discussion
>
> _______________________________________________
> http://lists.egnite.de/mailman/listinfo/en-nut-discussion
More information about the En-Nut-Discussion
mailing list