[En-Nut-Discussion] NutGetMillis overflow

5 views
Skip to first unread message

José Vallet

unread,
Nov 1, 2005, 11:09:45 AM11/1/05
to Ethernut mail list
Hello. First of all, I am novice NUT/OS user, just in case ;-)

I need to controll a process on real time, so I need to time-stamp some
measurements. A precission of milliseconds seems to be good enough, so
the function NutGetMillis suits me. Checking the code I saw that it
returns a 32 bits value. However the comments of the function suggest
something different. Then, either there are some "mistakes" in the
comments or I am missing somethig...

In the comments it is suggested that the tick counter overflows every
7.9 years, and I think that that is wrong:

the variable nut_ticks is defined as u_long, so 32 bits. Thus it can
count up to 4294967296 ticks. With a default tick rate of 1024 tics/s,
we can count a maximum of 4294967296/1024=4194304 seconds, which is
1165.084 hours, which is about 48.5 days, not 7.9 years!! This value is
important to my application, so it doesn't start to make weird things
after 48 days... (now I start to understand the "terrible year 2k
effect" ;-))

Thus, the upper bound of milliseconds returned by the function is
4194304000 that fits in a 32 bit number. Actually the returned value is
a 32 bit value (u_long), not a 64 bit value as the comments suggests.

So, now I wonder if I am missing something or is it so that the comment
is the result of a copy-paste-remake-and-re-bake and forgot to update?
;-) Look at that scary line with the comment:

// carefully stay within 64 bit values

I enclose the function in the following lines.

Regards.
José




/*!
* \brief Return the milliseconds counter value.
*
* This function returns the value of a counter, which is incremented
* every system timer tick. During system start, the counter is cleared
* to zero and will overflow with the 64 bit tick counter (4294967296).
* With the default 1024 ticks/s this will happen after 7.9 years.
* The resolution is also given by the system ticks.
*
* \note There is intentionally no provision to modify the seconds counter.
* Callers can rely on a continuous update and use this value for
* system tick independend timeout calculations.
* Depending on
*
* \return Value of the seconds counter.
*/
u_long NutGetMillis(void)
{
// carefully stay within 64 bit values
u_long ticks = NutGetTickCount();
u_long seconds = ticks / NutGetTickClock();
ticks -= seconds * NutGetTickClock();
return seconds * 1000 + (ticks * 1000 ) / NutGetTickClock();
}

_______________________________________________
En-Nut-Discussion mailing list
En-Nut-D...@egnite.de
http://www.egnite.de/mailman/listinfo.cgi/en-nut-discussion

Brett Abbott

unread,
Nov 1, 2005, 12:15:27 PM11/1/05
to Ethernut User Chat (English)
Jose

According to the Imagecraft help page, unsigned long (u_long) is 4
bytes. I am unsure of whether this is the same in gcc or how consistent
C compilers are across various platforms. It would be useful to know if
gcc matches the ICC implementation.

If you use ICCAVR, search on "Data Type Size". Hopefully with
Imagecraft's permission, I include the help page notes below to allow a
comparison with gcc.

It's good to see you looking so closely at the code, this will see you
do well.

Cheers
Brett

TYPE SIZE (bytes) RANGE
unsigned char 1 0..255
signed char 1 -128..127
char (*) 1 0..255
unsigned short 2 0..65535
(signed) short 2 -32768..32767
unsigned int 2 0..65535
(signed) int 2 -32768..32767
pointer 2 N/A
unsigned long 4 0..4294967295
(signed) long 4 -2147483648..2147483647
float 4 +/-1.175e-38..3.40e+38
double 4 +/-1.175e-38..3.40e+38
(*) "char" is equivalent to "unsigned char"
floats and doubles are in IEEE standard 32-bit format with 8 bit
exponent, 23-bit mantissa and 1 sign bit.
Bitfield types must be either signed or unsigned but they will be packed
into the smallest space. For example:

struct {

unsigned a : 1, b : 1;

};

Size of this structure is only 1 byte. Bitfields are packed right to left.
--
-----------------------------------------------------------------
Brett Abbott, Managing Director, Digital Telemetry Limited
Email: Brett....@digital-telemetry.com
PO Box 24 036 Manners Street, Wellington, New Zealand
Phone +64 (4) 5666-860 Mobile +64 (21) 656-144
------------------- Commercial in confidence --------------------

José Vallet

unread,
Nov 2, 2005, 5:55:13 AM11/2/05
to Brett....@digital-telemetry.com, Ethernut User Chat (English)
Hello Brett, and thanks for the fast answer.

In the file timer.h, where the function NutGetMillis is defined, we can
find the following include
#include <sys/types.h>

From /include/sys/types.h we get:

/*! \brief Unsigned 32-bit value */
typedef unsigned long u_long;

and from stdint.h (avrlibc) we get

typedef unsigned long uint32_t

/** \ingroup avr_stdint
32-bit unsigned type. */
typedef unsigned long uint32_t;

So I think gcc uses also 32 bits, which is 4 bytes.

32 bits count up to 4294967295, yes. The point is that, with a tick rate
of 1024ticks/sec and with 32 bits to count ticks we are able to count a
maximum of 194304 seconds, which is 1165.084 hours, so about 48.5 days,
not 7.9 years as it is suggessted in the comments of the code
(documentation). So either I am missing something or I think that the
comments are wrong and, perhaps, could be changed? (shy suggestion).

Regards
José
Reply all
Reply to author
Forward
0 new messages