Timestamps w/ higher res than a second

Discussion to talk about software related topics only.
Post Reply
Ridgeglider
Posts: 513
Joined: Sat Apr 26, 2008 7:14 am

Timestamps w/ higher res than a second

Post by Ridgeglider »

I need to timestamp events to a resolution of mSec, perhaps hundredths of a sec at the least. However most of the NB time resources (NTP, RTC, Secs, calling time(NULL) ) have resolution of only a second. I'm looking for an alternative. I can live with the inherent drift due to oscillator as main use for timestamping is to calc time differences between nearby events. Could easily periodically compare or resync to new NTP readings if needed to gauge drift

One way might be to set up a PIT or DMA timer with the appropriate resolution (.01 or .001 secs) and use it to increment a count. Next, update the system time via NTP and record the result after calling

Code: Select all

time(NULLL)
which will now be offset to UNIX time with a resolution of seconds. Immediately after getting NTP time, zero my fractional tick count. Timestamp by recording both the (never changing) base time, and the (constantly updating) tick count offset from that base. The downside here is that the fractional part is not synced to the rest of the world.

A second way might be to modify the GetNTPTime function which appears to get (but not report) the fractional seconds. Modify it to also report the fractional seconds and store both 32 bit Secs and FractionalSecs variables in a struct. Scale the FractionalSecs to the tick count ISR resolution. Then, in the ISR (PIT or DMA timer) increment the scaled FractionalSecs, and, when needed the Secs. This would be a closer analog to the NTP scheme...

Thoughts? Hard to believe this hasn't been done before. If anyone has utilities to do this and to read/print the results, I'd be interested.
Thanks!
User avatar
Forrest
Posts: 288
Joined: Wed Apr 23, 2008 10:05 am

Re: Timestamps w/ higher res than a second

Post by Forrest »

TimeTick by default ticks off 50ms accuracy. You can increase it to 5ms by changing
#define TICKS_PER_SECOND (20)

to
#define TICKS_PER_SECOND (200)

200 is a good limit before you start seeing degraded performance.

For even finer resolution, see the pit timer example. The help file is in the tech docs section. http://www.netburner.com/support/techni ... ments.html
Forrest Stanley
Project Engineer
NetBurner, Inc

NetBurner Learn Articles: http://www.netburner.com/learn
Ridgeglider
Posts: 513
Joined: Sat Apr 26, 2008 7:14 am

Re: Timestamps w/ higher res than a second

Post by Ridgeglider »

Hi Forrest:
I've always shied away from messing with TICKS_PER_SECOND; I'm so used to having it at 50mSec. I could live with it at 10mSec. Sounds like the performance hit would be considerably less than keeping TICKS_PER_SECOND at the default and also having a 2nd, simultaneous PIT runing at 10 mSec, let alone 1 mSec.

If I modify constants.h and rebuild the system files, is there a way to limit the change to a specific project? One reason I hate to mess with modifying constants.h is that I don't want the changes to impact all the projects going way back. Is there a way to inlcude a local version of constants.h that is only seen in a given project?

That said, I've often editted contstants.h to add/change longfilenames, task prios, number of tasks, buffer sizes, etc but it would be great to know how to limit these changes to specific projects. Is it as simple as putting a copy of constants.h in the project and rebuilding the system? I somehow don't think so...

I'm familiar w/ the PIT & DMA timer ISRs and use them often. Thanks.
rnixon
Posts: 833
Joined: Thu Apr 24, 2008 3:59 pm

Re: Timestamps w/ higher res than a second

Post by rnixon »

I would use the PIT or other timer. Changing the whole system RTOS clock would b a last resort due to the overhead, and the fact it would affect every other project.
User avatar
lgitlitz
Posts: 331
Joined: Wed Apr 23, 2008 11:43 am
Location: San Diego, CA
Contact:

Re: Timestamps w/ higher res than a second

Post by lgitlitz »

You should modify the NTP code to save the fractional value when you sync. I would then likely just use the NTP sync time as an offset of a hardware timer that you zero each NTP time retrieval.

I posted a stopwatch utility that uses the DMA timer a few weeks ago (http://forum.embeddedethernet.com/viewt ... ?f=7&t=397). You just add this to your app and you can call simple stopwatch routines for your timer.... start, stop and clear, readtime. The precision is the fastest possible for the processor and there is a software overflow register so the overflow time is a few millenniums away. Another possibility is to use the DWORD GetPreciseTime( void ) function from the bsp.c. I have not experimented with this one but it uses the running count from the OS hardware timer for a much higher precision tick count. This is only a 32-bit value so it will overflow more often and each tick does not equal a nice whole time unit like the normal OS ticks.

Modifying the system ticks can cause some unexpected effects to your application so be careful if you go that route. If you are using any OS functions and have the timeout parameter set with a constant instead of the TICKS_PER_SECOND variable then the timeouts will be faster. Like others have mentioned, increasing TICKS_PER_SECOND will also increase the OS CPU load. Realize that the TICKS_PER_SECOND variable is the number of times per second a hardware timer interrupt is triggered. Each time this interrupt is serviced the OS scheduler will check if any timeouts have occurred. If there is no timeout then this happens rather quickly but it still will have to spend at least 2 context switch times for each tick.
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Timestamps w/ higher res than a second

Post by tod »

A little while back I discovered there was a BspGetTickFraction(); call. Below is an example of how I use it.
The only problem was figuring out what it was a fraction of.

Code: Select all

#include <Bsp.h>
	float Timer::GetTimeInTicks() const
	{
		float fract_tick_count = BspGetTickFraction();
		float tick_fraction = fract_tick_count / _maxFractionalCount;
		float real_tick_count = static_cast<float> (TimeTick) + tick_fraction;
		return real_tick_count;
	}
These two methods (and some others) are in a small timer class that contains the private member var _maxFractionalCount. The constructor for the Mod5272 initializes this to 39062. I determined this empirically by running the following quick and dirty method a number of times. I assume the number will change for different platforms and for different values of TICKS_PER_SECOND. The nice thing about this approach is you don't have to rebuild the system files and it seems to incur very little overhead.

Code: Select all

	uint32_t Timer::SetMaxFractionalCount()
	{
		int max_frac = 0;
		for (int i = 0; i < 100000; ++i)
		{
			WORD fract_tick_count = BspGetTickFraction();
			if (fract_tick_count > max_frac) max_frac = fract_tick_count;
		}
		cout << "Max fractional count:" << max_frac << endl;
		_maxFractionalCount = max_frac;
		return max_frac;

	}
Post Reply