[En-Nut-Discussion] NutGetMillis overflow

José Vallet jose.vallet at hut.fi
Wed Nov 2 11:55:13 CET 2005


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é

Brett Abbott wrote:
> 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.
> José Vallet wrote:
> 
>> 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-Discussion at egnite.de
>> http://www.egnite.de/mailman/listinfo.cgi/en-nut-discussion
>>
>>
> 





More information about the En-Nut-Discussion mailing list