Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

gettimeofday

Altera_Forum
Honored Contributor II
1,380 Views

Has anyone had any trouble with using gettimeofday? I have been having a problem where the tv_usec value will rollover however the tv_sec value does not rollover. It does eventually but not when I expect it to? Is there any gotcha I should look out for? 

 

Thanks for your input, 

Chris F.
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
469 Views

Ok. I found the problem. Here is the NIOS II code for gettimeofday() (located in alt_gttod.c: 

 

/* 

* Macro defining the number of microseconds in a second. 

*/ 

# define ALT_US (1000000) 

 

int ALT_GETTIMEOFDAY (struct timeval *ptimeval, struct timezone *ptimezone) 

alt_u32 nticks = alt_nticks ();  

alt_u32 tick_rate = alt_ticks_per_second (); 

 

/*  

* Check to see if the system clock is running. This is indicated by a  

* non-zero system clock rate. If the system clock is not running, an error 

* is generated and the contents of "ptimeval" and "ptimezone" are not 

* updated. 

*/ 

 

if (tick_rate) 

ptimeval->tv_sec = alt_resettime.tv_sec + nticks / tick_rate; 

ptimeval->tv_usec = alt_resettime.tv_usec + (((nticks * ALT_US) / tick_rate) % ALT_US); 

 

if (ptimezone) 

{  

ptimezone->tz_minuteswest = alt_timezone.tz_minuteswest; 

ptimezone->tz_dsttime = alt_timezone.tz_dsttime; 

 

return 0; 

 

return -ENOTSUP; 

 

There is a fundamental problem with the way it calculates microseconds. In fact it only works right if nticks is less than ~4000 (if your tick_rate is 1000 for example). 

 

In fact the tv_usec and tv_sec use the alt_u32 variable type. This is 32 bit unsigned integer. It has a maximum value of 4,294,967,295 so pretty much 4 billion. So using the above code the first part of the usec calculation (nitcks * ALT_US) [4294 * 1000000 = 4,294,000,000 ... as soon as you hit 4295 the thing will overflow... and the math will be wrong] will overflow the 32 bit unsigned integer type at 4294 ticks have gone by. Folks... that is 4 seconds! Not very long at all! The person who coded this thought about this a little bit in that he/she added the modulous of ALT_US.... this only works well for nticks less than 1 second. The results of this can be seen by looking at the tv_usec ... you will find that you get values in the microseconds range with a (typical - default) 1 millisecond tick resolution... I asked myself where did those come from ... incorrect calculations... that is where they come from. Otherwise... using proper calculations, you will never get any value other than 000 for microseconds. 

 

I find that the best solution to the problem is to remove the number of seconds from the nticks first. That way the nticks is never over 1,000,000. This well never exceed the 32 bit unsigned integer value. 

 

Here is my revised code for gettimeofday(): 

 

int ALT_GETTIMEOFDAY (struct timeval *ptimeval, struct timezone *ptimezone) 

alt_u32 nticks = alt_nticks ();  

alt_u32 tick_rate = alt_ticks_per_second (); 

 

/*  

* Check to see if the system clock is running. This is indicated by a  

* non-zero system clock rate. If the system clock is not running, an error 

* is generated and the contents of "ptimeval" and "ptimezone" are not 

* updated. 

*/ 

 

if (tick_rate) 

alt_u32 seconds; 

alt_u32 safe_ticks; 

 

seconds = nticks / tick_rate; 

ptimeval->tv_sec = alt_resettime.tv_sec + seconds; 

safe_ticks = nticks - (seconds * tick_rate); 

ptimeval->tv_usec = alt_resettime.tv_usec + ((safe_ticks * ALT_US) / tick_rate); 

 

if (ptimezone) 

{  

ptimezone->tz_minuteswest = alt_timezone.tz_minuteswest; 

ptimezone->tz_dsttime = alt_timezone.tz_dsttime; 

 

return 0; 

 

return -ENOTSUP; 

 

If anyone has any suggestions/comments/criticism ... all is appreciated. Some comments on code optimization would be nice! 

 

I have posted this here first so everyone will know about it. Altera tech support is a pain to report bugs to, however I will be submitting a bug report to them.
0 Kudos
Altera_Forum
Honored Contributor II
469 Views

Altera support got back with me and confirmed this a bug to be fixed in v7.2. Anyone using the gettimeofday() function for anything using the tv_usec value, I suggest you write your own or patch the HAL source code in order for your software to work properly.

0 Kudos
Reply